view release on metacpan or search on metacpan
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
operating system's default device. If you have multiple physical devices connected and you want to
use a specific one you will need to specify the device ID in the configuration, like so:
```c
config.playback.pDeviceID = pMyPlaybackDeviceID; // Only if requesting a playback or duplex device.
config.capture.pDeviceID = pMyCaptureDeviceID; // Only if requesting a capture, duplex or loopback device.
```
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 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 and to perform operations outside the scope of an individual device. Mainly it is
used for performing run-time linking against backend libraries, initializing backends and
enumerating devices. The example below shows how to enumerate devices.
```c
ma_context context;
if (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
// Error.
}
ma_device_info* pPlaybackInfos;
ma_uint32 playbackCount;
ma_device_info* pCaptureInfos;
ma_uint32 captureCount;
if (ma_context_get_devices(&context, &pPlaybackInfos, &playbackCount, &pCaptureInfos, &captureCount) != MA_SUCCESS) {
// Error.
}
// Loop over each device info and do something with it. Here we just print the name with their index. You may want
// to give the user the opportunity to choose which device they'd prefer.
for (ma_uint32 iDevice = 0; iDevice < playbackCount; iDevice += 1) {
printf("%d - %s\n", iDevice, pPlaybackInfos[iDevice].name);
}
ma_device_config config = ma_device_config_init(ma_device_type_playback);
config.playback.pDeviceID = &pPlaybackInfos[chosenPlaybackDeviceIndex].id;
config.playback.format = MY_FORMAT;
config.playback.channels = MY_CHANNEL_COUNT;
config.sampleRate = MY_SAMPLE_RATE;
config.dataCallback = data_callback;
config.pUserData = pMyCustomData;
ma_device device;
if (ma_device_init(&context, &config, &device) != MA_SUCCESS) {
// Error
}
...
ma_device_uninit(&device);
ma_context_uninit(&context);
```
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` 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 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 which can be
NULL, in which case defaults are used. The context configuration is used for setting the logging
callback, custom memory allocation callbacks, user-defined data and some backend-specific
configurations.
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 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, 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 receive
the number of items in the returned buffer. Do not free the returned buffers as their memory is
managed internally by miniaudio.
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 for presenting a list of devices
to the user via the UI.
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, 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 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 allocate memory for
the context.
1.2. High Level API
-------------------
The high level API consists of three main parts:
* Resource management for loading and streaming sounds.
* A node graph for advanced mixing and effect processing.
* A high level "engine" that wraps around the resource manager and node graph.
The resource manager (`ma_resource_manager`) is used for loading sounds. It supports loading sounds
fully into memory and also streaming. It will also deal with reference counting for you which
avoids the same sound being loaded multiple times.
The node graph is used for mixing and effect processing. The idea is that you connect a number of
nodes into the graph by connecting each node's outputs to another node's inputs. Each node can
implement it's own effect. By chaining nodes together, advanced mixing and effect processing can
be achieved.
The engine encapsulates both the resource manager and the node graph to create a simple, easy to
use high level API. The resource manager and node graph APIs are covered in more later sections of
this manual.
The code below shows how you can initialize an engine using it's default configuration.
```c
ma_result result;
ma_engine engine;
result = ma_engine_init(NULL, &engine);
if (result != MA_SUCCESS) {
return result; // Failed to initialize the engine.
}
```
This creates an engine instance which will initialize a device internally which you can access with
`ma_engine_get_device()`. It will also initialize a resource manager for you which can be accessed
with `ma_engine_get_resource_manager()`. The engine itself is a node graph (`ma_node_graph`) which
means you can pass a pointer to the engine object into any of the `ma_node_graph` APIs (with a
cast). Alternatively, you can use `ma_engine_get_node_graph()` instead of a cast.
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
6.1. Asynchronous Loading and Synchronization
---------------------------------------------
When loading asynchronously, it can be useful to poll whether or not loading has finished. Use
`ma_resource_manager_data_source_result()` to determine this. For in-memory sounds, this will
return `MA_SUCCESS` when the file has been *entirely* decoded. If the sound is still being decoded,
`MA_BUSY` will be returned. Otherwise, some other error code will be returned if the sound failed
to load. For streaming data sources, `MA_SUCCESS` will be returned when the first page has been
decoded and the sound is ready to be played. If the first page is still being decoded, `MA_BUSY`
will be returned. Otherwise, some other error code will be returned if the sound failed to load.
In addition to polling, you can also use a simple synchronization object called a "fence" to wait
for asynchronously loaded sounds to finish. This is called `ma_fence`. The advantage to using a
fence is that it can be used to wait for a group of sounds to finish loading rather than waiting
for sounds on an individual basis. There are two stages to loading a sound:
* Initialization of the internal decoder; and
* Completion of decoding of the file (the file is fully decoded)
You can specify separate fences for each of the different stages. Waiting for the initialization
of the internal decoder is important for when you need to know the sample format, channels and
sample rate of the file.
The example below shows how you could use a fence when loading a number of sounds:
```c
// This fence will be released when all sounds are finished loading entirely.
ma_fence fence;
ma_fence_init(&fence);
// This will be passed into the initialization routine for each sound.
ma_resource_manager_pipeline_notifications notifications = ma_resource_manager_pipeline_notifications_init();
notifications.done.pFence = &fence;
// Now load a bunch of sounds:
for (iSound = 0; iSound < soundCount; iSound += 1) {
ma_resource_manager_data_source_init(pResourceManager, pSoundFilePaths[iSound], flags, ¬ifications, &pSoundSources[iSound]);
}
// ... DO SOMETHING ELSE WHILE SOUNDS ARE LOADING ...
// Wait for loading of sounds to finish.
ma_fence_wait(&fence);
```
In the example above we used a fence for waiting until the entire file has been fully decoded. If
you only need to wait for the initialization of the internal decoder to complete, you can use the
`init` member of the `ma_resource_manager_pipeline_notifications` object:
```c
notifications.init.pFence = &fence;
```
If a fence is not appropriate for your situation, you can instead use a callback that is fired on
an individual sound basis. This is done in a very similar way to fences:
```c
typedef struct
{
ma_async_notification_callbacks cb;
void* pMyData;
} my_notification;
void my_notification_callback(ma_async_notification* pNotification)
{
my_notification* pMyNotification = (my_notification*)pNotification;
// Do something in response to the sound finishing loading.
}
...
my_notification myCallback;
myCallback.cb.onSignal = my_notification_callback;
myCallback.pMyData = pMyData;
ma_resource_manager_pipeline_notifications notifications = ma_resource_manager_pipeline_notifications_init();
notifications.done.pNotification = &myCallback;
ma_resource_manager_data_source_init(pResourceManager, "my_sound.wav", flags, ¬ifications, &mySound);
```
In the example above we just extend the `ma_async_notification_callbacks` object and pass an
instantiation into the `ma_resource_manager_pipeline_notifications` in the same way as we did with
the fence, only we set `pNotification` instead of `pFence`. You can set both of these at the same
time and they should both work as expected. If using the `pNotification` system, you need to ensure
your `ma_async_notification_callbacks` object stays valid.
6.2. Resource Manager Implementation Details
--------------------------------------------
Resources are managed in two main ways:
* By storing the entire sound inside an in-memory buffer (referred to as a data buffer)
* By streaming audio data on the fly (referred to as a data stream)
A resource managed data source (`ma_resource_manager_data_source`) encapsulates a data buffer or
data stream, depending on whether or not the data source was initialized with the
`MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` flag. If so, it will make use of a
`ma_resource_manager_data_stream` object. Otherwise it will use a `ma_resource_manager_data_buffer`
object. Both of these objects are data sources which means they can be used with any
`ma_data_source_*()` API.
Another major feature of the resource manager is the ability to asynchronously decode audio files.
This relieves the audio thread of time-consuming decoding which can negatively affect scalability
due to the audio thread needing to complete it's work extremely quickly to avoid glitching.
Asynchronous decoding is achieved through a job system. There is a central multi-producer,
multi-consumer, fixed-capacity job queue. When some asynchronous work needs to be done, a job is
posted to the queue which is then read by a job thread. The number of job threads can be
configured for improved scalability, and job threads can all run in parallel without needing to
worry about the order of execution (how this is achieved is explained below).
When a sound is being loaded asynchronously, playback can begin before the sound has been fully
decoded. This enables the application to start playback of the sound quickly, while at the same
time allowing to resource manager to keep loading in the background. Since there may be less
threads than the number of sounds being loaded at a given time, a simple scheduling system is used
to keep decoding time balanced and fair. The resource manager solves this by splitting decoding
into chunks called pages. By default, each page is 1 second long. When a page has been decoded, a
new job will be posted to start decoding the next page. By dividing up decoding into pages, an
individual sound shouldn't ever delay every other sound from having their first page decoded. Of
course, when loading many sounds at the same time, there will always be an amount of time required
to process jobs in the queue so in heavy load situations there will still be some delay. To
determine if a data source is ready to have some frames read, use
`ma_resource_manager_data_source_get_available_frames()`. This will return the number of frames
available starting from the current position.
6.2.1. Job Queue
----------------
The resource manager uses a job queue which is multi-producer, multi-consumer, and fixed-capacity.
This job queue is not currently lock-free, and instead uses a spinlock to achieve thread-safety.
Only a fixed number of jobs can be allocated and inserted into the queue which is done through a
lock-free data structure for allocating an index into a fixed sized array, with reference counting
for mitigation of the ABA problem. The reference count is 32-bit.
For many types of jobs it's important that they execute in a specific order. In these cases, jobs
are executed serially. For the resource manager, serial execution of jobs is only required on a
per-object basis (per data buffer or per data stream). Each of these objects stores an execution
counter. When a job is posted it is associated with an execution counter. When the job is
processed, it checks if the execution counter of the job equals the execution counter of the
owning object and if so, processes the job. If the counters are not equal, the job will be posted
back onto the job queue for later processing. When the job finishes processing the execution order
of the main object is incremented. This system means the no matter how many job threads are
executing, decoding of an individual sound will always get processed serially. The advantage to
having multiple threads comes into play when loading multiple sounds at the same time.
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
Also, if the data stream is uninitialized while pages are in the middle of decoding, they must
complete before destroying any underlying object and the job system handles this cleanly.
Note that when a new page needs to be loaded, a job will be posted to the resource manager's job
thread from the audio thread. You must keep in mind the details mentioned in the "Job Queue"
section above regarding locking when posting an event if you require a strictly lock-free audio
thread.
7. Node Graph
=============
miniaudio's routing infrastructure follows a node graph paradigm. The idea is that you create a
node whose outputs are attached to inputs of another node, thereby creating a graph. There are
different types of nodes, with each node in the graph processing input data to produce output,
which is then fed through the chain. Each node in the graph can apply their own custom effects. At
the start of the graph will usually be one or more data source nodes which have no inputs, but
instead pull their data from a data source. At the end of the graph is an endpoint which represents
the end of the chain and is where the final output is ultimately extracted from.
Each node has a number of input buses and a number of output buses. An output bus from a node is
attached to an input bus of another. Multiple nodes can connect their output buses to another
node's input bus, in which case their outputs will be mixed before processing by the node. Below is
a diagram that illustrates a hypothetical node graph setup:
```
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Data flows left to right >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+---------------+ +-----------------+
| Data Source 1 =----+ +----------+ +----= Low Pass Filter =----+
+---------------+ | | =----+ +-----------------+ | +----------+
+----= Splitter | +----= ENDPOINT |
+---------------+ | | =----+ +-----------------+ | +----------+
| Data Source 2 =----+ +----------+ +----= Echo / Delay =----+
+---------------+ +-----------------+
```
In the above graph, it starts with two data sources whose outputs are attached to the input of a
splitter node. It's at this point that the two data sources are mixed. After mixing, the splitter
performs it's processing routine and produces two outputs which is simply a duplication of the
input stream. One output is attached to a low pass filter, whereas the other output is attached to
a echo/delay. The outputs of the the low pass filter and the echo are attached to the endpoint, and
since they're both connected to the same input but, they'll be mixed.
Each input bus must be configured to accept the same number of channels, but the number of channels
used by input buses can be different to the number of channels for output buses in which case
miniaudio will automatically convert the input data to the output channel count before processing.
The number of channels of an output bus of one node must match the channel count of the input bus
it's attached to. The channel counts cannot be changed after the node has been initialized. If you
attempt to attach an output bus to an input bus with a different channel count, attachment will
fail.
To use a node graph, you first need to initialize a `ma_node_graph` object. This is essentially a
container around the entire graph. The `ma_node_graph` object is required for some thread-safety
issues which will be explained later. A `ma_node_graph` object is initialized using miniaudio's
standard config/init system:
```c
ma_node_graph_config nodeGraphConfig = ma_node_graph_config_init(myChannelCount);
result = ma_node_graph_init(&nodeGraphConfig, NULL, &nodeGraph); // Second parameter is a pointer to allocation callbacks.
if (result != MA_SUCCESS) {
// Failed to initialize node graph.
}
```
When you initialize the node graph, you're specifying the channel count of the endpoint. The
endpoint is a special node which has one input bus and one output bus, both of which have the
same channel count, which is specified in the config. Any nodes that connect directly to the
endpoint must be configured such that their output buses have the same channel count. When you read
audio data from the node graph, it'll have the channel count you specified in the config. To read
data from the graph:
```c
ma_uint32 framesRead;
result = ma_node_graph_read_pcm_frames(&nodeGraph, pFramesOut, frameCount, &framesRead);
if (result != MA_SUCCESS) {
// Failed to read data from the node graph.
}
```
When you read audio data, miniaudio starts at the node graph's endpoint node which then pulls in
data from it's input attachments, which in turn recusively pull in data from their inputs, and so
on. At the start of the graph there will be some kind of data source node which will have zero
inputs and will instead read directly from a data source. The base nodes don't literally need to
read from a `ma_data_source` object, but they will always have some kind of underlying object that
sources some kind of audio. The `ma_data_source_node` node can be used to read from a
`ma_data_source`. Data is always in floating-point format and in the number of channels you
specified when the graph was initialized. The sample rate is defined by the underlying data sources.
It's up to you to ensure they use a consistent and appropraite sample rate.
The `ma_node` API is designed to allow custom nodes to be implemented with relative ease, but
miniaudio includes a few stock nodes for common functionality. This is how you would initialize a
node which reads directly from a data source (`ma_data_source_node`) which is an example of one
of the stock nodes that comes with miniaudio:
```c
ma_data_source_node_config config = ma_data_source_node_config_init(pMyDataSource);
ma_data_source_node dataSourceNode;
result = ma_data_source_node_init(&nodeGraph, &config, NULL, &dataSourceNode);
if (result != MA_SUCCESS) {
// Failed to create data source node.
}
```
The data source node will use the output channel count to determine the channel count of the output
bus. There will be 1 output bus and 0 input buses (data will be drawn directly from the data
source). The data source must output to floating-point (`ma_format_f32`) or else an error will be
returned from `ma_data_source_node_init()`.
By default the node will not be attached to the graph. To do so, use `ma_node_attach_output_bus()`:
```c
result = ma_node_attach_output_bus(&dataSourceNode, 0, ma_node_graph_get_endpoint(&nodeGraph), 0);
if (result != MA_SUCCESS) {
// Failed to attach node.
}
```
The code above connects the data source node directly to the endpoint. Since the data source node
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_node_attach_output_bus(&splitterNode, 1, &myEffectNode, 0); // Attach to input bus 0 of some effect node.
```
The volume of an output bus can be configured on a per-bus basis:
```c
ma_node_set_output_bus_volume(&splitterNode, 0, 0.5f);
ma_node_set_output_bus_volume(&splitterNode, 1, 0.5f);
```
In the code above we're using the splitter node from before and changing the volume of each of the
copied streams.
You can start and stop a node with the following:
```c
ma_node_set_state(&splitterNode, ma_node_state_started); // The default state.
ma_node_set_state(&splitterNode, ma_node_state_stopped);
```
By default the node is in a started state, but since it won't be connected to anything won't
actually be invoked by the node graph until it's connected. When you stop a node, data will not be
read from any of it's input connections. You can use this property to stop a group of sounds
atomically.
You can configure the initial state of a node in it's config:
```c
nodeConfig.initialState = ma_node_state_stopped;
```
Note that for the stock specialized nodes, all of their configs will have a `nodeConfig` member
which is the config to use with the base node. This is where the initial state can be configured
for specialized nodes:
```c
dataSourceNodeConfig.nodeConfig.initialState = ma_node_state_stopped;
```
When using a specialized node like `ma_data_source_node` or `ma_splitter_node`, be sure to not
modify the `vtable` member of the `nodeConfig` object.
7.1. Timing
-----------
The node graph supports starting and stopping nodes at scheduled times. This is especially useful
for data source nodes where you want to get the node set up, but only start playback at a specific
time. There are two clocks: local and global.
A local clock is per-node, whereas the global clock is per graph. Scheduling starts and stops can
only be done based on the global clock because the local clock will not be running while the node
is stopped. The global clocks advances whenever `ma_node_graph_read_pcm_frames()` is called. On the
other hand, the local clock only advances when the node's processing callback is fired, and is
advanced based on the output frame count.
To retrieve the global time, use `ma_node_graph_get_time()`. The global time can be set with
`ma_node_graph_set_time()` which might be useful if you want to do seeking on a global timeline.
Getting and setting the local time is similar. Use `ma_node_get_time()` to retrieve the local time,
and `ma_node_set_time()` to set the local time. The global and local times will be advanced by the
audio thread, so care should be taken to avoid data races. Ideally you should avoid calling these
outside of the node processing callbacks which are always run on the audio thread.
There is basic support for scheduling the starting and stopping of nodes. You can only schedule one
start and one stop at a time. This is mainly intended for putting nodes into a started or stopped
state in a frame-exact manner. Without this mechanism, starting and stopping of a node is limited
to the resolution of a call to `ma_node_graph_read_pcm_frames()` which would typically be in blocks
of several milliseconds. The following APIs can be used for scheduling node states:
```c
ma_node_set_state_time()
ma_node_get_state_time()
```
The time is absolute and must be based on the global clock. An example is below:
```c
ma_node_set_state_time(&myNode, ma_node_state_started, sampleRate*1); // Delay starting to 1 second.
ma_node_set_state_time(&myNode, ma_node_state_stopped, sampleRate*5); // Delay stopping to 5 seconds.
```
An example for changing the state using a relative time.
```c
ma_node_set_state_time(&myNode, ma_node_state_started, sampleRate*1 + ma_node_graph_get_time(&myNodeGraph));
ma_node_set_state_time(&myNode, ma_node_state_stopped, sampleRate*5 + ma_node_graph_get_time(&myNodeGraph));
```
Note that due to the nature of multi-threading the times may not be 100% exact. If this is an
issue, consider scheduling state changes from within a processing callback. An idea might be to
have some kind of passthrough trigger node that is used specifically for tracking time and handling
events.
7.2. Thread Safety and Locking
------------------------------
When processing audio, it's ideal not to have any kind of locking in the audio thread. Since it's
expected that `ma_node_graph_read_pcm_frames()` would be run on the audio thread, it does so
without the use of any locks. This section discusses the implementation used by miniaudio and goes
over some of the compromises employed by miniaudio to achieve this goal. Note that the current
implementation may not be ideal - feedback and critiques are most welcome.
The node graph API is not *entirely* lock-free. Only `ma_node_graph_read_pcm_frames()` is expected
to be lock-free. Attachment, detachment and uninitialization of nodes use locks to simplify the
implementation, but are crafted in a way such that such locking is not required when reading audio
data from the graph. Locking in these areas are achieved by means of spinlocks.
The main complication with keeping `ma_node_graph_read_pcm_frames()` lock-free stems from the fact
that a node can be uninitialized, and it's memory potentially freed, while in the middle of being
processed on the audio thread. There are times when the audio thread will be referencing a node,
which means the uninitialization process of a node needs to make sure it delays returning until the
audio thread is finished so that control is not handed back to the caller thereby giving them a
chance to free the node's memory.
When the audio thread is processing a node, it does so by reading from each of the output buses of
the node. In order for a node to process data for one of it's output buses, it needs to read from
each of it's input buses, and so on an so forth. It follows that once all output buses of a node
are detached, the node as a whole will be disconnected and no further processing will occur unless
it's output buses are reattached, which won't be happening when the node is being uninitialized.
By having `ma_node_detach_output_bus()` wait until the audio thread is finished with it, we can
simplify a few things, at the expense of making `ma_node_detach_output_bus()` a bit slower. By
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
to the next item in the list, and another to the previous item. A pointer to the previous item is
only required for fast detachment of the node - it is never used in iteration. This is an
important property because it means from the perspective of iteration, attaching and detaching of
an item can be done with a single atomic assignment. This is exploited by both the attachment and
detachment process. When attaching the node, the first thing that is done is the setting of the
local "next" and "previous" pointers of the node. After that, the item is "attached" to the list
by simply performing an atomic exchange with the head pointer. After that, the node is "attached"
to the list from the perspective of iteration. Even though the "previous" pointer of the next item
hasn't yet been set, from the perspective of iteration it's been attached because iteration will
only be happening in a forward direction which means the "previous" pointer won't actually ever get
used. The same general process applies to detachment. See `ma_node_attach_output_bus()` and
`ma_node_detach_output_bus()` for the implementation of this mechanism.
8. Decoding
===========
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 supported:
+---------+------------------+----------+
| Format | Decoding Backend | Built-In |
+---------+------------------+----------+
| WAV | dr_wav | Yes |
| MP3 | dr_mp3 | Yes |
| FLAC | dr_flac | Yes |
| Vorbis | stb_vorbis | No |
+---------+------------------+----------+
Vorbis is supported via stb_vorbis which can be enabled by including the header section before the
implementation of miniaudio, like the following:
```c
#define STB_VORBIS_HEADER_ONLY
#include "extras/stb_vorbis.c" // Enables Vorbis decoding.
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
// The stb_vorbis implementation must come after the implementation of miniaudio.
#undef STB_VORBIS_HEADER_ONLY
#include "extras/stb_vorbis.c"
```
A copy of stb_vorbis is included in the "extras" folder in the miniaudio repository (https://github.com/mackron/miniaudio).
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 following options before the miniaudio
implementation:
```c
#define MA_NO_WAV
#define MA_NO_MP3
#define MA_NO_FLAC
```
Disabling built-in decoding libraries is useful if you use these libraries independantly of the
`ma_decoder` API.
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 with `ma_decoder_init()`. Here is
an example for loading a decoder from a file:
```c
ma_decoder decoder;
ma_result result = ma_decoder_init_file("MySong.mp3", NULL, &decoder);
if (result != MA_SUCCESS) {
return false; // An error occurred.
}
...
ma_decoder_uninit(&decoder);
```
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 to configure the output format, channel
count, sample rate and channel map:
```c
ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 2, 48000);
```
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.
Data is read from the decoder as PCM frames. This will output the number of PCM frames actually
read. If this is less than the requested number of PCM frames it means you've reached the end. The
return value will be `MA_AT_END` if no samples have been read and the end has been reached.
```c
ma_result result = ma_decoder_read_pcm_frames(pDecoder, pFrames, framesToRead, &framesRead);
if (framesRead < framesToRead) {
// Reached the end.
}
```
You can also seek to a specific frame like so:
```c
ma_result result = ma_decoder_seek_to_pcm_frame(pDecoder, targetFrame);
if (result != MA_SUCCESS) {
return false; // An error occurred.
}
```
If you want to loop back to the start, you can simply seek back to the first PCM frame:
```c
ma_decoder_seek_to_pcm_frame(pDecoder, 0);
```
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 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:
```c
decoderConfig.encodingFormat = ma_encoding_format_wav;
```
See the `ma_encoding_format` enum for possible encoding formats.
The `ma_decoder_init_file()` API will try using the file extension to determine which decoding
backend to prefer.
8.1. Custom Decoders
--------------------
It's possible to implement a custom decoder and plug it into miniaudio. This is extremely useful
when you want to use the `ma_decoder` API, but need to support an encoding format that's not one of
the stock formats supported by miniaudio. This can be put to particularly good use when using the
`ma_engine` and/or `ma_resource_manager` APIs because they use `ma_decoder` internally. If, for
example, you wanted to support Opus, you can do so with a custom decoder (there if a reference
Opus decoder in the "extras" folder of the miniaudio repository which uses libopus + libopusfile).
A custom decoder must implement a data source. A vtable called `ma_decoding_backend_vtable` needs
to be implemented which is then passed into the decoder config:
```c
ma_decoding_backend_vtable* pCustomBackendVTables[] =
{
&g_ma_decoding_backend_vtable_libvorbis,
&g_ma_decoding_backend_vtable_libopus
};
...
decoderConfig = ma_decoder_config_init_default();
decoderConfig.pCustomBackendUserData = NULL;
decoderConfig.ppCustomBackendVTables = pCustomBackendVTables;
decoderConfig.customBackendCount = sizeof(pCustomBackendVTables) / sizeof(pCustomBackendVTables[0]);
```
The `ma_decoding_backend_vtable` vtable has the following functions:
```
onInit
onInitFile
onInitFileW
onInitMemory
onUninit
```
There are only two functions that must be implemented - `onInit` and `onUninit`. The other
functions can be implemented for a small optimization for loading from a file path or memory. If
these are not specified, miniaudio will deal with it for you via a generic implementation.
When you initialize a custom data source (by implementing the `onInit` function in the vtable) you
will need to output a pointer to a `ma_data_source` which implements your custom decoder. See the
section about data sources for details on how to implemen this. Alternatively, see the
"custom_decoders" example in the miniaudio repository.
The `onInit` function takes a pointer to some callbacks for the purpose of reading raw audio data
from some abitrary source. You'll use these functions to read from the raw data and perform the
decoding. When you call them, you will pass in the `pReadSeekTellUserData` pointer to the relevant
parameter.
The `pConfig` parameter in `onInit` can be used to configure the backend if appropriate. It's only
used as a hint and can be ignored. However, if any of the properties are relevant to your decoder,
an optimal implementation will handle the relevant properties appropriately.
If memory allocation is required, it should be done so via the specified allocation callbacks if
possible (the `pAllocationCallbacks` parameter).
If an error occurs when initializing the decoder, you should leave `ppBackend` unset, or set to
NULL, and make sure everything is cleaned up appropriately and an appropriate result code returned.
When multiple custom backends are specified, miniaudio will cycle through the vtables in the order
they're listed in the array that's passed into the decoder config so it's important that your
initialization routine is clean.
When a decoder is uninitialized, the `onUninit` callback will be fired which will give you an
opportunity to clean up and internal data.
9. Encoding
===========
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 implementation section of miniaudio.
This can be disabled by specifying the following option before the implementation of miniaudio:
```c
#define MA_NO_WAV
```
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 example for initializing an encoder
to output to a file.
```c
ma_encoder_config config = ma_encoder_config_init(ma_encoding_format_wav, FORMAT, CHANNELS, SAMPLE_RATE);
ma_encoder encoder;
ma_result result = ma_encoder_init_file("my_file.wav", &config, &encoder);
if (result != MA_SUCCESS) {
// Error
}
...
ma_encoder_uninit(&encoder);
```
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 sample format, output
channel count and output sample rate. The following file types are supported:
+------------------------+-------------+
| Enum | Description |
+------------------------+-------------+
| ma_encoding_format_wav | WAV |
+------------------------+-------------+
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 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:
```c
framesWritten = ma_encoder_write_pcm_frames(&encoder, pPCMFramesToWrite, framesToWrite);
```
Encoders must be uninitialized with `ma_encoder_uninit()`.
10. Data Conversion
===================
A data conversion API is included with miniaudio which supports the majority of data conversion
requirements. This supports conversion between sample formats, channel counts (with channel
mapping) and sample rates.
10.1. Sample Format Conversion
------------------------------
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_*()` 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 PCM frames where you want to specify the frame count
and channel count as a variable instead of the total sample count.
10.1.1. Dithering
-----------------
Dithering can be set using the ditherMode parameter.
The different dithering modes include the following, in order of efficiency:
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_uint64 framesRead = ma_audio_buffer_read_pcm_frames(pAudioBuffer, pFramesOut, desiredFrameCount, isLooping);
if (framesRead < desiredFrameCount) {
// If not looping, this means the end has been reached. This should never happen in looping mode with valid input.
}
```
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 pointer to a segment of data:
```c
void* pMappedFrames;
ma_uint64 frameCount = frameCountToTryMapping;
ma_result result = ma_audio_buffer_map(pAudioBuffer, &pMappedFrames, &frameCount);
if (result == MA_SUCCESS) {
// Map was successful. The value in frameCount will be how many frames were _actually_ mapped, which may be
// less due to the end of the buffer being reached.
ma_copy_pcm_frames(pFramesOut, pMappedFrames, frameCount, pAudioBuffer->format, pAudioBuffer->channels);
// You must unmap the buffer.
ma_audio_buffer_unmap(pAudioBuffer, frameCount);
}
```
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 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 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
`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()`.
14. Ring Buffers
================
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 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`.
Unlike most other APIs in miniaudio, ring buffers support both interleaved and deinterleaved
streams. The caller can also allocate their own backing memory for the ring buffer to use
internally for added flexibility. Otherwise the ring buffer will manage it's internal memory for
you.
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 something like the following:
```c
ma_pcm_rb rb;
ma_result result = ma_pcm_rb_init(FORMAT, CHANNELS, BUFFER_SIZE_IN_FRAMES, NULL, NULL, &rb);
if (result != MA_SUCCESS) {
// Error
}
```
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 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 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 routines.
Passing in `NULL` for this results in `MA_MALLOC()` and `MA_FREE()` being used.
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 sub-buffers you can use
`ma_pcm_rb_get_subbuffer_stride()`, `ma_pcm_rb_get_subbuffer_offset()` and
`ma_pcm_rb_get_subbuffer_ptr()`.
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 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 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.
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 `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 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
`ma_pcm_rb_commit_write()` is what's used to increment the pointers, and can be less that what was
originally requested.
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()`, `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 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
there is too little space between the pointers, move the write pointer forward.
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` functions instead of `ma_pcm_rb` and
instead of frame counts you will pass around byte counts.
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 managed buffers always being
aligned to `MA_SIMD_ALIGNMENT`.
Note that the ring buffer is only thread safe when used by a single consumer thread and single
producer thread.
15. Backends
============
The following backends are supported by miniaudio.
+-------------+-----------------------+--------------------------------------------------------+
| Name | Enum Name | Supported Operating Systems |
+-------------+-----------------------+--------------------------------------------------------+
| WASAPI | ma_backend_wasapi | Windows Vista+ |
| DirectSound | ma_backend_dsound | Windows XP+ |
| WinMM | ma_backend_winmm | Windows XP+ (may work on older versions, but untested) |
| Core Audio | ma_backend_coreaudio | macOS, iOS |
| ALSA | ma_backend_alsa | Linux |
| PulseAudio | ma_backend_pulseaudio | Cross Platform (disabled on Windows, BSD and Android) |
| JACK | ma_backend_jack | Cross Platform (disabled on BSD and Android) |
| sndio | ma_backend_sndio | OpenBSD |
| audio(4) | ma_backend_audio4 | NetBSD, OpenBSD |
| OSS | ma_backend_oss | FreeBSD |
| AAudio | ma_backend_aaudio | Android 8+ |
| OpenSL ES | ma_backend_opensl | Android (API level 16+) |
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
I am using "__inline__" only when we're compiling in strict ANSI mode.
*/
#if defined(__STRICT_ANSI__)
#define MA_GNUC_INLINE_HINT __inline__
#else
#define MA_GNUC_INLINE_HINT inline
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
#define MA_INLINE MA_GNUC_INLINE_HINT __attribute__((always_inline))
#else
#define MA_INLINE MA_GNUC_INLINE_HINT
#endif
#elif defined(__WATCOMC__)
#define MA_INLINE __inline
#else
#define MA_INLINE
#endif
#if !defined(MA_API)
#if defined(MA_DLL)
#if defined(_WIN32)
#define MA_DLL_IMPORT __declspec(dllimport)
#define MA_DLL_EXPORT __declspec(dllexport)
#define MA_DLL_PRIVATE static
#else
#if defined(__GNUC__) && __GNUC__ >= 4
#define MA_DLL_IMPORT __attribute__((visibility("default")))
#define MA_DLL_EXPORT __attribute__((visibility("default")))
#define MA_DLL_PRIVATE __attribute__((visibility("hidden")))
#else
#define MA_DLL_IMPORT
#define MA_DLL_EXPORT
#define MA_DLL_PRIVATE static
#endif
#endif
#if defined(MINIAUDIO_IMPLEMENTATION) || defined(MA_IMPLEMENTATION)
#define MA_API MA_DLL_EXPORT
#else
#define MA_API MA_DLL_IMPORT
#endif
#define MA_PRIVATE MA_DLL_PRIVATE
#else
#define MA_API extern
#define MA_PRIVATE static
#endif
#endif
/* SIMD alignment in bytes. Currently set to 32 bytes in preparation for future AVX optimizations. */
#define MA_SIMD_ALIGNMENT 32
/*
Logging Levels
==============
Log levels are only used to give logging callbacks some context as to the severity of a log message
so they can do filtering. All log levels will be posted to registered logging callbacks. If you
don't want to output a certain log level you can discriminate against the log level in the callback.
MA_LOG_LEVEL_DEBUG
Used for debugging. Useful for debug and test builds, but should be disabled in release builds.
MA_LOG_LEVEL_INFO
Informational logging. Useful for debugging. This will never be called from within the data
callback.
MA_LOG_LEVEL_WARNING
Warnings. You should enable this in you development builds and action them when encounted. These
logs usually indicate a potential problem or misconfiguration, but still allow you to keep
running. This will never be called from within the data callback.
MA_LOG_LEVEL_ERROR
Error logging. This will be fired when an operation fails and is subsequently aborted. This can
be fired from within the data callback, in which case the device will be stopped. You should
always have this log level enabled.
*/
typedef enum
{
MA_LOG_LEVEL_DEBUG = 4,
MA_LOG_LEVEL_INFO = 3,
MA_LOG_LEVEL_WARNING = 2,
MA_LOG_LEVEL_ERROR = 1
} ma_log_level;
/*
Variables needing to be accessed atomically should be declared with this macro for two reasons:
1) It allows people who read the code to identify a variable as such; and
2) It forces alignment on platforms where it's required or optimal.
Note that for x86/64, alignment is not strictly necessary, but does have some performance
implications. Where supported by the compiler, alignment will be used, but otherwise if the CPU
architecture does not require it, it will simply leave it unaligned. This is the case with old
versions of Visual Studio, which I've confirmed with at least VC6.
*/
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#include <stdalign.h>
#define MA_ATOMIC(alignment, type) alignas(alignment) type
#else
#if defined(__GNUC__)
/* GCC-style compilers. */
#define MA_ATOMIC(alignment, type) type __attribute__((aligned(alignment)))
#elif defined(_MSC_VER) && _MSC_VER > 1200 /* 1200 = VC6. Alignment not supported, but not necessary because x86 is the only supported target. */
/* MSVC. */
#define MA_ATOMIC(alignment, type) __declspec(align(alignment)) type
#else
/* Other compilers. */
#define MA_ATOMIC(alignment, type) type
#endif
#endif
typedef struct ma_context ma_context;
typedef struct ma_device ma_device;
typedef ma_uint8 ma_channel;
typedef enum
{
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
/* Standard rates need to be in priority order. */
ma_standard_sample_rate_48000 = 48000, /* Most common */
ma_standard_sample_rate_44100 = 44100,
ma_standard_sample_rate_32000 = 32000, /* Lows */
ma_standard_sample_rate_24000 = 24000,
ma_standard_sample_rate_22050 = 22050,
ma_standard_sample_rate_88200 = 88200, /* Highs */
ma_standard_sample_rate_96000 = 96000,
ma_standard_sample_rate_176400 = 176400,
ma_standard_sample_rate_192000 = 192000,
ma_standard_sample_rate_16000 = 16000, /* Extreme lows */
ma_standard_sample_rate_11025 = 11250,
ma_standard_sample_rate_8000 = 8000,
ma_standard_sample_rate_352800 = 352800, /* Extreme highs */
ma_standard_sample_rate_384000 = 384000,
ma_standard_sample_rate_min = ma_standard_sample_rate_8000,
ma_standard_sample_rate_max = ma_standard_sample_rate_384000,
ma_standard_sample_rate_count = 14 /* Need to maintain the count manually. Make sure this is updated if items are added to enum. */
} ma_standard_sample_rate;
typedef enum
{
ma_channel_mix_mode_rectangular = 0, /* Simple averaging based on the plane(s) the channel is sitting on. */
ma_channel_mix_mode_simple, /* Drop excess channels; zeroed out extra channels. */
ma_channel_mix_mode_custom_weights, /* Use custom weights specified in ma_channel_router_config. */
ma_channel_mix_mode_default = ma_channel_mix_mode_rectangular
} ma_channel_mix_mode;
typedef enum
{
ma_standard_channel_map_microsoft,
ma_standard_channel_map_alsa,
ma_standard_channel_map_rfc3551, /* Based off AIFF. */
ma_standard_channel_map_flac,
ma_standard_channel_map_vorbis,
ma_standard_channel_map_sound4, /* FreeBSD's sound(4). */
ma_standard_channel_map_sndio, /* www.sndio.org/tips.html */
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. */
ma_standard_channel_map_default = ma_standard_channel_map_microsoft
} ma_standard_channel_map;
typedef enum
{
ma_performance_profile_low_latency = 0,
ma_performance_profile_conservative
} ma_performance_profile;
typedef struct
{
void* pUserData;
void* (* onMalloc)(size_t sz, void* pUserData);
void* (* onRealloc)(void* p, size_t sz, void* pUserData);
void (* onFree)(void* p, void* pUserData);
} ma_allocation_callbacks;
typedef struct
{
ma_int32 state;
} ma_lcg;
/* Spinlocks are 32-bit for compatibility reasons. */
typedef ma_uint32 ma_spinlock;
#ifndef MA_NO_THREADING
/* Thread priorities should be ordered such that the default priority of the worker thread is 0. */
typedef enum
{
ma_thread_priority_idle = -5,
ma_thread_priority_lowest = -4,
ma_thread_priority_low = -3,
ma_thread_priority_normal = -2,
ma_thread_priority_high = -1,
ma_thread_priority_highest = 0,
ma_thread_priority_realtime = 1,
ma_thread_priority_default = 0
} ma_thread_priority;
#if defined(MA_WIN32)
typedef ma_handle ma_thread;
#endif
#if defined(MA_POSIX)
typedef ma_pthread_t ma_thread;
#endif
#if defined(MA_WIN32)
typedef ma_handle ma_mutex;
#endif
#if defined(MA_POSIX)
typedef ma_pthread_mutex_t ma_mutex;
#endif
#if defined(MA_WIN32)
typedef ma_handle ma_event;
#endif
#if defined(MA_POSIX)
typedef struct
{
ma_uint32 value;
ma_pthread_mutex_t lock;
ma_pthread_cond_t cond;
} ma_event;
#endif /* MA_POSIX */
#if defined(MA_WIN32)
typedef ma_handle ma_semaphore;
#endif
#if defined(MA_POSIX)
typedef struct
{
int value;
ma_pthread_mutex_t lock;
ma_pthread_cond_t cond;
} ma_semaphore;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
**************************************************************************************************************************************************************/
#include <stdarg.h> /* For va_list. */
#if defined(__has_attribute)
#if __has_attribute(format)
#define MA_ATTRIBUTE_FORMAT(fmt, va) __attribute__((format(printf, fmt, va)))
#endif
#endif
#ifndef MA_ATTRIBUTE_FORMAT
#define MA_ATTRIBUTE_FORMAT(fmt,va)
#endif
#ifndef MA_MAX_LOG_CALLBACKS
#define MA_MAX_LOG_CALLBACKS 4
#endif
/*
The callback for handling log messages.
Parameters
----------
pUserData (in)
The user data pointer that was passed into ma_log_register_callback().
logLevel (in)
The log level. This can be one of the following:
+----------------------+
| Log Level |
+----------------------+
| MA_LOG_LEVEL_DEBUG |
| MA_LOG_LEVEL_INFO |
| MA_LOG_LEVEL_WARNING |
| MA_LOG_LEVEL_ERROR |
+----------------------+
pMessage (in)
The log message.
Remarks
-------
Do not modify the state of the device from inside the callback.
*/
typedef void (* ma_log_callback_proc)(void* pUserData, ma_uint32 level, const char* pMessage);
typedef struct
{
ma_log_callback_proc onLog;
void* pUserData;
} ma_log_callback;
MA_API ma_log_callback ma_log_callback_init(ma_log_callback_proc onLog, void* pUserData);
typedef struct
{
ma_log_callback callbacks[MA_MAX_LOG_CALLBACKS];
ma_uint32 callbackCount;
ma_allocation_callbacks allocationCallbacks; /* Need to store these persistently because ma_log_postv() might need to allocate a buffer on the heap. */
#ifndef MA_NO_THREADING
ma_mutex lock; /* For thread safety just to make it easier and safer for the logging implementation. */
#endif
} ma_log;
MA_API ma_result ma_log_init(const ma_allocation_callbacks* pAllocationCallbacks, ma_log* pLog);
MA_API void ma_log_uninit(ma_log* pLog);
MA_API ma_result ma_log_register_callback(ma_log* pLog, ma_log_callback callback);
MA_API ma_result ma_log_unregister_callback(ma_log* pLog, ma_log_callback callback);
MA_API ma_result ma_log_post(ma_log* pLog, ma_uint32 level, const char* pMessage);
MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat, va_list args);
MA_API ma_result ma_log_postf(ma_log* pLog, ma_uint32 level, const char* pFormat, ...) MA_ATTRIBUTE_FORMAT(3, 4);
/**************************************************************************************************************************************************************
Biquad Filtering
**************************************************************************************************************************************************************/
typedef union
{
float f32;
ma_int32 s32;
} ma_biquad_coefficient;
typedef struct
{
ma_format format;
ma_uint32 channels;
double b0;
double b1;
double b2;
double a0;
double a1;
double a2;
} ma_biquad_config;
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);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_biquad_coefficient b0;
ma_biquad_coefficient b1;
ma_biquad_coefficient b2;
ma_biquad_coefficient a1;
ma_biquad_coefficient a2;
ma_biquad_coefficient* pR1;
ma_biquad_coefficient* pR2;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_biquad;
MA_API ma_result ma_biquad_get_heap_size(const ma_biquad_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_biquad_init_preallocated(const ma_biquad_config* pConfig, void* pHeap, ma_biquad* pBQ);
MA_API ma_result ma_biquad_init(const ma_biquad_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad* pBQ);
MA_API void ma_biquad_uninit(ma_biquad* pBQ, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_biquad_reinit(const ma_biquad_config* pConfig, ma_biquad* pBQ);
MA_API ma_result ma_biquad_clear_cache(ma_biquad* pBQ);
MA_API ma_result ma_biquad_process_pcm_frames(ma_biquad* pBQ, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_biquad_get_latency(const ma_biquad* pBQ);
/**************************************************************************************************************************************************************
Low-Pass Filtering
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double cutoffFrequency;
double q;
} ma_lpf1_config, ma_lpf2_config;
MA_API ma_lpf1_config ma_lpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency);
MA_API ma_lpf2_config ma_lpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_biquad_coefficient a;
ma_biquad_coefficient* pR1;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_lpf1;
MA_API ma_result ma_lpf1_get_heap_size(const ma_lpf1_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_lpf1_init_preallocated(const ma_lpf1_config* pConfig, void* pHeap, ma_lpf1* pLPF);
MA_API ma_result ma_lpf1_init(const ma_lpf1_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf1* pLPF);
MA_API void ma_lpf1_uninit(ma_lpf1* pLPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_lpf1_reinit(const ma_lpf1_config* pConfig, ma_lpf1* pLPF);
MA_API ma_result ma_lpf1_clear_cache(ma_lpf1* pLPF);
MA_API ma_result ma_lpf1_process_pcm_frames(ma_lpf1* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_lpf1_get_latency(const ma_lpf1* pLPF);
typedef struct
{
ma_biquad bq; /* The second order low-pass filter is implemented as a biquad filter. */
} ma_lpf2;
MA_API ma_result ma_lpf2_get_heap_size(const ma_lpf2_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_lpf2_init_preallocated(const ma_lpf2_config* pConfig, void* pHeap, ma_lpf2* pHPF);
MA_API ma_result ma_lpf2_init(const ma_lpf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf2* pLPF);
MA_API void ma_lpf2_uninit(ma_lpf2* pLPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_lpf2_reinit(const ma_lpf2_config* pConfig, ma_lpf2* pLPF);
MA_API ma_result ma_lpf2_clear_cache(ma_lpf2* pLPF);
MA_API ma_result ma_lpf2_process_pcm_frames(ma_lpf2* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_lpf2_get_latency(const ma_lpf2* pLPF);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double cutoffFrequency;
ma_uint32 order; /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
} ma_lpf_config;
MA_API ma_lpf_config ma_lpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
ma_uint32 lpf1Count;
ma_uint32 lpf2Count;
ma_lpf1* pLPF1;
ma_lpf2* pLPF2;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_lpf;
MA_API ma_result ma_lpf_get_heap_size(const ma_lpf_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_lpf_init_preallocated(const ma_lpf_config* pConfig, void* pHeap, ma_lpf* pLPF);
MA_API ma_result ma_lpf_init(const ma_lpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf* pLPF);
MA_API void ma_lpf_uninit(ma_lpf* pLPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_lpf_reinit(const ma_lpf_config* pConfig, ma_lpf* pLPF);
MA_API ma_result ma_lpf_clear_cache(ma_lpf* pLPF);
MA_API ma_result ma_lpf_process_pcm_frames(ma_lpf* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_lpf_get_latency(const ma_lpf* pLPF);
/**************************************************************************************************************************************************************
High-Pass Filtering
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double cutoffFrequency;
double q;
} ma_hpf1_config, ma_hpf2_config;
MA_API ma_hpf1_config ma_hpf1_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency);
MA_API ma_hpf2_config ma_hpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_biquad_coefficient a;
ma_biquad_coefficient* pR1;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_hpf1;
MA_API ma_result ma_hpf1_get_heap_size(const ma_hpf1_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_hpf1_init_preallocated(const ma_hpf1_config* pConfig, void* pHeap, ma_hpf1* pLPF);
MA_API ma_result ma_hpf1_init(const ma_hpf1_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf1* pHPF);
MA_API void ma_hpf1_uninit(ma_hpf1* pHPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_hpf1_reinit(const ma_hpf1_config* pConfig, ma_hpf1* pHPF);
MA_API ma_result ma_hpf1_process_pcm_frames(ma_hpf1* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_hpf1_get_latency(const ma_hpf1* pHPF);
typedef struct
{
ma_biquad bq; /* The second order high-pass filter is implemented as a biquad filter. */
} ma_hpf2;
MA_API ma_result ma_hpf2_get_heap_size(const ma_hpf2_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_hpf2_init_preallocated(const ma_hpf2_config* pConfig, void* pHeap, ma_hpf2* pHPF);
MA_API ma_result ma_hpf2_init(const ma_hpf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf2* pHPF);
MA_API void ma_hpf2_uninit(ma_hpf2* pHPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_hpf2_reinit(const ma_hpf2_config* pConfig, ma_hpf2* pHPF);
MA_API ma_result ma_hpf2_process_pcm_frames(ma_hpf2* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_hpf2_get_latency(const ma_hpf2* pHPF);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double cutoffFrequency;
ma_uint32 order; /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
} ma_hpf_config;
MA_API ma_hpf_config ma_hpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
ma_uint32 hpf1Count;
ma_uint32 hpf2Count;
ma_hpf1* pHPF1;
ma_hpf2* pHPF2;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_hpf;
MA_API ma_result ma_hpf_get_heap_size(const ma_hpf_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_hpf_init_preallocated(const ma_hpf_config* pConfig, void* pHeap, ma_hpf* pLPF);
MA_API ma_result ma_hpf_init(const ma_hpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf* pHPF);
MA_API void ma_hpf_uninit(ma_hpf* pHPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_hpf_reinit(const ma_hpf_config* pConfig, ma_hpf* pHPF);
MA_API ma_result ma_hpf_process_pcm_frames(ma_hpf* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_hpf_get_latency(const ma_hpf* pHPF);
/**************************************************************************************************************************************************************
Band-Pass Filtering
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double cutoffFrequency;
double q;
} ma_bpf2_config;
MA_API ma_bpf2_config ma_bpf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, double q);
typedef struct
{
ma_biquad bq; /* The second order band-pass filter is implemented as a biquad filter. */
} ma_bpf2;
MA_API ma_result ma_bpf2_get_heap_size(const ma_bpf2_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_bpf2_init_preallocated(const ma_bpf2_config* pConfig, void* pHeap, ma_bpf2* pBPF);
MA_API ma_result ma_bpf2_init(const ma_bpf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf2* pBPF);
MA_API void ma_bpf2_uninit(ma_bpf2* pBPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_bpf2_reinit(const ma_bpf2_config* pConfig, ma_bpf2* pBPF);
MA_API ma_result ma_bpf2_process_pcm_frames(ma_bpf2* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_bpf2_get_latency(const ma_bpf2* pBPF);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double cutoffFrequency;
ma_uint32 order; /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
} ma_bpf_config;
MA_API ma_bpf_config ma_bpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 bpf2Count;
ma_bpf2* pBPF2;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_bpf;
MA_API ma_result ma_bpf_get_heap_size(const ma_bpf_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_bpf_init_preallocated(const ma_bpf_config* pConfig, void* pHeap, ma_bpf* pBPF);
MA_API ma_result ma_bpf_init(const ma_bpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf* pBPF);
MA_API void ma_bpf_uninit(ma_bpf* pBPF, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_bpf_reinit(const ma_bpf_config* pConfig, ma_bpf* pBPF);
MA_API ma_result ma_bpf_process_pcm_frames(ma_bpf* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_bpf_get_latency(const ma_bpf* pBPF);
/**************************************************************************************************************************************************************
Notching Filter
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double q;
double frequency;
} ma_notch2_config, ma_notch_config;
MA_API ma_notch2_config ma_notch2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency);
typedef struct
{
ma_biquad bq;
} ma_notch2;
MA_API ma_result ma_notch2_get_heap_size(const ma_notch2_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_notch2_init_preallocated(const ma_notch2_config* pConfig, void* pHeap, ma_notch2* pFilter);
MA_API ma_result ma_notch2_init(const ma_notch2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch2* pFilter);
MA_API void ma_notch2_uninit(ma_notch2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_notch2_reinit(const ma_notch2_config* pConfig, ma_notch2* pFilter);
MA_API ma_result ma_notch2_process_pcm_frames(ma_notch2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_notch2_get_latency(const ma_notch2* pFilter);
/**************************************************************************************************************************************************************
Peaking EQ Filter
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double gainDB;
double q;
double frequency;
} ma_peak2_config, ma_peak_config;
MA_API ma_peak2_config ma_peak2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
typedef struct
{
ma_biquad bq;
} ma_peak2;
MA_API ma_result ma_peak2_get_heap_size(const ma_peak2_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_peak2_init_preallocated(const ma_peak2_config* pConfig, void* pHeap, ma_peak2* pFilter);
MA_API ma_result ma_peak2_init(const ma_peak2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak2* pFilter);
MA_API void ma_peak2_uninit(ma_peak2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_peak2_reinit(const ma_peak2_config* pConfig, ma_peak2* pFilter);
MA_API ma_result ma_peak2_process_pcm_frames(ma_peak2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_peak2_get_latency(const ma_peak2* pFilter);
/**************************************************************************************************************************************************************
Low Shelf Filter
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double gainDB;
double shelfSlope;
double frequency;
} ma_loshelf2_config, ma_loshelf_config;
MA_API ma_loshelf2_config ma_loshelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency);
typedef struct
{
ma_biquad bq;
} ma_loshelf2;
MA_API ma_result ma_loshelf2_get_heap_size(const ma_loshelf2_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_loshelf2_init_preallocated(const ma_loshelf2_config* pConfig, void* pHeap, ma_loshelf2* pFilter);
MA_API ma_result ma_loshelf2_init(const ma_loshelf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf2* pFilter);
MA_API void ma_loshelf2_uninit(ma_loshelf2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_loshelf2_reinit(const ma_loshelf2_config* pConfig, ma_loshelf2* pFilter);
MA_API ma_result ma_loshelf2_process_pcm_frames(ma_loshelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_loshelf2_get_latency(const ma_loshelf2* pFilter);
/**************************************************************************************************************************************************************
High Shelf Filter
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
double gainDB;
double shelfSlope;
double frequency;
} ma_hishelf2_config, ma_hishelf_config;
MA_API ma_hishelf2_config ma_hishelf2_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double shelfSlope, double frequency);
typedef struct
{
ma_biquad bq;
} ma_hishelf2;
MA_API ma_result ma_hishelf2_get_heap_size(const ma_hishelf2_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_hishelf2_init_preallocated(const ma_hishelf2_config* pConfig, void* pHeap, ma_hishelf2* pFilter);
MA_API ma_result ma_hishelf2_init(const ma_hishelf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf2* pFilter);
MA_API void ma_hishelf2_uninit(ma_hishelf2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_hishelf2_reinit(const ma_hishelf2_config* pConfig, ma_hishelf2* pFilter);
MA_API ma_result ma_hishelf2_process_pcm_frames(ma_hishelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_hishelf2_get_latency(const ma_hishelf2* pFilter);
/*
Delay
*/
typedef struct
{
ma_uint32 channels;
ma_uint32 sampleRate;
ma_uint32 delayInFrames;
ma_bool32 delayStart; /* Set to true to delay the start of the output; false otherwise. */
float wet; /* 0..1. Default = 1. */
float dry; /* 0..1. Default = 1. */
float decay; /* 0..1. Default = 0 (no feedback). Feedback decay. Use this for echo. */
} ma_delay_config;
MA_API ma_delay_config ma_delay_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay);
typedef struct
{
ma_delay_config config;
ma_uint32 cursor; /* Feedback is written to this cursor. Always equal or in front of the read cursor. */
ma_uint32 bufferSizeInFrames; /* The maximum of config.startDelayInFrames and config.feedbackDelayInFrames. */
float* pBuffer;
} ma_delay;
MA_API ma_result ma_delay_init(const ma_delay_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay* pDelay);
MA_API void ma_delay_uninit(ma_delay* pDelay, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_delay_process_pcm_frames(ma_delay* pDelay, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount);
MA_API void ma_delay_set_wet(ma_delay* pDelay, float value);
MA_API float ma_delay_get_wet(const ma_delay* pDelay);
MA_API void ma_delay_set_dry(ma_delay* pDelay, float value);
MA_API float ma_delay_get_dry(const ma_delay* pDelay);
MA_API void ma_delay_set_decay(ma_delay* pDelay, float value);
MA_API float ma_delay_get_decay(const ma_delay* pDelay);
/* Gainer for smooth volume changes. */
typedef struct
{
ma_uint32 channels;
ma_uint32 smoothTimeInFrames;
} ma_gainer_config;
MA_API ma_gainer_config ma_gainer_config_init(ma_uint32 channels, ma_uint32 smoothTimeInFrames);
typedef struct
{
ma_gainer_config config;
ma_uint32 t;
float* pOldGains;
float* pNewGains;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_gainer;
MA_API ma_result ma_gainer_get_heap_size(const ma_gainer_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_gainer_init_preallocated(const ma_gainer_config* pConfig, void* pHeap, ma_gainer* pGainer);
MA_API ma_result ma_gainer_init(const ma_gainer_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_gainer* pGainer);
MA_API void ma_gainer_uninit(ma_gainer* pGainer, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_gainer_process_pcm_frames(ma_gainer* pGainer, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_result ma_gainer_set_gain(ma_gainer* pGainer, float newGain);
MA_API ma_result ma_gainer_set_gains(ma_gainer* pGainer, float* pNewGains);
/* Stereo panner. */
typedef enum
{
ma_pan_mode_balance = 0, /* Does not blend one side with the other. Technically just a balance. Compatible with other popular audio engines and therefore the default. */
ma_pan_mode_pan /* A true pan. The sound from one side will "move" to the other side and blend with it. */
} ma_pan_mode;
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_pan_mode mode;
float pan;
} ma_panner_config;
MA_API ma_panner_config ma_panner_config_init(ma_format format, ma_uint32 channels);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_pan_mode mode;
float pan; /* -1..1 where 0 is no pan, -1 is left side, +1 is right side. Defaults to 0. */
} ma_panner;
MA_API ma_result ma_panner_init(const ma_panner_config* pConfig, ma_panner* pPanner);
MA_API ma_result ma_panner_process_pcm_frames(ma_panner* pPanner, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API void ma_panner_set_mode(ma_panner* pPanner, ma_pan_mode mode);
MA_API ma_pan_mode ma_panner_get_mode(const ma_panner* pPanner);
MA_API void ma_panner_set_pan(ma_panner* pPanner, float pan);
MA_API float ma_panner_get_pan(const ma_panner* pPanner);
/* Fader. */
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
} ma_fader_config;
MA_API ma_fader_config ma_fader_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate);
typedef struct
{
ma_fader_config config;
float volumeBeg; /* If volumeBeg and volumeEnd is equal to 1, no fading happens (ma_fader_process_pcm_frames() will run as a passthrough). */
float volumeEnd;
ma_uint64 lengthInFrames; /* The total length of the fade. */
ma_uint64 cursorInFrames; /* The current time in frames. Incremented by ma_fader_process_pcm_frames(). */
} ma_fader;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
/* Spatializer. */
typedef struct
{
float x;
float y;
float z;
} ma_vec3f;
typedef enum
{
ma_attenuation_model_none, /* No distance attenuation and no spatialization. */
ma_attenuation_model_inverse, /* Equivalent to OpenAL's AL_INVERSE_DISTANCE_CLAMPED. */
ma_attenuation_model_linear, /* Linear attenuation. Equivalent to OpenAL's AL_LINEAR_DISTANCE_CLAMPED. */
ma_attenuation_model_exponential /* Exponential attenuation. Equivalent to OpenAL's AL_EXPONENT_DISTANCE_CLAMPED. */
} ma_attenuation_model;
typedef enum
{
ma_positioning_absolute,
ma_positioning_relative
} ma_positioning;
typedef enum
{
ma_handedness_right,
ma_handedness_left
} ma_handedness;
typedef struct
{
ma_uint32 channelsOut;
ma_channel* pChannelMapOut;
ma_handedness handedness; /* Defaults to right. Forward is -1 on the Z axis. In a left handed system, forward is +1 on the Z axis. */
float coneInnerAngleInRadians;
float coneOuterAngleInRadians;
float coneOuterGain;
float speedOfSound;
ma_vec3f worldUp;
} ma_spatializer_listener_config;
MA_API ma_spatializer_listener_config ma_spatializer_listener_config_init(ma_uint32 channelsOut);
typedef struct
{
ma_spatializer_listener_config config;
ma_vec3f position; /* The absolute position of the listener. */
ma_vec3f direction; /* The direction the listener is facing. The world up vector is config.worldUp. */
ma_vec3f velocity;
ma_bool32 isEnabled;
/* Memory management. */
ma_bool32 _ownsHeap;
void* _pHeap;
} ma_spatializer_listener;
MA_API ma_result ma_spatializer_listener_get_heap_size(const ma_spatializer_listener_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_spatializer_listener_init_preallocated(const ma_spatializer_listener_config* pConfig, void* pHeap, ma_spatializer_listener* pListener);
MA_API ma_result ma_spatializer_listener_init(const ma_spatializer_listener_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_spatializer_listener* pListener);
MA_API void ma_spatializer_listener_uninit(ma_spatializer_listener* pListener, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_channel* ma_spatializer_listener_get_channel_map(ma_spatializer_listener* pListener);
MA_API void ma_spatializer_listener_set_cone(ma_spatializer_listener* pListener, float innerAngleInRadians, float outerAngleInRadians, float outerGain);
MA_API void ma_spatializer_listener_get_cone(const ma_spatializer_listener* pListener, float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain);
MA_API void ma_spatializer_listener_set_position(ma_spatializer_listener* pListener, float x, float y, float z);
MA_API ma_vec3f ma_spatializer_listener_get_position(const ma_spatializer_listener* pListener);
MA_API void ma_spatializer_listener_set_direction(ma_spatializer_listener* pListener, float x, float y, float z);
MA_API ma_vec3f ma_spatializer_listener_get_direction(const ma_spatializer_listener* pListener);
MA_API void ma_spatializer_listener_set_velocity(ma_spatializer_listener* pListener, float x, float y, float z);
MA_API ma_vec3f ma_spatializer_listener_get_velocity(const ma_spatializer_listener* pListener);
MA_API void ma_spatializer_listener_set_speed_of_sound(ma_spatializer_listener* pListener, float speedOfSound);
MA_API float ma_spatializer_listener_get_speed_of_sound(const ma_spatializer_listener* pListener);
MA_API void ma_spatializer_listener_set_world_up(ma_spatializer_listener* pListener, float x, float y, float z);
MA_API ma_vec3f ma_spatializer_listener_get_world_up(const ma_spatializer_listener* pListener);
MA_API void ma_spatializer_listener_set_enabled(ma_spatializer_listener* pListener, ma_bool32 isEnabled);
MA_API ma_bool32 ma_spatializer_listener_is_enabled(const ma_spatializer_listener* pListener);
typedef struct
{
ma_uint32 channelsIn;
ma_uint32 channelsOut;
ma_channel* pChannelMapIn;
ma_attenuation_model attenuationModel;
ma_positioning positioning;
ma_handedness handedness; /* Defaults to right. Forward is -1 on the Z axis. In a left handed system, forward is +1 on the Z axis. */
float minGain;
float maxGain;
float minDistance;
float maxDistance;
float rolloff;
float coneInnerAngleInRadians;
float coneOuterAngleInRadians;
float coneOuterGain;
float dopplerFactor; /* Set to 0 to disable doppler effect. */
float directionalAttenuationFactor; /* Set to 0 to disable directional attenuation. */
ma_uint32 gainSmoothTimeInFrames; /* When the gain of a channel changes during spatialization, the transition will be linearly interpolated over this number of frames. */
} ma_spatializer_config;
MA_API ma_spatializer_config ma_spatializer_config_init(ma_uint32 channelsIn, ma_uint32 channelsOut);
typedef struct
{
ma_uint32 channelsIn;
ma_uint32 channelsOut;
ma_channel* pChannelMapIn;
ma_attenuation_model attenuationModel;
ma_positioning positioning;
ma_handedness handedness; /* Defaults to right. Forward is -1 on the Z axis. In a left handed system, forward is +1 on the Z axis. */
float minGain;
float maxGain;
float minDistance;
float maxDistance;
float rolloff;
float coneInnerAngleInRadians;
float coneOuterAngleInRadians;
float coneOuterGain;
float dopplerFactor; /* Set to 0 to disable doppler effect. */
float directionalAttenuationFactor; /* Set to 0 to disable directional attenuation. */
ma_uint32 gainSmoothTimeInFrames; /* When the gain of a channel changes during spatialization, the transition will be linearly interpolated over this number of frames. */
ma_vec3f position;
ma_vec3f direction;
ma_vec3f velocity; /* For doppler effect. */
float dopplerPitch; /* Will be updated by ma_spatializer_process_pcm_frames() and can be used by higher level functions to apply a pitch shift for doppler effect. */
ma_gainer gainer; /* For smooth gain transitions. */
float* pNewChannelGainsOut; /* An offset of _pHeap. Used by ma_spatializer_process_pcm_frames() to store new channel gains. The number of elements in this array is equal to config.channelsOut. */
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_spatializer;
MA_API ma_result ma_spatializer_get_heap_size(const ma_spatializer_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_spatializer_init_preallocated(const ma_spatializer_config* pConfig, void* pHeap, ma_spatializer* pSpatializer);
MA_API ma_result ma_spatializer_init(const ma_spatializer_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_spatializer* pSpatializer);
MA_API void ma_spatializer_uninit(ma_spatializer* pSpatializer, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer, ma_spatializer_listener* pListener, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_uint32 ma_spatializer_get_input_channels(const ma_spatializer* pSpatializer);
MA_API ma_uint32 ma_spatializer_get_output_channels(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_attenuation_model(ma_spatializer* pSpatializer, ma_attenuation_model attenuationModel);
MA_API ma_attenuation_model ma_spatializer_get_attenuation_model(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_positioning(ma_spatializer* pSpatializer, ma_positioning positioning);
MA_API ma_positioning ma_spatializer_get_positioning(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_rolloff(ma_spatializer* pSpatializer, float rolloff);
MA_API float ma_spatializer_get_rolloff(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_min_gain(ma_spatializer* pSpatializer, float minGain);
MA_API float ma_spatializer_get_min_gain(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_max_gain(ma_spatializer* pSpatializer, float maxGain);
MA_API float ma_spatializer_get_max_gain(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_min_distance(ma_spatializer* pSpatializer, float minDistance);
MA_API float ma_spatializer_get_min_distance(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_max_distance(ma_spatializer* pSpatializer, float maxDistance);
MA_API float ma_spatializer_get_max_distance(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_cone(ma_spatializer* pSpatializer, float innerAngleInRadians, float outerAngleInRadians, float outerGain);
MA_API void ma_spatializer_get_cone(const ma_spatializer* pSpatializer, float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain);
MA_API void ma_spatializer_set_doppler_factor(ma_spatializer* pSpatializer, float dopplerFactor);
MA_API float ma_spatializer_get_doppler_factor(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_directional_attenuation_factor(ma_spatializer* pSpatializer, float directionalAttenuationFactor);
MA_API float ma_spatializer_get_directional_attenuation_factor(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_position(ma_spatializer* pSpatializer, float x, float y, float z);
MA_API ma_vec3f ma_spatializer_get_position(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_direction(ma_spatializer* pSpatializer, float x, float y, float z);
MA_API ma_vec3f ma_spatializer_get_direction(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_set_velocity(ma_spatializer* pSpatializer, float x, float y, float z);
MA_API ma_vec3f ma_spatializer_get_velocity(const ma_spatializer* pSpatializer);
MA_API void ma_spatializer_get_relative_position_and_direction(const ma_spatializer* pSpatializer, const ma_spatializer_listener* pListener, ma_vec3f* pRelativePos, ma_vec3f* pRelativeDir);
/************************************************************************************************************************************************************
*************************************************************************************************************************************************************
DATA CONVERSION
===============
This section contains the APIs for data conversion. You will find everything here for channel mapping, sample format conversion, resampling, etc.
*************************************************************************************************************************************************************
************************************************************************************************************************************************************/
/**************************************************************************************************************************************************************
Resampling
**************************************************************************************************************************************************************/
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRateIn;
ma_uint32 sampleRateOut;
ma_uint32 lpfOrder; /* The low-pass filter order. Setting this to 0 will disable low-pass filtering. */
double lpfNyquistFactor; /* 0..1. Defaults to 1. 1 = Half the sampling frequency (Nyquist Frequency), 0.5 = Quarter the sampling frequency (half Nyquest Frequency), etc. */
} ma_linear_resampler_config;
MA_API ma_linear_resampler_config ma_linear_resampler_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut);
typedef struct
{
ma_linear_resampler_config config;
ma_uint32 inAdvanceInt;
ma_uint32 inAdvanceFrac;
ma_uint32 inTimeInt;
ma_uint32 inTimeFrac;
union
{
float* f32;
ma_int16* s16;
} x0; /* The previous input frame. */
union
{
float* f32;
ma_int16* s16;
} x1; /* The next input frame. */
ma_lpf lpf;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_linear_resampler;
MA_API ma_result ma_linear_resampler_get_heap_size(const ma_linear_resampler_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_linear_resampler_init_preallocated(const ma_linear_resampler_config* pConfig, void* pHeap, ma_linear_resampler* pResampler);
MA_API ma_result ma_linear_resampler_init(const ma_linear_resampler_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_linear_resampler* pResampler);
MA_API void ma_linear_resampler_uninit(ma_linear_resampler* pResampler, const ma_allocation_callbacks* pAllocationCallbacks);
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);
MA_API ma_result ma_linear_resampler_set_rate(ma_linear_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut);
MA_API ma_result ma_linear_resampler_set_rate_ratio(ma_linear_resampler* pResampler, float ratioInOut);
MA_API ma_uint64 ma_linear_resampler_get_input_latency(const ma_linear_resampler* pResampler);
MA_API ma_uint64 ma_linear_resampler_get_output_latency(const ma_linear_resampler* pResampler);
MA_API ma_result ma_linear_resampler_get_required_input_frame_count(const ma_linear_resampler* pResampler, ma_uint64 outputFrameCount, ma_uint64* pInputFrameCount);
MA_API ma_result ma_linear_resampler_get_expected_output_frame_count(const ma_linear_resampler* pResampler, ma_uint64 inputFrameCount, ma_uint64* pOutputFrameCount);
MA_API ma_result ma_linear_resampler_reset(ma_linear_resampler* pResampler);
typedef struct ma_resampler_config ma_resampler_config;
typedef void ma_resampling_backend;
typedef struct
{
ma_result (* onGetHeapSize )(void* pUserData, const ma_resampler_config* pConfig, size_t* pHeapSizeInBytes);
ma_result (* onInit )(void* pUserData, const ma_resampler_config* pConfig, void* pHeap, ma_resampling_backend** ppBackend);
void (* onUninit )(void* pUserData, ma_resampling_backend* pBackend, const ma_allocation_callbacks* pAllocationCallbacks);
ma_result (* onProcess )(void* pUserData, ma_resampling_backend* pBackend, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut);
ma_result (* onSetRate )(void* pUserData, ma_resampling_backend* pBackend, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut); /* Optional. Rate changes will be disabled. */
ma_uint64 (* onGetInputLatency )(void* pUserData, const ma_resampling_backend* pBackend); /* Optional. Latency will be reported as 0. */
ma_uint64 (* onGetOutputLatency )(void* pUserData, const ma_resampling_backend* pBackend); /* Optional. Latency will be reported as 0. */
ma_result (* onGetRequiredInputFrameCount )(void* pUserData, const ma_resampling_backend* pBackend, ma_uint64 outputFrameCount, ma_uint64* pInputFrameCount); /* Optional. Latency mitigation will be disabled. */
ma_result (* onGetExpectedOutputFrameCount)(void* pUserData, const ma_resampling_backend* pBackend, ma_uint64 inputFrameCount, ma_uint64* pOutputFrameCount); /* Optional. Latency mitigation will be disabled. */
ma_result (* onReset )(void* pUserData, ma_resampling_backend* pBackend);
} ma_resampling_backend_vtable;
typedef enum
{
ma_resample_algorithm_linear = 0, /* Fastest, lowest quality. Optional low-pass filtering. Default. */
ma_resample_algorithm_custom,
} ma_resample_algorithm;
struct ma_resampler_config
{
ma_format format; /* Must be either ma_format_f32 or ma_format_s16. */
ma_uint32 channels;
ma_uint32 sampleRateIn;
ma_uint32 sampleRateOut;
ma_resample_algorithm algorithm; /* When set to ma_resample_algorithm_custom, pBackendVTable will be used. */
ma_resampling_backend_vtable* pBackendVTable;
void* pBackendUserData;
struct
{
ma_uint32 lpfOrder;
} linear;
};
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);
typedef struct
{
ma_resampling_backend* pBackend;
ma_resampling_backend_vtable* pBackendVTable;
void* pBackendUserData;
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRateIn;
ma_uint32 sampleRateOut;
union
{
ma_linear_resampler linear;
} state; /* State for stock resamplers so we can avoid a malloc. For stock resamplers, pBackend will point here. */
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_resampler;
MA_API ma_result ma_resampler_get_heap_size(const ma_resampler_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_resampler_init_preallocated(const ma_resampler_config* pConfig, void* pHeap, ma_resampler* pResampler);
/*
Initializes a new resampler object from a config.
*/
MA_API ma_result ma_resampler_init(const ma_resampler_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_resampler* pResampler);
/*
Uninitializes a resampler.
*/
MA_API void ma_resampler_uninit(ma_resampler* pResampler, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Converts the given input data.
Both the input and output frames must be in the format specified in the config when the resampler was initilized.
On input, [pFrameCountOut] contains the number of output frames to process. On output it contains the number of output frames that
were actually processed, which may be less than the requested amount which will happen if there's not enough input data. You can use
ma_resampler_get_expected_output_frame_count() to know how many output frames will be processed for a given number of input frames.
On input, [pFrameCountIn] contains the number of input frames contained in [pFramesIn]. On output it contains the number of whole
input frames that were actually processed. You can use ma_resampler_get_required_input_frame_count() to know how many input frames
you should provide for a given number of output frames. [pFramesIn] can be NULL, in which case zeroes will be used instead.
If [pFramesOut] is NULL, a seek is performed. In this case, if [pFrameCountOut] is not NULL it will seek by the specified number of
output frames. Otherwise, if [pFramesCountOut] is NULL and [pFrameCountIn] is not NULL, it will seek by the specified number of input
frames. When seeking, [pFramesIn] is allowed to NULL, in which case the internal timing state will be updated, but no input will be
processed. In this case, any internal filter state will be updated as if zeroes were passed in.
It is an error for [pFramesOut] to be non-NULL and [pFrameCountOut] to be NULL.
It is an error for both [pFrameCountOut] and [pFrameCountIn] to be NULL.
*/
MA_API ma_result ma_resampler_process_pcm_frames(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut);
/*
Sets the input and output sample sample rate.
*/
MA_API ma_result ma_resampler_set_rate(ma_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut);
/*
Sets the input and output sample rate as a ratio.
The ration is in/out.
*/
MA_API ma_result ma_resampler_set_rate_ratio(ma_resampler* pResampler, float ratio);
/*
Retrieves the latency introduced by the resampler in input frames.
*/
MA_API ma_uint64 ma_resampler_get_input_latency(const ma_resampler* pResampler);
/*
Retrieves the latency introduced by the resampler in output frames.
*/
MA_API ma_uint64 ma_resampler_get_output_latency(const ma_resampler* pResampler);
/*
Calculates the number of whole input frames that would need to be read from the client in order to output the specified
number of output frames.
The returned value does not include cached input frames. It only returns the number of extra frames that would need to be
read from the input buffer in order to output the specified number of output frames.
*/
MA_API ma_result ma_resampler_get_required_input_frame_count(const ma_resampler* pResampler, ma_uint64 outputFrameCount, ma_uint64* pInputFrameCount);
/*
Calculates the number of whole output frames that would be output after fully reading and consuming the specified number of
input frames.
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
/**************************************************************************************************************************************************************
Channel Conversion
**************************************************************************************************************************************************************/
typedef enum
{
ma_channel_conversion_path_unknown,
ma_channel_conversion_path_passthrough,
ma_channel_conversion_path_mono_out, /* Converting to mono. */
ma_channel_conversion_path_mono_in, /* Converting from mono. */
ma_channel_conversion_path_shuffle, /* Simple shuffle. Will use this when all channels are present in both input and output channel maps, but just in a different order. */
ma_channel_conversion_path_weights /* Blended based on weights. */
} ma_channel_conversion_path;
typedef enum
{
ma_mono_expansion_mode_duplicate = 0, /* The default. */
ma_mono_expansion_mode_average, /* Average the mono channel across all channels. */
ma_mono_expansion_mode_stereo_only, /* Duplicate to the left and right channels only and ignore the others. */
ma_mono_expansion_mode_default = ma_mono_expansion_mode_duplicate
} ma_mono_expansion_mode;
typedef struct
{
ma_format format;
ma_uint32 channelsIn;
ma_uint32 channelsOut;
const ma_channel* pChannelMapIn;
const ma_channel* pChannelMapOut;
ma_channel_mix_mode mixingMode;
float** ppWeights; /* [in][out]. Only used when mixingMode is set to ma_channel_mix_mode_custom_weights. */
} ma_channel_converter_config;
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);
typedef struct
{
ma_format format;
ma_uint32 channelsIn;
ma_uint32 channelsOut;
ma_channel_mix_mode mixingMode;
ma_channel_conversion_path conversionPath;
ma_channel* pChannelMapIn;
ma_channel* pChannelMapOut;
ma_uint8* pShuffleTable; /* Indexed by output channel index. */
union
{
float** f32;
ma_int32** s16;
} weights; /* [in][out] */
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_channel_converter;
MA_API ma_result ma_channel_converter_get_heap_size(const ma_channel_converter_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_channel_converter_init_preallocated(const ma_channel_converter_config* pConfig, void* pHeap, ma_channel_converter* pConverter);
MA_API ma_result ma_channel_converter_init(const ma_channel_converter_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_channel_converter* pConverter);
MA_API void ma_channel_converter_uninit(ma_channel_converter* pConverter, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_channel_converter_process_pcm_frames(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API ma_result ma_channel_converter_get_input_channel_map(const ma_channel_converter* pConverter, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_channel_converter_get_output_channel_map(const ma_channel_converter* pConverter, ma_channel* pChannelMap, size_t channelMapCap);
/**************************************************************************************************************************************************************
Data Conversion
**************************************************************************************************************************************************************/
typedef struct
{
ma_format formatIn;
ma_format formatOut;
ma_uint32 channelsIn;
ma_uint32 channelsOut;
ma_uint32 sampleRateIn;
ma_uint32 sampleRateOut;
ma_channel* pChannelMapIn;
ma_channel* pChannelMapOut;
ma_dither_mode ditherMode;
ma_channel_mix_mode channelMixMode;
float** ppChannelWeights; /* [in][out]. Only used when mixingMode is set to ma_channel_mix_mode_custom_weights. */
ma_bool32 allowDynamicSampleRate;
ma_resampler_config resampling;
} ma_data_converter_config;
MA_API ma_data_converter_config ma_data_converter_config_init_default(void);
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);
typedef enum
{
ma_data_converter_execution_path_passthrough, /* No conversion. */
ma_data_converter_execution_path_format_only, /* Only format conversion. */
ma_data_converter_execution_path_channels_only, /* Only channel conversion. */
ma_data_converter_execution_path_resample_only, /* Only resampling. */
ma_data_converter_execution_path_resample_first, /* All conversions, but resample as the first step. */
ma_data_converter_execution_path_channels_first /* All conversions, but channels as the first step. */
} ma_data_converter_execution_path;
typedef struct
{
ma_format formatIn;
ma_format formatOut;
ma_uint32 channelsIn;
ma_uint32 channelsOut;
ma_uint32 sampleRateIn;
ma_uint32 sampleRateOut;
ma_dither_mode ditherMode;
ma_data_converter_execution_path executionPath; /* The execution path the data converter will follow when processing. */
ma_channel_converter channelConverter;
ma_resampler resampler;
ma_bool8 hasPreFormatConversion;
ma_bool8 hasPostFormatConversion;
ma_bool8 hasChannelConverter;
ma_bool8 hasResampler;
ma_bool8 isPassthrough;
/* Memory management. */
ma_bool8 _ownsHeap;
void* _pHeap;
} ma_data_converter;
MA_API ma_result ma_data_converter_get_heap_size(const ma_data_converter_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_data_converter_init_preallocated(const ma_data_converter_config* pConfig, void* pHeap, ma_data_converter* pConverter);
MA_API ma_result ma_data_converter_init(const ma_data_converter_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_converter* pConverter);
MA_API void ma_data_converter_uninit(ma_data_converter* pConverter, const ma_allocation_callbacks* pAllocationCallbacks);
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);
MA_API ma_result ma_data_converter_set_rate(ma_data_converter* pConverter, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut);
MA_API ma_result ma_data_converter_set_rate_ratio(ma_data_converter* pConverter, float ratioInOut);
MA_API ma_uint64 ma_data_converter_get_input_latency(const ma_data_converter* pConverter);
MA_API ma_uint64 ma_data_converter_get_output_latency(const ma_data_converter* pConverter);
MA_API ma_result ma_data_converter_get_required_input_frame_count(const ma_data_converter* pConverter, ma_uint64 outputFrameCount, ma_uint64* pInputFrameCount);
MA_API ma_result ma_data_converter_get_expected_output_frame_count(const ma_data_converter* pConverter, ma_uint64 inputFrameCount, ma_uint64* pOutputFrameCount);
MA_API ma_result ma_data_converter_get_input_channel_map(const ma_data_converter* pConverter, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_data_converter_get_output_channel_map(const ma_data_converter* pConverter, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_data_converter_reset(ma_data_converter* pConverter);
/************************************************************************************************************************************************************
Format Conversion
************************************************************************************************************************************************************/
MA_API void ma_pcm_u8_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_u8_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_u8_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_u8_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s16_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s16_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s16_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s16_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s24_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s24_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s24_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s24_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s32_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s32_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s32_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_s32_to_f32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_f32_to_u8(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_f32_to_s16(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_f32_to_s24(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_f32_to_s32(void* pOut, const void* pIn, ma_uint64 count, ma_dither_mode ditherMode);
MA_API void ma_pcm_convert(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode);
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);
/*
Deinterleaves an interleaved buffer.
*/
MA_API void ma_deinterleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void* pInterleavedPCMFrames, void** ppDeinterleavedPCMFrames);
/*
Interleaves a group of deinterleaved buffers.
*/
MA_API void ma_interleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void** ppDeinterleavedPCMFrames, void* pInterleavedPCMFrames);
/************************************************************************************************************************************************************
Channel Maps
************************************************************************************************************************************************************/
/*
This is used in the shuffle table to indicate that the channel index is undefined and should be ignored.
*/
#define MA_CHANNEL_INDEX_NULL 255
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
MA_API ma_bool32 ma_channel_map_is_valid(const ma_channel* pChannelMap, ma_uint32 channels);
/*
Helper for comparing two channel maps for equality.
This assumes the channel count is the same between the two.
Both channels map buffers must have a capacity of at least `channels`.
*/
MA_API ma_bool32 ma_channel_map_is_equal(const ma_channel* pChannelMapA, const ma_channel* pChannelMapB, ma_uint32 channels);
/*
Helper for determining if a channel map is blank (all channels set to MA_CHANNEL_NONE).
The channel map buffer must have a capacity of at least `channels`.
*/
MA_API ma_bool32 ma_channel_map_is_blank(const ma_channel* pChannelMap, ma_uint32 channels);
/*
Helper for determining whether or not a channel is present in the given channel map.
The channel map buffer must have a capacity of at least `channels`.
*/
MA_API ma_bool32 ma_channel_map_contains_channel_position(ma_uint32 channels, const ma_channel* pChannelMap, ma_channel channelPosition);
/************************************************************************************************************************************************************
Conversion Helpers
************************************************************************************************************************************************************/
/*
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
determine the required size of the output buffer. frameCountOut should be set to the capacity of pOut. If pOut is NULL, frameCountOut is
ignored.
A return value of 0 indicates an error.
This function is useful for one-off bulk conversions, but if you're streaming data you should use the ma_data_converter APIs instead.
*/
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);
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);
/************************************************************************************************************************************************************
Ring Buffer
************************************************************************************************************************************************************/
typedef struct
{
void* pBuffer;
ma_uint32 subbufferSizeInBytes;
ma_uint32 subbufferCount;
ma_uint32 subbufferStrideInBytes;
MA_ATOMIC(4, ma_uint32) encodedReadOffset; /* Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
MA_ATOMIC(4, ma_uint32) encodedWriteOffset; /* Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
ma_bool8 ownsBuffer; /* Used to know whether or not miniaudio is responsible for free()-ing the buffer. */
ma_bool8 clearOnWriteAcquire; /* When set, clears the acquired write buffer before returning from ma_rb_acquire_write(). */
ma_allocation_callbacks allocationCallbacks;
} ma_rb;
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);
MA_API ma_result ma_rb_init(size_t bufferSizeInBytes, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_rb* pRB);
MA_API void ma_rb_uninit(ma_rb* pRB);
MA_API void ma_rb_reset(ma_rb* pRB);
MA_API ma_result ma_rb_acquire_read(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut);
MA_API ma_result ma_rb_commit_read(ma_rb* pRB, size_t sizeInBytes);
MA_API ma_result ma_rb_acquire_write(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut);
MA_API ma_result ma_rb_commit_write(ma_rb* pRB, size_t sizeInBytes);
MA_API ma_result ma_rb_seek_read(ma_rb* pRB, size_t offsetInBytes);
MA_API ma_result ma_rb_seek_write(ma_rb* pRB, size_t offsetInBytes);
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 hi...
MA_API ma_uint32 ma_rb_available_read(ma_rb* pRB);
MA_API ma_uint32 ma_rb_available_write(ma_rb* pRB);
MA_API size_t ma_rb_get_subbuffer_size(ma_rb* pRB);
MA_API size_t ma_rb_get_subbuffer_stride(ma_rb* pRB);
MA_API size_t ma_rb_get_subbuffer_offset(ma_rb* pRB, size_t subbufferIndex);
MA_API void* ma_rb_get_subbuffer_ptr(ma_rb* pRB, size_t subbufferIndex, void* pBuffer);
typedef struct
{
ma_rb rb;
ma_format format;
ma_uint32 channels;
} ma_pcm_rb;
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* pAllocationCallba...
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);
MA_API void ma_pcm_rb_uninit(ma_pcm_rb* pRB);
MA_API void ma_pcm_rb_reset(ma_pcm_rb* pRB);
MA_API ma_result ma_pcm_rb_acquire_read(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut);
MA_API ma_result ma_pcm_rb_commit_read(ma_pcm_rb* pRB, ma_uint32 sizeInFrames);
MA_API ma_result ma_pcm_rb_acquire_write(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut);
MA_API ma_result ma_pcm_rb_commit_write(ma_pcm_rb* pRB, ma_uint32 sizeInFrames);
MA_API ma_result ma_pcm_rb_seek_read(ma_pcm_rb* pRB, ma_uint32 offsetInFrames);
MA_API ma_result ma_pcm_rb_seek_write(ma_pcm_rb* pRB, ma_uint32 offsetInFrames);
MA_API ma_int32 ma_pcm_rb_pointer_distance(ma_pcm_rb* pRB); /* Return value is in frames. */
MA_API ma_uint32 ma_pcm_rb_available_read(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_available_write(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_size(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_stride(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_offset(ma_pcm_rb* pRB, ma_uint32 subbufferIndex);
MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferIndex, void* pBuffer);
/*
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
capture device writes to it, and then a playback device reads from it.
At the moment this is just a simple naive implementation, but in the future I want to implement some dynamic resampling to seamlessly
handle desyncs. Note that the API is work in progress and may change at any time in any version.
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
in frames. The internal sample rate of the capture device is also needed in order to calculate the size.
*/
typedef struct
{
ma_pcm_rb rb;
} ma_duplex_rb;
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_dup...
MA_API ma_result ma_duplex_rb_uninit(ma_duplex_rb* pRB);
/************************************************************************************************************************************************************
Miscellaneous Helpers
************************************************************************************************************************************************************/
/*
Retrieves a human readable description of the given result code.
*/
MA_API const char* ma_result_description(ma_result result);
/*
malloc()
*/
MA_API void* ma_malloc(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks);
/*
calloc()
*/
MA_API void* ma_calloc(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks);
/*
realloc()
*/
MA_API void* ma_realloc(void* p, size_t sz, const ma_allocation_callbacks* pAllocationCallbacks);
/*
free()
*/
MA_API void ma_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Performs an aligned malloc, with the assumption that the alignment is a power of 2.
*/
MA_API void* ma_aligned_malloc(size_t sz, size_t alignment, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Free's an aligned malloc'd buffer.
*/
MA_API void ma_aligned_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Retrieves a friendly name for a format.
*/
MA_API const char* ma_get_format_name(ma_format format);
/*
Blends two frames in floating point format.
*/
MA_API void ma_blend_f32(float* pOut, float* pInA, float* pInB, float factor, ma_uint32 channels);
/*
Retrieves the size of a sample in bytes for the given format.
This API is efficient and is implemented using a lookup table.
Thread Safety: SAFE
This API is pure.
*/
MA_API ma_uint32 ma_get_bytes_per_sample(ma_format format);
static MA_INLINE ma_uint32 ma_get_bytes_per_frame(ma_format format, ma_uint32 channels) { return ma_get_bytes_per_sample(format) * channels; }
/*
Converts a log level to a string.
*/
MA_API const char* ma_log_level_to_string(ma_uint32 logLevel);
/************************************************************************************************************************************************************
Synchronization
************************************************************************************************************************************************************/
/*
Locks a spinlock.
*/
MA_API ma_result ma_spinlock_lock(volatile ma_spinlock* pSpinlock);
/*
Locks a spinlock, but does not yield() when looping.
*/
MA_API ma_result ma_spinlock_lock_noyield(volatile ma_spinlock* pSpinlock);
/*
Unlocks a spinlock.
*/
MA_API ma_result ma_spinlock_unlock(volatile ma_spinlock* pSpinlock);
#ifndef MA_NO_THREADING
/*
Creates a mutex.
A mutex must be created from a valid context. A mutex is initially unlocked.
*/
MA_API ma_result ma_mutex_init(ma_mutex* pMutex);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
/*
Initializes an auto-reset event.
*/
MA_API ma_result ma_event_init(ma_event* pEvent);
/*
Uninitializes an auto-reset event.
*/
MA_API void ma_event_uninit(ma_event* pEvent);
/*
Waits for the specified auto-reset event to become signalled.
*/
MA_API ma_result ma_event_wait(ma_event* pEvent);
/*
Signals the specified auto-reset event.
*/
MA_API ma_result ma_event_signal(ma_event* pEvent);
#endif /* MA_NO_THREADING */
/*
Fence
=====
This locks while the counter is larger than 0. Counter can be incremented and decremented by any
thread, but care needs to be taken when waiting. It is possible for one thread to acquire the
fence just as another thread returns from ma_fence_wait().
The idea behind a fence is to allow you to wait for a group of operations to complete. When an
operation starts, the counter is incremented which locks the fence. When the operation completes,
the fence will be released which decrements the counter. ma_fence_wait() will block until the
counter hits zero.
If threading is disabled, ma_fence_wait() will spin on the counter.
*/
typedef struct
{
#ifndef MA_NO_THREADING
ma_event e;
#endif
ma_uint32 counter;
} ma_fence;
MA_API ma_result ma_fence_init(ma_fence* pFence);
MA_API void ma_fence_uninit(ma_fence* pFence);
MA_API ma_result ma_fence_acquire(ma_fence* pFence); /* Increment counter. */
MA_API ma_result ma_fence_release(ma_fence* pFence); /* Decrement counter. */
MA_API ma_result ma_fence_wait(ma_fence* pFence); /* Wait for counter to reach 0. */
/*
Notification callback for asynchronous operations.
*/
typedef void ma_async_notification;
typedef struct
{
void (* onSignal)(ma_async_notification* pNotification);
} ma_async_notification_callbacks;
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification);
/*
Simple polling notification.
This just sets a variable when the notification has been signalled which is then polled with ma_async_notification_poll_is_signalled()
*/
typedef struct
{
ma_async_notification_callbacks cb;
ma_bool32 signalled;
} ma_async_notification_poll;
MA_API ma_result ma_async_notification_poll_init(ma_async_notification_poll* pNotificationPoll);
MA_API ma_bool32 ma_async_notification_poll_is_signalled(const ma_async_notification_poll* pNotificationPoll);
/*
Event Notification
This uses an ma_event. If threading is disabled (MA_NO_THREADING), initialization will fail.
*/
typedef struct
{
ma_async_notification_callbacks cb;
#ifndef MA_NO_THREADING
ma_event e;
#endif
} ma_async_notification_event;
MA_API ma_result ma_async_notification_event_init(ma_async_notification_event* pNotificationEvent);
MA_API ma_result ma_async_notification_event_uninit(ma_async_notification_event* pNotificationEvent);
MA_API ma_result ma_async_notification_event_wait(ma_async_notification_event* pNotificationEvent);
MA_API ma_result ma_async_notification_event_signal(ma_async_notification_event* pNotificationEvent);
/************************************************************************************************************************************************************
Job Queue
************************************************************************************************************************************************************/
/*
Slot Allocator
--------------
The idea of the slot allocator is for it to be used in conjunction with a fixed sized buffer. You use the slot allocator to allocator an index that can be used
as the insertion point for an object.
Slots are reference counted to help mitigate the ABA problem in the lock-free queue we use for tracking jobs.
The slot index is stored in the low 32 bits. The reference counter is stored in the high 32 bits:
+-----------------+-----------------+
| 32 Bits | 32 Bits |
+-----------------+-----------------+
| Reference Count | Slot Index |
+-----------------+-----------------+
*/
typedef struct
{
ma_uint32 capacity; /* The number of slots to make available. */
} ma_slot_allocator_config;
MA_API ma_slot_allocator_config ma_slot_allocator_config_init(ma_uint32 capacity);
typedef struct
{
MA_ATOMIC(4, ma_uint32) bitfield; /* Must be used atomically because the allocation and freeing routines need to make copies of this which must never be optimized away by the compiler. */
} ma_slot_allocator_group;
typedef struct
{
ma_slot_allocator_group* pGroups; /* Slots are grouped in chunks of 32. */
ma_uint32* pSlots; /* 32 bits for reference counting for ABA mitigation. */
ma_uint32 count; /* Allocation count. */
ma_uint32 capacity;
/* Memory management. */
ma_bool32 _ownsHeap;
void* _pHeap;
} ma_slot_allocator;
MA_API ma_result ma_slot_allocator_get_heap_size(const ma_slot_allocator_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_slot_allocator_init_preallocated(const ma_slot_allocator_config* pConfig, void* pHeap, ma_slot_allocator* pAllocator);
MA_API ma_result ma_slot_allocator_init(const ma_slot_allocator_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_slot_allocator* pAllocator);
MA_API void ma_slot_allocator_uninit(ma_slot_allocator* pAllocator, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_slot_allocator_alloc(ma_slot_allocator* pAllocator, ma_uint64* pSlot);
MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64 slot);
typedef struct ma_job ma_job;
/*
Callback for processing a job. Each job type will have their own processing callback which will be
called by ma_job_process().
*/
typedef ma_result (* ma_job_proc)(ma_job* pJob);
/* When a job type is added here an callback needs to be added go "g_jobVTable" in the implementation section. */
typedef enum
{
/* Miscellaneous. */
MA_JOB_TYPE_QUIT = 0,
MA_JOB_TYPE_CUSTOM,
/* Resource Manager. */
MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER_NODE,
MA_JOB_TYPE_RESOURCE_MANAGER_FREE_DATA_BUFFER_NODE,
MA_JOB_TYPE_RESOURCE_MANAGER_PAGE_DATA_BUFFER_NODE,
MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER,
MA_JOB_TYPE_RESOURCE_MANAGER_FREE_DATA_BUFFER,
MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_STREAM,
MA_JOB_TYPE_RESOURCE_MANAGER_FREE_DATA_STREAM,
MA_JOB_TYPE_RESOURCE_MANAGER_PAGE_DATA_STREAM,
MA_JOB_TYPE_RESOURCE_MANAGER_SEEK_DATA_STREAM,
/* Device. */
MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE,
/* Count. Must always be last. */
MA_JOB_TYPE_COUNT
} ma_job_type;
struct ma_job
{
union
{
struct
{
ma_uint16 code; /* Job type. */
ma_uint16 slot; /* Index into a ma_slot_allocator. */
ma_uint32 refcount;
} breakup;
ma_uint64 allocation;
} toc; /* 8 bytes. We encode the job code into the slot allocation data to save space. */
MA_ATOMIC(8, ma_uint64) next; /* refcount + slot for the next item. Does not include the job code. */
ma_uint32 order; /* Execution order. Used to create a data dependency and ensure a job is executed in order. Usage is contextual depending on the job type. */
union
{
/* Miscellaneous. */
struct
{
ma_job_proc proc;
ma_uintptr data0;
ma_uintptr data1;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
union
{
union
{
struct
{
/*ma_device**/ void* pDevice;
/*ma_device_type*/ ma_uint32 deviceType;
} reroute;
} aaudio;
} device;
} data;
};
MA_API ma_job ma_job_init(ma_uint16 code);
MA_API ma_result ma_job_process(ma_job* pJob);
/*
When set, ma_job_queue_next() will not wait and no semaphore will be signaled in
ma_job_queue_post(). ma_job_queue_next() will return MA_NO_DATA_AVAILABLE if nothing is available.
This flag should always be used for platforms that do not support multithreading.
*/
typedef enum
{
MA_JOB_QUEUE_FLAG_NON_BLOCKING = 0x00000001
} ma_job_queue_flags;
typedef struct
{
ma_uint32 flags;
ma_uint32 capacity; /* The maximum number of jobs that can fit in the queue at a time. */
} ma_job_queue_config;
MA_API ma_job_queue_config ma_job_queue_config_init(ma_uint32 flags, ma_uint32 capacity);
typedef struct
{
ma_uint32 flags; /* Flags passed in at initialization time. */
ma_uint32 capacity; /* The maximum number of jobs that can fit in the queue at a time. Set by the config. */
MA_ATOMIC(8, ma_uint64) head; /* The first item in the list. Required for removing from the top of the list. */
MA_ATOMIC(8, ma_uint64) tail; /* The last item in the list. Required for appending to the end of the list. */
#ifndef MA_NO_THREADING
ma_semaphore sem; /* Only used when MA_JOB_QUEUE_FLAG_NON_BLOCKING is unset. */
#endif
ma_slot_allocator allocator;
ma_job* pJobs;
#ifndef MA_USE_EXPERIMENTAL_LOCK_FREE_JOB_QUEUE
ma_spinlock lock;
#endif
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_job_queue;
MA_API ma_result ma_job_queue_get_heap_size(const ma_job_queue_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_job_queue_init_preallocated(const ma_job_queue_config* pConfig, void* pHeap, ma_job_queue* pQueue);
MA_API ma_result ma_job_queue_init(const ma_job_queue_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_job_queue* pQueue);
MA_API void ma_job_queue_uninit(ma_job_queue* pQueue, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_job_queue_post(ma_job_queue* pQueue, const ma_job* pJob);
MA_API ma_result ma_job_queue_next(ma_job_queue* pQueue, ma_job* pJob); /* Returns MA_CANCELLED if the next job is a quit job. */
/************************************************************************************************************************************************************
*************************************************************************************************************************************************************
DEVICE I/O
==========
This section contains the APIs for device playback and capture. Here is where you'll find ma_device_init(), etc.
*************************************************************************************************************************************************************
************************************************************************************************************************************************************/
#ifndef MA_NO_DEVICE_IO
/* Some backends are only supported on certain platforms. */
#if defined(MA_WIN32)
#define MA_SUPPORT_WASAPI
#if defined(MA_WIN32_DESKTOP) /* DirectSound and WinMM backends are only supported on desktops. */
#define MA_SUPPORT_DSOUND
#define MA_SUPPORT_WINMM
#define MA_SUPPORT_JACK /* JACK is technically supported on Windows, but I don't know how many people use it in practice... */
#endif
#endif
#if defined(MA_UNIX)
#if defined(MA_LINUX)
#if !defined(MA_ANDROID) /* ALSA is not supported on Android. */
#define MA_SUPPORT_ALSA
#endif
#endif
#if !defined(MA_BSD) && !defined(MA_ANDROID) && !defined(MA_EMSCRIPTEN)
#define MA_SUPPORT_PULSEAUDIO
#define MA_SUPPORT_JACK
#endif
#if defined(MA_ANDROID)
#define MA_SUPPORT_AAUDIO
#define MA_SUPPORT_OPENSL
#endif
#if defined(__OpenBSD__) /* <-- Change this to "#if defined(MA_BSD)" to enable sndio on all BSD flavors. */
#define MA_SUPPORT_SNDIO /* sndio is only supported on OpenBSD for now. May be expanded later if there's demand. */
#endif
#if defined(__NetBSD__) || defined(__OpenBSD__)
#define MA_SUPPORT_AUDIO4 /* Only support audio(4) on platforms with known support. */
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
#define MA_SUPPORT_OSS /* Only support OSS on specific platforms with known support. */
#endif
#endif
#if defined(MA_APPLE)
#define MA_SUPPORT_COREAUDIO
#endif
#if defined(MA_EMSCRIPTEN)
#define MA_SUPPORT_WEBAUDIO
#endif
/* All platforms should support custom backends. */
#define MA_SUPPORT_CUSTOM
/* Explicitly disable the Null backend for Emscripten because it uses a background thread which is not properly supported right now. */
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#if defined(MA_SUPPORT_SNDIO) && !defined(MA_NO_SNDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_SNDIO))
#define MA_HAS_SNDIO
#endif
#if defined(MA_SUPPORT_AUDIO4) && !defined(MA_NO_AUDIO4) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_AUDIO4))
#define MA_HAS_AUDIO4
#endif
#if defined(MA_SUPPORT_OSS) && !defined(MA_NO_OSS) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_OSS))
#define MA_HAS_OSS
#endif
#if defined(MA_SUPPORT_AAUDIO) && !defined(MA_NO_AAUDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_AAUDIO))
#define MA_HAS_AAUDIO
#endif
#if defined(MA_SUPPORT_OPENSL) && !defined(MA_NO_OPENSL) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_OPENSL))
#define MA_HAS_OPENSL
#endif
#if defined(MA_SUPPORT_WEBAUDIO) && !defined(MA_NO_WEBAUDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_WEBAUDIO))
#define MA_HAS_WEBAUDIO
#endif
#if defined(MA_SUPPORT_CUSTOM) && !defined(MA_NO_CUSTOM) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_CUSTOM))
#define MA_HAS_CUSTOM
#endif
#if defined(MA_SUPPORT_NULL) && !defined(MA_NO_NULL) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_NULL))
#define MA_HAS_NULL
#endif
typedef enum
{
ma_device_state_uninitialized = 0,
ma_device_state_stopped = 1, /* The device's default state after initialization. */
ma_device_state_started = 2, /* The device is started and is requesting and/or delivering audio data. */
ma_device_state_starting = 3, /* Transitioning from a stopped state to started. */
ma_device_state_stopping = 4 /* Transitioning from a started state to stopped. */
} ma_device_state;
#ifdef MA_SUPPORT_WASAPI
/* We need a IMMNotificationClient object for WASAPI. */
typedef struct
{
void* lpVtbl;
ma_uint32 counter;
ma_device* pDevice;
} ma_IMMNotificationClient;
#endif
/* Backend enums must be in priority order. */
typedef enum
{
ma_backend_wasapi,
ma_backend_dsound,
ma_backend_winmm,
ma_backend_coreaudio,
ma_backend_sndio,
ma_backend_audio4,
ma_backend_oss,
ma_backend_pulseaudio,
ma_backend_alsa,
ma_backend_jack,
ma_backend_aaudio,
ma_backend_opensl,
ma_backend_webaudio,
ma_backend_custom, /* <-- Custom backend, with callbacks defined by the context config. */
ma_backend_null /* <-- Must always be the last item. Lowest priority, and used as the terminator for backend enumeration. */
} ma_backend;
#define MA_BACKEND_COUNT (ma_backend_null+1)
/*
Device job thread. This is used by backends that require asynchronous processing of certain
operations. It is not used by all backends.
The device job thread is made up of a thread and a job queue. You can post a job to the thread with
ma_device_job_thread_post(). The thread will do the processing of the job.
*/
typedef struct
{
ma_bool32 noThread; /* Set this to true if you want to process jobs yourself. */
ma_uint32 jobQueueCapacity;
ma_uint32 jobQueueFlags;
} ma_device_job_thread_config;
MA_API ma_device_job_thread_config ma_device_job_thread_config_init(void);
typedef struct
{
ma_thread thread;
ma_job_queue jobQueue;
ma_bool32 _hasThread;
} ma_device_job_thread;
MA_API ma_result ma_device_job_thread_init(const ma_device_job_thread_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_device_job_thread* pJobThread);
MA_API void ma_device_job_thread_uninit(ma_device_job_thread* pJobThread, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_device_job_thread_post(ma_device_job_thread* pJobThread, const ma_job* pJob);
MA_API ma_result ma_device_job_thread_next(ma_device_job_thread* pJobThread, ma_job* pJob);
/* Device notification types. */
typedef enum
{
ma_device_notification_type_started,
ma_device_notification_type_stopped,
ma_device_notification_type_rerouted,
ma_device_notification_type_interruption_began,
ma_device_notification_type_interruption_ended
} ma_device_notification_type;
typedef struct
{
ma_device* pDevice;
ma_device_notification_type type;
union
{
struct
{
int _unused;
} started;
struct
{
int _unused;
} stopped;
struct
{
int _unused;
} rerouted;
struct
{
int _unused;
} interruption;
} data;
} ma_device_notification;
/*
The notification callback for when the application should be notified of a change to the device.
This callback is used for notifying the application of changes such as when the device has started,
stopped, rerouted or an interruption has occurred. Note that not all backends will post all
notification types. For example, some backends will perform automatic stream routing without any
kind of notification to the host program which means miniaudio will never know about it and will
never be able to fire the rerouted notification. You should keep this in mind when designing your
program.
The stopped notification will *not* get fired when a device is rerouted.
Parameters
----------
pNotification (in)
A pointer to a structure containing information about the event. Use the `pDevice` member of
this object to retrieve the relevant device. The `type` member can be used to discriminate
against each of the notification types.
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_aaudio_usage_voice_communication, /* AAUDIO_USAGE_VOICE_COMMUNICATION */
ma_aaudio_usage_voice_communication_signalling /* AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING */
} ma_aaudio_usage;
/* AAudio content types. */
typedef enum
{
ma_aaudio_content_type_default = 0, /* Leaves the content type unset. */
ma_aaudio_content_type_movie, /* AAUDIO_CONTENT_TYPE_MOVIE */
ma_aaudio_content_type_music, /* AAUDIO_CONTENT_TYPE_MUSIC */
ma_aaudio_content_type_sonification, /* AAUDIO_CONTENT_TYPE_SONIFICATION */
ma_aaudio_content_type_speech /* AAUDIO_CONTENT_TYPE_SPEECH */
} ma_aaudio_content_type;
/* AAudio input presets. */
typedef enum
{
ma_aaudio_input_preset_default = 0, /* Leaves the input preset unset. */
ma_aaudio_input_preset_generic, /* AAUDIO_INPUT_PRESET_GENERIC */
ma_aaudio_input_preset_camcorder, /* AAUDIO_INPUT_PRESET_CAMCORDER */
ma_aaudio_input_preset_unprocessed, /* AAUDIO_INPUT_PRESET_UNPROCESSED */
ma_aaudio_input_preset_voice_recognition, /* AAUDIO_INPUT_PRESET_VOICE_RECOGNITION */
ma_aaudio_input_preset_voice_communication, /* AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION */
ma_aaudio_input_preset_voice_performance /* AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE */
} ma_aaudio_input_preset;
typedef union
{
ma_int64 counter;
double counterD;
} ma_timer;
typedef union
{
wchar_t wasapi[64]; /* WASAPI uses a wchar_t string for identification. */
ma_uint8 dsound[16]; /* DirectSound uses a GUID for identification. */
/*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. */
char alsa[256]; /* ALSA uses a name string for identification. */
char pulse[256]; /* PulseAudio uses a name string for identification. */
int jack; /* JACK always uses default devices. */
char coreaudio[256]; /* Core Audio uses a string for identification. */
char sndio[256]; /* "snd/0", etc. */
char audio4[256]; /* "/dev/audio", etc. */
char oss[64]; /* "dev/dsp0", etc. "dev/dsp" for the default device. */
ma_int32 aaudio; /* AAudio uses a 32-bit integer for identification. */
ma_uint32 opensl; /* OpenSL|ES uses a 32-bit unsigned integer for identification. */
char webaudio[32]; /* Web Audio always uses default devices for now, but if this changes it'll be a GUID. */
union
{
int i;
char s[256];
void* p;
} custom; /* The custom backend could be anything. Give them a few options. */
int nullbackend; /* The null backend uses an integer for device IDs. */
} ma_device_id;
typedef struct ma_context_config ma_context_config;
typedef struct ma_device_config ma_device_config;
typedef struct ma_backend_callbacks ma_backend_callbacks;
#define MA_DATA_FORMAT_FLAG_EXCLUSIVE_MODE (1U << 1) /* If set, this is supported in exclusive mode. Otherwise not natively supported by exclusive mode. */
#ifndef MA_MAX_DEVICE_NAME_LENGTH
#define MA_MAX_DEVICE_NAME_LENGTH 255
#endif
typedef struct
{
/* Basic info. This is the only information guaranteed to be filled in during device enumeration. */
ma_device_id id;
char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; /* +1 for null terminator. */
ma_bool32 isDefault;
ma_uint32 nativeDataFormatCount;
struct
{
ma_format format; /* Sample format. If set to ma_format_unknown, all sample formats are supported. */
ma_uint32 channels; /* If set to 0, all channels are supported. */
ma_uint32 sampleRate; /* If set to 0, all sample rates are supported. */
ma_uint32 flags; /* A combination of MA_DATA_FORMAT_FLAG_* flags. */
} 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. */
} ma_device_info;
struct ma_device_config
{
ma_device_type deviceType;
ma_uint32 sampleRate;
ma_uint32 periodSizeInFrames;
ma_uint32 periodSizeInMilliseconds;
ma_uint32 periods;
ma_performance_profile performanceProfile;
ma_bool8 noPreSilencedOutputBuffer; /* When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to silence. */
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. */
ma_bool8 noDisableDenormals; /* Do not disable denormals when firing the data callback. */
ma_bool8 noFixedSizedCallback; /* Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callb...
ma_device_data_proc dataCallback;
ma_device_notification_proc notificationCallback;
ma_stop_proc stopCallback;
void* pUserData;
ma_resampler_config resampling;
struct
{
const ma_device_id* pDeviceID;
ma_format format;
ma_uint32 channels;
ma_channel* pChannelMap;
ma_channel_mix_mode channelMixMode;
ma_share_mode shareMode;
} playback;
struct
{
const ma_device_id* pDeviceID;
ma_format format;
ma_uint32 channels;
ma_channel* pChannelMap;
ma_channel_mix_mode channelMixMode;
ma_share_mode shareMode;
} capture;
struct
{
ma_bool8 noAutoConvertSRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM. */
ma_bool8 noDefaultQualitySRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY. */
ma_bool8 noAutoStreamRouting; /* Disables automatic stream routing. */
ma_bool8 noHardwareOffloading; /* Disables WASAPI's hardware offloading feature. */
} wasapi;
struct
{
ma_bool32 noMMap; /* Disables MMap mode. */
ma_bool32 noAutoFormat; /* Opens the ALSA device with SND_PCM_NO_AUTO_FORMAT. */
ma_bool32 noAutoChannels; /* Opens the ALSA device with SND_PCM_NO_AUTO_CHANNELS. */
ma_bool32 noAutoResample; /* Opens the ALSA device with SND_PCM_NO_AUTO_RESAMPLE. */
} alsa;
struct
{
const char* pStreamNamePlayback;
const char* pStreamNameCapture;
} pulse;
struct
{
ma_bool32 allowNominalSampleRateChange; /* Desktop only. When enabled, allows changing of the sample rate at the operating system level. */
} coreaudio;
struct
{
ma_opensl_stream_type streamType;
ma_opensl_recording_preset recordingPreset;
} opensl;
struct
{
ma_aaudio_usage usage;
ma_aaudio_content_type contentType;
ma_aaudio_input_preset inputPreset;
ma_bool32 noAutoStartAfterReroute;
} aaudio;
};
/*
The callback for handling device enumeration. This is fired from `ma_context_enumerated_devices()`.
Parameters
----------
pContext (in)
A pointer to the context performing the enumeration.
deviceType (in)
The type of the device being enumerated. This will always be either `ma_device_type_playback` or `ma_device_type_capture`.
pInfo (in)
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,
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
is too inefficient.
pUserData (in)
The user data pointer passed into `ma_context_enumerate_devices()`.
*/
typedef ma_bool32 (* ma_enum_devices_callback_proc)(ma_context* pContext, ma_device_type deviceType, const ma_device_info* pInfo, void* pUserData);
/*
Describes some basic details about a playback or capture device.
*/
typedef struct
{
const ma_device_id* pDeviceID;
ma_share_mode shareMode;
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
ma_channel channelMap[MA_MAX_CHANNELS];
ma_uint32 periodSizeInFrames;
ma_uint32 periodSizeInMilliseconds;
ma_uint32 periodCount;
} ma_device_descriptor;
/*
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
to many devices. A device is created from a context.
The general flow goes like this:
1) A context is created with `onContextInit()`
1a) Available devices can be enumerated with `onContextEnumerateDevices()` if required.
1b) Detailed information about a device can be queried with `onContextGetDeviceInfo()` if required.
2) A device is created from the context that was created in the first step using `onDeviceInit()`, and optionally a device ID that was
selected from device enumeration via `onContextEnumerateDevices()`.
3) A device is started or stopped with `onDeviceStart()` / `onDeviceStop()`
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
to `onDeviceInit()`. Conversion between the device's native format and the format requested by the application will be handled by
miniaudio internally.
Initialization of the context is quite simple. You need to do any necessary initialization of internal objects and then output the
callbacks defined in this structure.
Once the context has been initialized you can initialize a device. Before doing so, however, the application may want to know which
physical devices are available. This is where `onContextEnumerateDevices()` comes in. This is fairly simple. For each device, fire the
given callback with, at a minimum, the basic information filled out in `ma_device_info`. When the callback returns `MA_FALSE`, enumeration
needs to stop and the `onContextEnumerateDevices()` function returns with a success code.
Detailed device information can be retrieved from a device ID using `onContextGetDeviceInfo()`. This takes as input the device type and ID,
and on output returns detailed information about the device in `ma_device_info`. The `onContextGetDeviceInfo()` callback must handle the
case when the device ID is NULL, in which case information about the default device needs to be retrieved.
Once the context has been created and the device ID retrieved (if using anything other than the default device), the device can be created.
This is a little bit more complicated than initialization of the context due to it's more complicated configuration. When initializing a
device, a duplex device may be requested. This means a separate data format needs to be specified for both playback and capture. On input,
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
the requested format. The conversion between the format requested by the application and the device's native format will be handled
internally by miniaudio.
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
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
sample rate. For the channel map, the default should be used when `ma_channel_map_is_blank()` returns true (all channels set to
`MA_CHANNEL_NONE`). On input, the `periodSizeInFrames` or `periodSizeInMilliseconds` option should always be set. The backend should
inspect both of these variables. If `periodSizeInFrames` is set, it should take priority, otherwise it needs to be derived from the period
size in milliseconds (`periodSizeInMilliseconds`) and the sample rate, keeping in mind that the sample rate may be 0, in which case the
sample rate will need to be determined before calculating the period size in frames. On output, all members of the `ma_device_data_format`
object should be set to a valid value, except for `periodSizeInMilliseconds` which is optional (`periodSizeInFrames` *must* be set).
Starting and stopping of the device is done with `onDeviceStart()` and `onDeviceStop()` and should be self-explanatory. If the backend uses
asynchronous reading and writing, `onDeviceStart()` and `onDeviceStop()` should always be implemented.
The handling of data delivery between the application and the device is the most complicated part of the process. To make this a bit
easier, some helper callbacks are available. If the backend uses a blocking read/write style of API, the `onDeviceRead()` and
`onDeviceWrite()` callbacks can optionally be implemented. These are blocking and work just like reading and writing from a file. If the
backend uses a callback for data delivery, that callback must call `ma_device_handle_backend_data_callback()` from within it's callback.
This allows miniaudio to then process any necessary data conversion and then pass it to the miniaudio data callback.
If the backend requires absolute flexibility with it's data delivery, it can optionally implement the `onDeviceDataLoop()` callback
which will allow it to implement the logic that will run on the audio thread. This is much more advanced and is completely optional.
The audio thread should run data delivery logic in a loop while `ma_device_get_state() == ma_device_state_started` and no errors have been
encounted. Do not start or stop the device here. That will be handled from outside the `onDeviceDataLoop()` callback.
The invocation of the `onDeviceDataLoop()` callback will be handled by miniaudio. When you start the device, miniaudio will fire this
callback. When the device is stopped, the `ma_device_get_state() == ma_device_state_started` condition will fail and the loop will be terminated
which will then fall through to the part that stops the device. For an example on how to implement the `onDeviceDataLoop()` callback,
look at `ma_device_audio_thread__default_read_write()`. Implement the `onDeviceDataLoopWakeup()` callback if you need a mechanism to
wake up the audio thread.
If the backend supports an optimized retrieval of device information from an initialized `ma_device` object, it should implement the
`onDeviceGetInfo()` callback. This is optional, in which case it will fall back to `onContextGetDeviceInfo()` which is less efficient.
*/
struct ma_backend_callbacks
{
ma_result (* onContextInit)(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks);
ma_result (* onContextUninit)(ma_context* pContext);
ma_result (* onContextEnumerateDevices)(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData);
ma_result (* onContextGetDeviceInfo)(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo);
ma_result (* onDeviceInit)(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture);
ma_result (* onDeviceUninit)(ma_device* pDevice);
ma_result (* onDeviceStart)(ma_device* pDevice);
ma_result (* onDeviceStop)(ma_device* pDevice);
ma_result (* onDeviceRead)(ma_device* pDevice, void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesRead);
ma_result (* onDeviceWrite)(ma_device* pDevice, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten);
ma_result (* onDeviceDataLoop)(ma_device* pDevice);
ma_result (* onDeviceDataLoopWakeup)(ma_device* pDevice);
ma_result (* onDeviceGetInfo)(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo);
};
struct ma_context_config
{
ma_log* pLog;
ma_thread_priority threadPriority;
size_t threadStackSize;
void* pUserData;
ma_allocation_callbacks allocationCallbacks;
struct
{
ma_bool32 useVerboseDeviceEnumeration;
} alsa;
struct
{
const char* pApplicationName;
const char* pServerName;
ma_bool32 tryAutoSpawn; /* Enables autospawning of the PulseAudio daemon if necessary. */
} pulse;
struct
{
ma_ios_session_category sessionCategory;
ma_uint32 sessionCategoryOptions;
ma_bool32 noAudioSessionActivate; /* iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:true] on initialization. */
ma_bool32 noAudioSessionDeactivate; /* iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:false] on uninitialization. */
} coreaudio;
struct
{
const char* pClientName;
ma_bool32 tryStartServer;
} jack;
ma_backend_callbacks custom;
};
/* WASAPI specific structure for some commands which must run on a common thread due to bugs in WASAPI. */
typedef struct
{
int code;
ma_event* pEvent; /* This will be signalled when the event is complete. */
union
{
struct
{
int _unused;
} quit;
struct
{
ma_device_type deviceType;
void* pAudioClient;
void** ppAudioClientService;
ma_result* pResult; /* The result from creating the audio client service. */
} createAudioClient;
struct
{
ma_device* pDevice;
ma_device_type deviceType;
} releaseAudioClient;
} data;
} ma_context_command__wasapi;
struct ma_context
{
ma_backend_callbacks callbacks;
ma_backend backend; /* DirectSound, ALSA, etc. */
ma_log* pLog;
ma_log log; /* Only used if the log is owned by the context. The pLog member will be set to &log in this case. */
ma_thread_priority threadPriority;
size_t threadStackSize;
void* pUserData;
ma_allocation_callbacks allocationCallbacks;
ma_mutex deviceEnumLock; /* Used to make ma_context_get_devices() thread safe. */
ma_mutex deviceInfoLock; /* Used to make ma_context_get_device_info() thread safe. */
ma_uint32 deviceInfoCapacity; /* Total capacity of pDeviceInfos. */
ma_uint32 playbackDeviceInfoCount;
ma_uint32 captureDeviceInfoCount;
ma_device_info* pDeviceInfos; /* Playback devices first, then capture. */
union
{
#ifdef MA_SUPPORT_WASAPI
struct
{
ma_thread commandThread;
ma_mutex commandLock;
ma_semaphore commandSem;
ma_uint32 commandIndex;
ma_uint32 commandCount;
ma_context_command__wasapi commands[4];
} wasapi;
#endif
#ifdef MA_SUPPORT_DSOUND
struct
{
ma_handle hDSoundDLL;
ma_proc DirectSoundCreate;
ma_proc DirectSoundEnumerateA;
ma_proc DirectSoundCaptureCreate;
ma_proc DirectSoundCaptureEnumerateA;
} dsound;
#endif
#ifdef MA_SUPPORT_WINMM
struct
{
ma_handle hWinMM;
ma_proc waveOutGetNumDevs;
ma_proc waveOutGetDevCapsA;
ma_proc waveOutOpen;
ma_proc waveOutClose;
ma_proc waveOutPrepareHeader;
ma_proc waveOutUnprepareHeader;
ma_proc waveOutWrite;
ma_proc waveOutReset;
ma_proc waveInGetNumDevs;
ma_proc waveInGetDevCapsA;
ma_proc waveInOpen;
ma_proc waveInClose;
ma_proc waveInPrepareHeader;
ma_proc waveInUnprepareHeader;
ma_proc waveInAddBuffer;
ma_proc waveInStart;
ma_proc waveInReset;
} winmm;
#endif
#ifdef MA_SUPPORT_ALSA
struct
{
ma_handle asoundSO;
ma_proc snd_pcm_open;
ma_proc snd_pcm_close;
ma_proc snd_pcm_hw_params_sizeof;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_proc pthread_attr_destroy;
ma_proc pthread_attr_setschedpolicy;
ma_proc pthread_attr_getschedparam;
ma_proc pthread_attr_setschedparam;
} posix;
#endif
int _unused;
};
};
struct ma_device
{
ma_context* pContext;
ma_device_type type;
ma_uint32 sampleRate;
MA_ATOMIC(4, ma_device_state) state; /* The state of the device is variable and can change at any time on any thread. Must be used atomically. */
ma_device_data_proc onData; /* Set once at initialization time and should not be changed after. */
ma_device_notification_proc onNotification; /* Set once at initialization time and should not be changed after. */
ma_stop_proc onStop; /* DEPRECATED. Use the notification callback instead. Set once at initialization time and should not be changed after. */
void* pUserData; /* Application defined data. */
ma_mutex startStopLock;
ma_event wakeupEvent;
ma_event startEvent;
ma_event stopEvent;
ma_thread thread;
ma_result workResult; /* This is set by the worker thread after it's finished doing a job. */
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(). */
ma_bool8 noPreSilencedOutputBuffer;
ma_bool8 noClip;
ma_bool8 noDisableDenormals;
ma_bool8 noFixedSizedCallback;
MA_ATOMIC(4, float) masterVolumeFactor; /* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
ma_duplex_rb duplexRB; /* Intermediary buffer for duplex device on asynchronous backends. */
struct
{
ma_resample_algorithm algorithm;
ma_resampling_backend_vtable* pBackendVTable;
void* pBackendUserData;
struct
{
ma_uint32 lpfOrder;
} linear;
} resampling;
struct
{
ma_device_id* pID; /* Set to NULL if using default ID, otherwise set to the address of "id". */
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. */
char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; /* Maybe temporary. Likely to be replaced with a query API. */
ma_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */
ma_format format;
ma_uint32 channels;
ma_channel channelMap[MA_MAX_CHANNELS];
ma_format internalFormat;
ma_uint32 internalChannels;
ma_uint32 internalSampleRate;
ma_channel internalChannelMap[MA_MAX_CHANNELS];
ma_uint32 internalPeriodSizeInFrames;
ma_uint32 internalPeriods;
ma_channel_mix_mode channelMixMode;
ma_data_converter converter;
void* pIntermediaryBuffer; /* For implementing fixed sized buffer callbacks. Will be null if using variable sized callbacks. */
ma_uint32 intermediaryBufferCap;
ma_uint32 intermediaryBufferLen; /* How many valid frames are sitting in the intermediary buffer. */
void* pInputCache; /* In external format. Can be null. */
ma_uint64 inputCacheCap;
ma_uint64 inputCacheConsumed;
ma_uint64 inputCacheRemaining;
} playback;
struct
{
ma_device_id* pID; /* Set to NULL if using default ID, otherwise set to the address of "id". */
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. */
char name[MA_MAX_DEVICE_NAME_LENGTH + 1]; /* Maybe temporary. Likely to be replaced with a query API. */
ma_share_mode shareMode; /* Set to whatever was passed in when the device was initialized. */
ma_format format;
ma_uint32 channels;
ma_channel channelMap[MA_MAX_CHANNELS];
ma_format internalFormat;
ma_uint32 internalChannels;
ma_uint32 internalSampleRate;
ma_channel internalChannelMap[MA_MAX_CHANNELS];
ma_uint32 internalPeriodSizeInFrames;
ma_uint32 internalPeriods;
ma_channel_mix_mode channelMixMode;
ma_data_converter converter;
void* pIntermediaryBuffer; /* For implementing fixed sized buffer callbacks. Will be null if using variable sized callbacks. */
ma_uint32 intermediaryBufferCap;
ma_uint32 intermediaryBufferLen; /* How many valid frames are sitting in the intermediary buffer. */
} capture;
union
{
#ifdef MA_SUPPORT_WASAPI
struct
{
/*IAudioClient**/ ma_ptr pAudioClientPlayback;
/*IAudioClient**/ ma_ptr pAudioClientCapture;
/*IAudioRenderClient**/ ma_ptr pRenderClient;
/*IAudioCaptureClient**/ ma_ptr pCaptureClient;
/*IMMDeviceEnumerator**/ ma_ptr pDeviceEnumerator; /* Used for IMMNotificationClient notifications. Required for detecting default device changes. */
ma_IMMNotificationClient notificationClient;
/*HANDLE*/ ma_handle hEventPlayback; /* Auto reset. Initialized to signaled. */
/*HANDLE*/ ma_handle hEventCapture; /* Auto reset. Initialized to unsignaled. */
ma_uint32 actualBufferSizeInFramesPlayback; /* 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...
ma_uint32 actualBufferSizeInFramesCapture;
ma_uint32 originalPeriodSizeInFrames;
ma_uint32 originalPeriodSizeInMilliseconds;
ma_uint32 originalPeriods;
ma_performance_profile originalPerformanceProfile;
ma_uint32 periodSizeInFramesPlayback;
ma_uint32 periodSizeInFramesCapture;
void* pMappedBufferCapture;
ma_uint32 mappedBufferCaptureCap;
ma_uint32 mappedBufferCaptureLen;
void* pMappedBufferPlayback;
ma_uint32 mappedBufferPlaybackCap;
ma_uint32 mappedBufferPlaybackLen;
MA_ATOMIC(4, ma_bool32) isStartedCapture; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */
MA_ATOMIC(4, ma_bool32) isStartedPlayback; /* Can be read and written simultaneously across different threads. Must be used atomically, and must be 32-bit. */
ma_bool8 noAutoConvertSRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM. */
ma_bool8 noDefaultQualitySRC; /* When set to true, disables the use of AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY. */
ma_bool8 noHardwareOffloading;
ma_bool8 allowCaptureAutoStreamRouting;
ma_bool8 allowPlaybackAutoStreamRouting;
ma_bool8 isDetachedPlayback;
ma_bool8 isDetachedCapture;
} wasapi;
#endif
#ifdef MA_SUPPORT_DSOUND
struct
{
/*LPDIRECTSOUND*/ ma_ptr pPlayback;
/*LPDIRECTSOUNDBUFFER*/ ma_ptr pPlaybackPrimaryBuffer;
/*LPDIRECTSOUNDBUFFER*/ ma_ptr pPlaybackBuffer;
/*LPDIRECTSOUNDCAPTURE*/ ma_ptr pCapture;
/*LPDIRECTSOUNDCAPTUREBUFFER*/ ma_ptr pCaptureBuffer;
} dsound;
#endif
#ifdef MA_SUPPORT_WINMM
struct
{
/*HWAVEOUT*/ ma_handle hDevicePlayback;
/*HWAVEIN*/ ma_handle hDeviceCapture;
/*HANDLE*/ ma_handle hEventPlayback;
/*HANDLE*/ ma_handle hEventCapture;
ma_uint32 fragmentSizeInFrames;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
Thread Safety
-------------
Unsafe. Do not call this function across multiple threads as some backends read and write to global state.
Remarks
-------
When `backends` is NULL, the default priority order will be used. Below is a list of backends in priority order:
|-------------|-----------------------|--------------------------------------------------------|
| Name | Enum Name | Supported Operating Systems |
|-------------|-----------------------|--------------------------------------------------------|
| WASAPI | ma_backend_wasapi | Windows Vista+ |
| DirectSound | ma_backend_dsound | Windows XP+ |
| WinMM | ma_backend_winmm | Windows XP+ (may work on older versions, but untested) |
| Core Audio | ma_backend_coreaudio | macOS, iOS |
| ALSA | ma_backend_alsa | Linux |
| PulseAudio | ma_backend_pulseaudio | Cross Platform (disabled on Windows, BSD and Android) |
| JACK | ma_backend_jack | Cross Platform (disabled on BSD and Android) |
| sndio | ma_backend_sndio | OpenBSD |
| audio(4) | ma_backend_audio4 | NetBSD, OpenBSD |
| OSS | ma_backend_oss | FreeBSD |
| AAudio | ma_backend_aaudio | Android 8+ |
| OpenSL|ES | ma_backend_opensl | Android (API level 16+) |
| Web Audio | ma_backend_webaudio | Web (via Emscripten) |
| Null | ma_backend_null | Cross Platform (not used on Web) |
|-------------|-----------------------|--------------------------------------------------------|
The context can be configured via the `pConfig` argument. The config object is initialized with `ma_context_config_init()`. Individual configuration settings
can then be set directly on the structure. Below are the members of the `ma_context_config` object.
pLog
A pointer to the `ma_log` to post log messages to. Can be NULL if the application does not
require logging. See the `ma_log` API for details on how to use the logging system.
threadPriority
The desired priority to use for the audio thread. Allowable values include the following:
|--------------------------------------|
| Thread Priority |
|--------------------------------------|
| ma_thread_priority_idle |
| ma_thread_priority_lowest |
| ma_thread_priority_low |
| ma_thread_priority_normal |
| ma_thread_priority_high |
| ma_thread_priority_highest (default) |
| ma_thread_priority_realtime |
| ma_thread_priority_default |
|--------------------------------------|
threadStackSize
The desired size of the stack for the audio thread. Defaults to the operating system's default.
pUserData
A pointer to application-defined data. This can be accessed from the context object directly such as `context.pUserData`.
allocationCallbacks
Structure containing custom allocation callbacks. Leaving this at defaults will cause it to use MA_MALLOC, MA_REALLOC and MA_FREE. These allocation
callbacks will be used for anything tied to the context, including devices.
alsa.useVerboseDeviceEnumeration
ALSA will typically enumerate many different devices which can be intrusive and not user-friendly. To combat this, miniaudio will enumerate only unique
card/device pairs by default. The problem with this is that you lose a bit of flexibility and control. Setting alsa.useVerboseDeviceEnumeration makes
it so the ALSA backend includes all devices. Defaults to false.
pulse.pApplicationName
PulseAudio only. The application name to use when initializing the PulseAudio context with `pa_context_new()`.
pulse.pServerName
PulseAudio only. The name of the server to connect to with `pa_context_connect()`.
pulse.tryAutoSpawn
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
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
intrusive for the end user.
coreaudio.sessionCategory
iOS only. The session category to use for the shared AudioSession instance. Below is a list of allowable values and their Core Audio equivalents.
|-----------------------------------------|-------------------------------------|
| miniaudio Token | Core Audio Token |
|-----------------------------------------|-------------------------------------|
| ma_ios_session_category_ambient | AVAudioSessionCategoryAmbient |
| ma_ios_session_category_solo_ambient | AVAudioSessionCategorySoloAmbient |
| ma_ios_session_category_playback | AVAudioSessionCategoryPlayback |
| ma_ios_session_category_record | AVAudioSessionCategoryRecord |
| ma_ios_session_category_play_and_record | AVAudioSessionCategoryPlayAndRecord |
| ma_ios_session_category_multi_route | AVAudioSessionCategoryMultiRoute |
| ma_ios_session_category_none | AVAudioSessionCategoryAmbient |
| ma_ios_session_category_default | AVAudioSessionCategoryAmbient |
|-----------------------------------------|-------------------------------------|
coreaudio.sessionCategoryOptions
iOS only. Session category options to use with the shared AudioSession instance. Below is a list of allowable values and their Core Audio equivalents.
|---------------------------------------------------------------------------|------------------------------------------------------------------|
| miniaudio Token | Core Audio Token |
|---------------------------------------------------------------------------|------------------------------------------------------------------|
| ma_ios_session_category_option_mix_with_others | AVAudioSessionCategoryOptionMixWithOthers |
| ma_ios_session_category_option_duck_others | AVAudioSessionCategoryOptionDuckOthers |
| ma_ios_session_category_option_allow_bluetooth | AVAudioSessionCategoryOptionAllowBluetooth |
| ma_ios_session_category_option_default_to_speaker | AVAudioSessionCategoryOptionDefaultToSpeaker |
| ma_ios_session_category_option_interrupt_spoken_audio_and_mix_with_others | AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers |
| ma_ios_session_category_option_allow_bluetooth_a2dp | AVAudioSessionCategoryOptionAllowBluetoothA2DP |
| ma_ios_session_category_option_allow_air_play | AVAudioSessionCategoryOptionAllowAirPlay |
|---------------------------------------------------------------------------|------------------------------------------------------------------|
coreaudio.noAudioSessionActivate
iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:true] on initialization.
coreaudio.noAudioSessionDeactivate
iOS only. When set to true, does not perform an explicit [[AVAudioSession sharedInstace] setActive:false] on uninitialization.
jack.pClientName
The name of the client to pass to `jack_client_open()`.
jack.tryStartServer
Whether or not to try auto-starting the JACK server. Defaults to false.
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
The device can be configured via the `pConfig` argument. The config object is initialized with `ma_device_config_init()`. Individual configuration settings can
then be set directly on the structure. Below are the members of the `ma_device_config` object.
deviceType
Must be `ma_device_type_playback`, `ma_device_type_capture`, `ma_device_type_duplex` of `ma_device_type_loopback`.
sampleRate
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.
periodSizeInFrames
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
be used depending on the selected performance profile. This value affects latency. See below for details.
periodSizeInMilliseconds
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
used depending on the selected performance profile. The value affects latency. See below for details.
periods
The number of periods making up the device's entire buffer. The total buffer size is `periodSizeInFrames` or `periodSizeInMilliseconds` multiplied by
this value. This is just a hint as backends will be the ones who ultimately decide how your periods will be configured.
performanceProfile
A hint to miniaudio as to the performance requirements of your program. Can be either `ma_performance_profile_low_latency` (default) or
`ma_performance_profile_conservative`. This mainly affects the size of default buffers and can usually be left at it's default value.
noPreSilencedOutputBuffer
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
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
callback will write to every sample in the output buffer, or if you are doing your own clearing.
noClip
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
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
applies when the playback sample format is f32.
noDisableDenormals
By default, miniaudio will disable denormals when the data callback is called. Setting this to true will prevent the disabling of denormals.
noFixedSizedCallback
Allows miniaudio to fire the data callback with any frame count. When this is set to true, the data callback will be fired with a consistent frame
count as specified by `periodSizeInFrames` or `periodSizeInMilliseconds`. When set to false, miniaudio will fire the callback with whatever the
backend requests, which could be anything.
dataCallback
The callback to fire whenever data is ready to be delivered to or from the device.
notificationCallback
The callback to fire when something has changed with the device, such as whether or not it has been started or stopped.
pUserData
The user data pointer to use with the device. You can access this directly from the device object like `device.pUserData`.
resampling.algorithm
The resampling algorithm to use when miniaudio needs to perform resampling between the rate specified by `sampleRate` and the device's native rate. The
default value is `ma_resample_algorithm_linear`, and the quality can be configured with `resampling.linear.lpfOrder`.
resampling.pBackendVTable
A pointer to an optional vtable that can be used for plugging in a custom resampler.
resampling.pBackendUserData
A pointer that will passed to callbacks in pBackendVTable.
resampling.linear.lpfOrder
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
the value, the better the quality, in general. Setting this to 0 will disable low-pass filtering altogether. The maximum value is
`MA_MAX_FILTER_ORDER`. The default value is `min(4, MA_MAX_FILTER_ORDER)`.
playback.pDeviceID
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
default playback device. Retrieve the device ID from the `ma_device_info` structure, which can be retrieved using device enumeration.
playback.format
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
initialization from the device object directly with `device.playback.format`.
playback.channels
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
from the device object directly with `device.playback.channels`.
playback.pChannelMap
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
device object direct with `device.playback.pChannelMap`. When set, the buffer should contain `channels` items.
playback.shareMode
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
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
ma_share_mode_shared and reinitializing.
capture.pDeviceID
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
default capture device. Retrieve the device ID from the `ma_device_info` structure, which can be retrieved using device enumeration.
capture.format
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
initialization from the device object directly with `device.capture.format`.
capture.channels
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
from the device object directly with `device.capture.channels`.
capture.pChannelMap
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
device object direct with `device.capture.pChannelMap`. When set, the buffer should contain `channels` items.
capture.shareMode
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
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
ma_share_mode_shared and reinitializing.
wasapi.noAutoConvertSRC
WASAPI only. When set to true, disables WASAPI's automatic resampling and forces the use of miniaudio's resampler. Defaults to false.
wasapi.noDefaultQualitySRC
WASAPI only. Only used when `wasapi.noAutoConvertSRC` is set to false. When set to true, disables the use of `AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY`.
You should usually leave this set to false, which is the default.
wasapi.noAutoStreamRouting
WASAPI only. When set to true, disables automatic stream routing on the WASAPI backend. Defaults to false.
wasapi.noHardwareOffloading
WASAPI only. When set to true, disables the use of WASAPI's hardware offloading feature. Defaults to false.
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_data_source_get_next_proc onGetNext; /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
MA_ATOMIC(4, ma_bool32) isLooping;
} ma_data_source_base;
MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_data_source* pDataSource);
MA_API void ma_data_source_uninit(ma_data_source* pDataSource);
MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Must support pFramesOut = NULL in which case a forward seek should be performed. */
MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked); /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, &framesRead); */
MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex);
MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor);
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. */
MA_API ma_result ma_data_source_get_cursor_in_seconds(ma_data_source* pDataSource, float* pCursor);
MA_API ma_result ma_data_source_get_length_in_seconds(ma_data_source* pDataSource, float* pLength);
MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping);
MA_API ma_bool32 ma_data_source_is_looping(const ma_data_source* pDataSource);
MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames);
MA_API void ma_data_source_get_range_in_pcm_frames(const ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames);
MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames);
MA_API void ma_data_source_get_loop_point_in_pcm_frames(const ma_data_source* pDataSource, ma_uint64* pLoopBegInFrames, ma_uint64* pLoopEndInFrames);
MA_API ma_result ma_data_source_set_current(ma_data_source* pDataSource, ma_data_source* pCurrentDataSource);
MA_API ma_data_source* ma_data_source_get_current(const ma_data_source* pDataSource);
MA_API ma_result ma_data_source_set_next(ma_data_source* pDataSource, ma_data_source* pNextDataSource);
MA_API ma_data_source* ma_data_source_get_next(const ma_data_source* pDataSource);
MA_API ma_result ma_data_source_set_next_callback(ma_data_source* pDataSource, ma_data_source_get_next_proc onGetNext);
MA_API ma_data_source_get_next_proc ma_data_source_get_next_callback(const ma_data_source* pDataSource);
typedef struct
{
ma_data_source_base ds;
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
ma_uint64 cursor;
ma_uint64 sizeInFrames;
const void* pData;
} ma_audio_buffer_ref;
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);
MA_API void ma_audio_buffer_ref_uninit(ma_audio_buffer_ref* pAudioBufferRef);
MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames);
MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref* pAudioBufferRef, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
MA_API ma_result ma_audio_buffer_ref_seek_to_pcm_frame(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameIndex);
MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref* pAudioBufferRef, void** ppFramesOut, ma_uint64* pFrameCount);
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. */
MA_API ma_bool32 ma_audio_buffer_ref_at_end(const ma_audio_buffer_ref* pAudioBufferRef);
MA_API ma_result ma_audio_buffer_ref_get_cursor_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pCursor);
MA_API ma_result ma_audio_buffer_ref_get_length_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pLength);
MA_API ma_result ma_audio_buffer_ref_get_available_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pAvailableFrames);
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
ma_uint64 sizeInFrames;
const void* pData; /* If set to NULL, will allocate a block of memory for you. */
ma_allocation_callbacks allocationCallbacks;
} ma_audio_buffer_config;
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);
typedef struct
{
ma_audio_buffer_ref ref;
ma_allocation_callbacks allocationCallbacks;
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(). */
ma_uint8 _pExtraData[1]; /* For allocating a buffer with the memory located directly after the other memory of the structure. */
} ma_audio_buffer;
MA_API ma_result ma_audio_buffer_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer);
MA_API ma_result ma_audio_buffer_init_copy(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer);
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. */
MA_API void ma_audio_buffer_uninit(ma_audio_buffer* pAudioBuffer);
MA_API void ma_audio_buffer_uninit_and_free(ma_audio_buffer* pAudioBuffer);
MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer* pAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
MA_API ma_result ma_audio_buffer_seek_to_pcm_frame(ma_audio_buffer* pAudioBuffer, ma_uint64 frameIndex);
MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount);
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. */
MA_API ma_bool32 ma_audio_buffer_at_end(const ma_audio_buffer* pAudioBuffer);
MA_API ma_result ma_audio_buffer_get_cursor_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pCursor);
MA_API ma_result ma_audio_buffer_get_length_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pLength);
MA_API ma_result ma_audio_buffer_get_available_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames);
/*
Paged Audio Buffer
==================
A paged audio buffer is made up of a linked list of pages. It's expandable, but not shrinkable. It
can be used for cases where audio data is streamed in asynchronously while allowing data to be read
at the same time.
This is lock-free, but not 100% thread safe. You can append a page and read from the buffer across
simultaneously across different threads, however only one thread at a time can append, and only one
thread at a time can read and seek.
*/
typedef struct ma_paged_audio_buffer_page ma_paged_audio_buffer_page;
struct ma_paged_audio_buffer_page
{
MA_ATOMIC(MA_SIZEOF_PTR, ma_paged_audio_buffer_page*) pNext;
ma_uint64 sizeInFrames;
ma_uint8 pAudioData[1];
};
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_paged_audio_buffer_page head; /* Dummy head for the lock-free algorithm. Always has a size of 0. */
MA_ATOMIC(MA_SIZEOF_PTR, ma_paged_audio_buffer_page*) pTail; /* Never null. Initially set to &head. */
} ma_paged_audio_buffer_data;
MA_API ma_result ma_paged_audio_buffer_data_init(ma_format format, ma_uint32 channels, ma_paged_audio_buffer_data* pData);
MA_API void ma_paged_audio_buffer_data_uninit(ma_paged_audio_buffer_data* pData, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_head(ma_paged_audio_buffer_data* pData);
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_tail(ma_paged_audio_buffer_data* pData);
MA_API ma_result ma_paged_audio_buffer_data_get_length_in_pcm_frames(ma_paged_audio_buffer_data* pData, ma_uint64* pLength);
MA_API ma_result ma_paged_audio_buffer_data_allocate_page(ma_paged_audio_buffer_data* pData, ma_uint64 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks, ma_paged_audio_buffer_page** ppPage);
MA_API ma_result ma_paged_audio_buffer_data_free_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_paged_audio_buffer_data_append_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage);
MA_API ma_result ma_paged_audio_buffer_data_allocate_and_append_page(ma_paged_audio_buffer_data* pData, ma_uint32 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks);
typedef struct
{
ma_paged_audio_buffer_data* pData; /* Must not be null. */
} ma_paged_audio_buffer_config;
MA_API ma_paged_audio_buffer_config ma_paged_audio_buffer_config_init(ma_paged_audio_buffer_data* pData);
typedef struct
{
ma_data_source_base ds;
ma_paged_audio_buffer_data* pData; /* Audio data is read from here. Cannot be null. */
ma_paged_audio_buffer_page* pCurrent;
ma_uint64 relativeCursor; /* Relative to the current page. */
ma_uint64 absoluteCursor;
} ma_paged_audio_buffer;
MA_API ma_result ma_paged_audio_buffer_init(const ma_paged_audio_buffer_config* pConfig, ma_paged_audio_buffer* pPagedAudioBuffer);
MA_API void ma_paged_audio_buffer_uninit(ma_paged_audio_buffer* pPagedAudioBuffer);
MA_API ma_result ma_paged_audio_buffer_read_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Returns MA_AT_END if no more pages available. */
MA_API ma_result ma_paged_audio_buffer_seek_to_pcm_frame(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64 frameIndex);
MA_API ma_result ma_paged_audio_buffer_get_cursor_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pCursor);
MA_API ma_result ma_paged_audio_buffer_get_length_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pLength);
/************************************************************************************************************************************************************
VFS
===
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
appropriate for a given situation.
************************************************************************************************************************************************************/
typedef void ma_vfs;
typedef ma_handle ma_vfs_file;
typedef enum
{
MA_OPEN_MODE_READ = 0x00000001,
MA_OPEN_MODE_WRITE = 0x00000002
} ma_open_mode_flags;
typedef enum
{
ma_seek_origin_start,
ma_seek_origin_current,
ma_seek_origin_end /* Not used by decoders. */
} ma_seek_origin;
typedef struct
{
ma_uint64 sizeInBytes;
} ma_file_info;
typedef struct
{
ma_result (* onOpen) (ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
ma_result (* onOpenW)(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
ma_result (* onClose)(ma_vfs* pVFS, ma_vfs_file file);
ma_result (* onRead) (ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead);
ma_result (* onWrite)(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten);
ma_result (* onSeek) (ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin);
ma_result (* onTell) (ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor);
ma_result (* onInfo) (ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo);
} ma_vfs_callbacks;
MA_API ma_result ma_vfs_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
MA_API ma_result ma_vfs_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile);
MA_API ma_result ma_vfs_close(ma_vfs* pVFS, ma_vfs_file file);
MA_API ma_result ma_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead);
MA_API ma_result ma_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten);
MA_API ma_result ma_vfs_seek(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin);
MA_API ma_result ma_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor);
MA_API ma_result ma_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo);
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);
typedef struct
{
ma_vfs_callbacks cb;
ma_allocation_callbacks allocationCallbacks; /* Only used for the wchar_t version of open() on non-Windows platforms. */
} ma_default_vfs;
MA_API ma_result ma_default_vfs_init(ma_default_vfs* pVFS, const ma_allocation_callbacks* pAllocationCallbacks);
typedef ma_result (* ma_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead);
typedef ma_result (* ma_seek_proc)(void* pUserData, ma_int64 offset, ma_seek_origin origin);
typedef ma_result (* ma_tell_proc)(void* pUserData, ma_int64* pCursor);
#if !defined(MA_NO_DECODING) || !defined(MA_NO_ENCODING)
typedef enum
{
ma_encoding_format_unknown = 0,
ma_encoding_format_wav,
ma_encoding_format_flac,
ma_encoding_format_mp3,
ma_encoding_format_vorbis
} ma_encoding_format;
#endif
/************************************************************************************************************************************************************
Decoding
========
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
you do your own synchronization.
************************************************************************************************************************************************************/
#ifndef MA_NO_DECODING
typedef struct ma_decoder ma_decoder;
typedef struct
{
ma_format preferredFormat;
ma_uint32 seekPointCount; /* Set to > 0 to generate a seektable if the decoding backend supports it. */
} ma_decoding_backend_config;
MA_API ma_decoding_backend_config ma_decoding_backend_config_init(ma_format preferredFormat, ma_uint32 seekPointCount);
typedef struct
{
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...
ma_result (* onInitFile )(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend); /* Optional. */
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. */
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. */
void (* onUninit )(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks);
} ma_decoding_backend_vtable;
typedef ma_result (* ma_decoder_read_proc)(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead); /* Returns the number of bytes read. */
typedef ma_result (* ma_decoder_seek_proc)(ma_decoder* pDecoder, ma_int64 byteOffset, ma_seek_origin origin);
typedef ma_result (* ma_decoder_tell_proc)(ma_decoder* pDecoder, ma_int64* pCursor);
typedef struct
{
ma_format format; /* Set to 0 or ma_format_unknown to use the stream's internal format. */
ma_uint32 channels; /* Set to 0 to use the stream's internal channels. */
ma_uint32 sampleRate; /* Set to 0 to use the stream's internal sample rate. */
ma_channel* pChannelMap;
ma_channel_mix_mode channelMixMode;
ma_dither_mode ditherMode;
ma_resampler_config resampling;
ma_allocation_callbacks allocationCallbacks;
ma_encoding_format encodingFormat;
ma_uint32 seekPointCount; /* When set to > 0, specifies the number of seek points to use for the generation of a seek table. Not all decoding backends support this. */
ma_decoding_backend_vtable** ppCustomBackendVTables;
ma_uint32 customBackendCount;
void* pCustomBackendUserData;
} ma_decoder_config;
struct ma_decoder
{
ma_data_source_base ds;
ma_data_source* pBackend; /* The decoding backend we'll be pulling data from. */
const ma_decoding_backend_vtable* pBackendVTable; /* The vtable for the decoding backend. This needs to be stored so we can access the onUninit() callback. */
void* pBackendUserData;
ma_decoder_read_proc onRead;
ma_decoder_seek_proc onSeek;
ma_decoder_tell_proc onTell;
void* pUserData;
ma_uint64 readPointerInPCMFrames; /* In output sample rate. Used for keeping track of how many frames are available for decoding. */
ma_format outputFormat;
ma_uint32 outputChannels;
ma_uint32 outputSampleRate;
ma_data_converter converter; /* Data conversion is achieved by running frames through this. */
void* pInputCache; /* In input format. Can be null if it's not needed. */
ma_uint64 inputCacheCap; /* The capacity of the input cache. */
ma_uint64 inputCacheConsumed; /* The number of frames that have been consumed in the cache. Used for determining the next valid frame. */
ma_uint64 inputCacheRemaining; /* The number of valid frames remaining in the cahce. */
ma_allocation_callbacks allocationCallbacks;
union
{
struct
{
ma_vfs* pVFS;
ma_vfs_file file;
} vfs;
struct
{
const ma_uint8* pData;
size_t dataSize;
size_t currentReadPos;
} memory; /* Only used for decoders that were opened against a block of memory. */
} data;
};
MA_API ma_decoder_config ma_decoder_config_init(ma_format outputFormat, ma_uint32 outputChannels, ma_uint32 outputSampleRate);
MA_API ma_decoder_config ma_decoder_config_init_default(void);
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);
MA_API ma_result ma_decoder_init_memory(const void* pData, size_t dataSize, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
MA_API ma_result ma_decoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
MA_API ma_result ma_decoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
MA_API ma_result ma_decoder_init_file(const char* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
MA_API ma_result ma_decoder_init_file_w(const wchar_t* pFilePath, const ma_decoder_config* pConfig, ma_decoder* pDecoder);
/*
Uninitializes a decoder.
*/
MA_API ma_result ma_decoder_uninit(ma_decoder* pDecoder);
/*
Reads PCM frames from the given decoder.
This is not thread safe without your own synchronization.
*/
MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
/*
Seeks to a PCM frame based on it's absolute index.
This is not thread safe without your own synchronization.
*/
MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder* pDecoder, ma_uint64 frameIndex);
/*
Retrieves the decoder's output data format.
*/
MA_API ma_result ma_decoder_get_data_format(ma_decoder* pDecoder, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
/*
Retrieves the current position of the read cursor in PCM frames.
*/
MA_API ma_result ma_decoder_get_cursor_in_pcm_frames(ma_decoder* pDecoder, ma_uint64* pCursor);
/*
Retrieves the length of the decoder in PCM frames.
Do not call this on streams of an undefined length, such as internet radio.
If the length is unknown or an error occurs, 0 will be returned.
This will always return 0 for Vorbis decoders. This is due to a limitation with stb_vorbis in push mode which is what miniaudio
uses internally.
For MP3's, this will decode the entire file. Do not call this in time critical scenarios.
This function is not thread safe without your own synchronization.
*/
MA_API ma_result ma_decoder_get_length_in_pcm_frames(ma_decoder* pDecoder, ma_uint64* pLength);
/*
Retrieves the number of frames that can be read before reaching the end.
This calls `ma_decoder_get_length_in_pcm_frames()` so you need to be aware of the rules for that function, in
particular ensuring you do not call it on streams of an undefined length, such as internet radio.
If the total length of the decoder cannot be retrieved, such as with Vorbis decoders, `MA_NOT_IMPLEMENTED` will be
returned.
*/
MA_API ma_result ma_decoder_get_available_frames(ma_decoder* pDecoder, ma_uint64* pAvailableFrames);
/*
Helper for opening and decoding a file into a heap allocated block of memory. Free the returned pointer with ma_free(). On input,
pConfig should be set to what you want. On output it will be set to what you got.
*/
MA_API ma_result ma_decode_from_vfs(ma_vfs* pVFS, const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut);
MA_API ma_result ma_decode_file(const char* pFilePath, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut);
MA_API ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder_config* pConfig, ma_uint64* pFrameCountOut, void** ppPCMFramesOut);
#endif /* MA_NO_DECODING */
/************************************************************************************************************************************************************
Encoding
========
Encoders do not perform any format conversion for you. If your target format does not support the format, and error will be returned.
************************************************************************************************************************************************************/
#ifndef MA_NO_ENCODING
typedef struct ma_encoder ma_encoder;
typedef ma_result (* ma_encoder_write_proc) (ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite, size_t* pBytesWritten);
typedef ma_result (* ma_encoder_seek_proc) (ma_encoder* pEncoder, ma_int64 offset, ma_seek_origin origin);
typedef ma_result (* ma_encoder_init_proc) (ma_encoder* pEncoder);
typedef void (* ma_encoder_uninit_proc) (ma_encoder* pEncoder);
typedef ma_result (* ma_encoder_write_pcm_frames_proc)(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount, ma_uint64* pFramesWritten);
typedef struct
{
ma_encoding_format encodingFormat;
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
ma_allocation_callbacks allocationCallbacks;
} ma_encoder_config;
MA_API ma_encoder_config ma_encoder_config_init(ma_encoding_format encodingFormat, ma_format format, ma_uint32 channels, ma_uint32 sampleRate);
struct ma_encoder
{
ma_encoder_config config;
ma_encoder_write_proc onWrite;
ma_encoder_seek_proc onSeek;
ma_encoder_init_proc onInit;
ma_encoder_uninit_proc onUninit;
ma_encoder_write_pcm_frames_proc onWritePCMFrames;
void* pUserData;
void* pInternalEncoder; /* <-- The drwav/drflac/stb_vorbis/etc. objects. */
union
{
struct
{
ma_vfs* pVFS;
ma_vfs_file file;
} vfs;
} data;
};
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);
MA_API ma_result ma_encoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
MA_API ma_result ma_encoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
MA_API void ma_encoder_uninit(ma_encoder* pEncoder);
MA_API ma_result ma_encoder_write_pcm_frames(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount, ma_uint64* pFramesWritten);
#endif /* MA_NO_ENCODING */
/************************************************************************************************************************************************************
Generation
************************************************************************************************************************************************************/
#ifndef MA_NO_GENERATION
typedef enum
{
ma_waveform_type_sine,
ma_waveform_type_square,
ma_waveform_type_triangle,
ma_waveform_type_sawtooth
} ma_waveform_type;
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_uint32 sampleRate;
ma_waveform_type type;
double amplitude;
double frequency;
} ma_waveform_config;
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);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_waveform_config config;
double advance;
double time;
} ma_waveform;
MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform* pWaveform);
MA_API void ma_waveform_uninit(ma_waveform* pWaveform);
MA_API ma_result ma_waveform_read_pcm_frames(ma_waveform* pWaveform, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_waveform_seek_to_pcm_frame(ma_waveform* pWaveform, ma_uint64 frameIndex);
MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude);
MA_API ma_result ma_waveform_set_frequency(ma_waveform* pWaveform, double frequency);
MA_API ma_result ma_waveform_set_type(ma_waveform* pWaveform, ma_waveform_type type);
MA_API ma_result ma_waveform_set_sample_rate(ma_waveform* pWaveform, ma_uint32 sampleRate);
typedef enum
{
ma_noise_type_white,
ma_noise_type_pink,
ma_noise_type_brownian
} ma_noise_type;
typedef struct
{
ma_format format;
ma_uint32 channels;
ma_noise_type type;
ma_int32 seed;
double amplitude;
ma_bool32 duplicateChannels;
} ma_noise_config;
MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels, ma_noise_type type, ma_int32 seed, double amplitude);
typedef struct
{
ma_data_source_vtable ds;
ma_noise_config config;
ma_lcg lcg;
union
{
struct
{
double** bin;
double* accumulation;
ma_uint32* counter;
} pink;
struct
{
double* accumulation;
} brownian;
} state;
/* Memory management. */
void* _pHeap;
ma_bool32 _ownsHeap;
} ma_noise;
MA_API ma_result ma_noise_get_heap_size(const ma_noise_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_noise_init_preallocated(const ma_noise_config* pConfig, void* pHeap, ma_noise* pNoise);
MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_noise* pNoise);
MA_API void ma_noise_uninit(ma_noise* pNoise, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude);
MA_API ma_result ma_noise_set_seed(ma_noise* pNoise, ma_int32 seed);
MA_API ma_result ma_noise_set_type(ma_noise* pNoise, ma_noise_type type);
#endif /* MA_NO_GENERATION */
/************************************************************************************************************************************************************
Resource Manager
************************************************************************************************************************************************************/
/* The resource manager cannot be enabled if there is no decoder. */
#if !defined(MA_NO_RESOURCE_MANAGER) && defined(MA_NO_DECODING)
#define MA_NO_RESOURCE_MANAGER
#endif
#ifndef MA_NO_RESOURCE_MANAGER
typedef struct ma_resource_manager ma_resource_manager;
typedef struct ma_resource_manager_data_buffer_node ma_resource_manager_data_buffer_node;
typedef struct ma_resource_manager_data_buffer ma_resource_manager_data_buffer;
typedef struct ma_resource_manager_data_stream ma_resource_manager_data_stream;
typedef struct ma_resource_manager_data_source ma_resource_manager_data_source;
typedef enum
{
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM = 0x00000001, /* When set, does not load the entire data source in memory. Disk I/O will happen on job threads. */
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE = 0x00000002, /* Decode data before storing in memory. When set, decoding is done at the resource manager level rather than the mixing thread. Results in faster mixing, but higher memory usage...
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC = 0x00000004, /* When set, the resource manager will load the data source asynchronously. */
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT = 0x00000008, /* When set, waits for initialization of the underlying data source before returning from ma_resource_manager_data_source_init(). */
MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH = 0x00000010 /* Gives the resource manager a hint that the length of the data source is unknown and calling `ma_data_source_get_length_in_pcm_frames()` should be avoided. */
} ma_resource_manager_data_source_flags;
/*
Pipeline notifications used by the resource manager. Made up of both an async notification and a fence, both of which are optional.
*/
typedef struct
{
ma_async_notification* pNotification;
ma_fence* pFence;
} ma_resource_manager_pipeline_stage_notification;
typedef struct
{
ma_resource_manager_pipeline_stage_notification init; /* Initialization of the decoder. */
ma_resource_manager_pipeline_stage_notification done; /* Decoding fully completed. */
} ma_resource_manager_pipeline_notifications;
MA_API ma_resource_manager_pipeline_notifications ma_resource_manager_pipeline_notifications_init(void);
/* BEGIN BACKWARDS COMPATIBILITY */
/* TODO: Remove this block in version 0.12. */
#if 1
#define ma_resource_manager_job ma_job
#define ma_resource_manager_job_init ma_job_init
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_resource_manager_data_buffer_node* pParent;
ma_resource_manager_data_buffer_node* pChildLo;
ma_resource_manager_data_buffer_node* pChildHi;
};
struct ma_resource_manager_data_buffer
{
ma_data_source_base ds; /* Base data source. A data buffer is a data source. */
ma_resource_manager* pResourceManager; /* A pointer to the resource manager that owns this buffer. */
ma_resource_manager_data_buffer_node* pNode; /* The data node. This is reference counted and is what supplies the data. */
ma_uint32 flags; /* The flags that were passed used to initialize the buffer. */
MA_ATOMIC(4, ma_uint32) executionCounter; /* For allocating execution orders for jobs. */
MA_ATOMIC(4, ma_uint32) executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
ma_uint64 seekTargetInPCMFrames; /* Only updated by the public API. Never written nor read from the job thread. */
ma_bool32 seekToCursorOnNextRead; /* On the next read we need to seek to the frame cursor. */
MA_ATOMIC(4, ma_result) result; /* Keeps track of a result of decoding. Set to MA_BUSY while the buffer is still loading. Set to MA_SUCCESS when loading is finished successfully. Otherwise set to some other code. */
MA_ATOMIC(4, ma_bool32) isLooping; /* Can be read and written by different threads at the same time. Must be used atomically. */
ma_bool32 isConnectorInitialized; /* Used for asynchronous loading to ensure we don't try to initialize the connector multiple times while waiting for the node to fully load. */
union
{
ma_decoder decoder; /* Supply type is ma_resource_manager_data_supply_type_encoded */
ma_audio_buffer buffer; /* Supply type is ma_resource_manager_data_supply_type_decoded */
ma_paged_audio_buffer pagedBuffer; /* Supply type is ma_resource_manager_data_supply_type_decoded_paged */
} connector; /* Connects this object to the node's data supply. */
};
struct ma_resource_manager_data_stream
{
ma_data_source_base ds; /* Base data source. A data stream is a data source. */
ma_resource_manager* pResourceManager; /* A pointer to the resource manager that owns this data stream. */
ma_uint32 flags; /* The flags that were passed used to initialize the stream. */
ma_decoder decoder; /* Used for filling pages with data. This is only ever accessed by the job thread. The public API should never touch this. */
ma_bool32 isDecoderInitialized; /* Required for determining whether or not the decoder should be uninitialized in MA_JOB_TYPE_RESOURCE_MANAGER_FREE_DATA_STREAM. */
ma_uint64 totalLengthInPCMFrames; /* This is calculated when first loaded by the MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_STREAM. */
ma_uint32 relativeCursor; /* The playback cursor, relative to the current page. Only ever accessed by the public API. Never accessed by the job thread. */
MA_ATOMIC(8, ma_uint64) absoluteCursor; /* The playback cursor, in absolute position starting from the start of the file. */
ma_uint32 currentPageIndex; /* Toggles between 0 and 1. Index 0 is the first half of pPageData. Index 1 is the second half. Only ever accessed by the public API. Never accessed by the job thread. */
MA_ATOMIC(4, ma_uint32) executionCounter; /* For allocating execution orders for jobs. */
MA_ATOMIC(4, ma_uint32) executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
/* Written by the public API, read by the job thread. */
MA_ATOMIC(4, ma_bool32) isLooping; /* Whether or not the stream is looping. It's important to set the looping flag at the data stream level for smooth loop transitions. */
/* Written by the job thread, read by the public API. */
void* pPageData; /* Buffer containing the decoded data of each page. Allocated once at initialization time. */
MA_ATOMIC(4, ma_uint32) pageFrameCount[2]; /* The number of valid PCM frames in each page. Used to determine the last valid frame. */
/* Written and read by both the public API and the job thread. These must be atomic. */
MA_ATOMIC(4, ma_result) result; /* Result from asynchronous loading. When loading set to MA_BUSY. When initialized set to MA_SUCCESS. When deleting set to MA_UNAVAILABLE. If an error occurs when loading, set to an error code. */
MA_ATOMIC(4, ma_bool32) isDecoderAtEnd; /* Whether or not the decoder has reached the end. */
MA_ATOMIC(4, ma_bool32) isPageValid[2]; /* Booleans to indicate whether or not a page is valid. Set to false by the public API, set to true by the job thread. Set to false as the pages are consumed, true when they are filled. */
MA_ATOMIC(4, ma_bool32) seekCounter; /* When 0, no seeking is being performed. When > 0, a seek is being performed and reading should be delayed with MA_BUSY. */
};
struct ma_resource_manager_data_source
{
union
{
ma_resource_manager_data_buffer buffer;
ma_resource_manager_data_stream stream;
} backend; /* Must be the first item because we need the first item to be the data source callbacks for the buffer or stream. */
ma_uint32 flags; /* The flags that were passed in to ma_resource_manager_data_source_init(). */
MA_ATOMIC(4, ma_uint32) executionCounter; /* For allocating execution orders for jobs. */
MA_ATOMIC(4, ma_uint32) executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
};
typedef struct
{
ma_allocation_callbacks allocationCallbacks;
ma_log* pLog;
ma_format decodedFormat; /* The decoded format to use. Set to ma_format_unknown (default) to use the file's native format. */
ma_uint32 decodedChannels; /* The decoded channel count to use. Set to 0 (default) to use the file's native channel count. */
ma_uint32 decodedSampleRate; /* the decoded sample rate to use. Set to 0 (default) to use the file's native sample rate. */
ma_uint32 jobThreadCount; /* Set to 0 if you want to self-manage your job threads. Defaults to 1. */
ma_uint32 jobQueueCapacity; /* The maximum number of jobs that can fit in the queue at a time. Defaults to MA_JOB_TYPE_RESOURCE_MANAGER_QUEUE_CAPACITY. Cannot be zero. */
ma_uint32 flags;
ma_vfs* pVFS; /* Can be NULL in which case defaults will be used. */
ma_decoding_backend_vtable** ppCustomDecodingBackendVTables;
ma_uint32 customDecodingBackendCount;
void* pCustomDecodingBackendUserData;
} ma_resource_manager_config;
MA_API ma_resource_manager_config ma_resource_manager_config_init(void);
struct ma_resource_manager
{
ma_resource_manager_config config;
ma_resource_manager_data_buffer_node* pRootDataBufferNode; /* The root buffer in the binary tree. */
#ifndef MA_NO_THREADING
ma_mutex dataBufferBSTLock; /* For synchronizing access to the data buffer binary tree. */
ma_thread jobThreads[MA_RESOURCE_MANAGER_MAX_JOB_THREAD_COUNT]; /* The threads for executing jobs. */
#endif
ma_job_queue jobQueue; /* Multi-consumer, multi-producer job queue for managing jobs for asynchronous decoding and streaming. */
ma_default_vfs defaultVFS; /* Only used if a custom VFS is not specified. */
ma_log log; /* Only used if no log was specified in the config. */
};
/* Init. */
MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pConfig, ma_resource_manager* pResourceManager);
MA_API void ma_resource_manager_uninit(ma_resource_manager* pResourceManager);
MA_API ma_log* ma_resource_manager_get_log(ma_resource_manager* pResourceManager);
/* Registration. */
MA_API ma_result ma_resource_manager_register_file(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags);
MA_API ma_result ma_resource_manager_register_file_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath, ma_uint32 flags);
MA_API ma_result ma_resource_manager_register_decoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate); /* Does not copy. Increments t...
MA_API ma_result ma_resource_manager_register_decoded_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate);
MA_API ma_result ma_resource_manager_register_encoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, size_t sizeInBytes); /* Does not copy. Increments the reference count if already exists and returns MA_SUCCESS....
MA_API ma_result ma_resource_manager_register_encoded_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName, const void* pData, size_t sizeInBytes);
MA_API ma_result ma_resource_manager_unregister_file(ma_resource_manager* pResourceManager, const char* pFilePath);
MA_API ma_result ma_resource_manager_unregister_file_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath);
MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResourceManager, const char* pName);
MA_API ma_result ma_resource_manager_unregister_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName);
/* Data Buffers. */
MA_API ma_result ma_resource_manager_data_buffer_init_ex(ma_resource_manager* pResourceManager, const ma_resource_manager_data_source_config* pConfig, ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_init_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_init_copy(ma_resource_manager* pResourceManager, const ma_resource_manager_data_buffer* pExistingDataBuffer, ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_uninit(ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_resource_manager_data_buffer_seek_to_pcm_frame(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64 frameIndex);
MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_manager_data_buffer* pDataBuffer, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pCursor);
MA_API ma_result ma_resource_manager_data_buffer_get_length_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pLength);
MA_API ma_result ma_resource_manager_data_buffer_result(const ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_set_looping(ma_resource_manager_data_buffer* pDataBuffer, ma_bool32 isLooping);
MA_API ma_bool32 ma_resource_manager_data_buffer_is_looping(const ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#define MA_MAX_NODE_BUS_COUNT 254
#endif
/* Used internally by miniaudio for memory management. Must never exceed MA_MAX_NODE_BUS_COUNT. */
#ifndef MA_MAX_NODE_LOCAL_BUS_COUNT
#define MA_MAX_NODE_LOCAL_BUS_COUNT 2
#endif
/* Use this when the bus count is determined by the node instance rather than the vtable. */
#define MA_NODE_BUS_COUNT_UNKNOWN 255
typedef struct ma_node_graph ma_node_graph;
typedef void ma_node;
/* Node flags. */
typedef enum
{
MA_NODE_FLAG_PASSTHROUGH = 0x00000001,
MA_NODE_FLAG_CONTINUOUS_PROCESSING = 0x00000002,
MA_NODE_FLAG_ALLOW_NULL_INPUT = 0x00000004,
MA_NODE_FLAG_DIFFERENT_PROCESSING_RATES = 0x00000008,
MA_NODE_FLAG_SILENT_OUTPUT = 0x00000010
} ma_node_flags;
/* The playback state of a node. Either started or stopped. */
typedef enum
{
ma_node_state_started = 0,
ma_node_state_stopped = 1
} ma_node_state;
typedef struct
{
/*
Extended processing callback. This callback is used for effects that process input and output
at different rates (i.e. they perform resampling). This is similar to the simple version, only
they take two seperate frame counts: one for input, and one for output.
On input, `pFrameCountOut` is equal to the capacity of the output buffer for each bus, whereas
`pFrameCountIn` will be equal to the number of PCM frames in each of the buffers in `ppFramesIn`.
On output, set `pFrameCountOut` to the number of PCM frames that were actually output and set
`pFrameCountIn` to the number of input frames that were consumed.
*/
void (* onProcess)(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut);
/*
A callback for retrieving the number of a input frames that are required to output the
specified number of output frames. You would only want to implement this when the node performs
resampling. This is optional, even for nodes that perform resampling, but it does offer a
small reduction in latency as it allows miniaudio to calculate the exact number of input frames
to read at a time instead of having to estimate.
*/
ma_result (* onGetRequiredInputFrameCount)(ma_node* pNode, ma_uint32 outputFrameCount, ma_uint32* pInputFrameCount);
/*
The number of input buses. This is how many sub-buffers will be contained in the `ppFramesIn`
parameters of the callbacks above.
*/
ma_uint8 inputBusCount;
/*
The number of output buses. This is how many sub-buffers will be contained in the `ppFramesOut`
parameters of the callbacks above.
*/
ma_uint8 outputBusCount;
/*
Flags describing characteristics of the node. This is currently just a placeholder for some
ideas for later on.
*/
ma_uint32 flags;
} ma_node_vtable;
typedef struct
{
const ma_node_vtable* vtable; /* Should never be null. Initialization of the node will fail if so. */
ma_node_state initialState; /* Defaults to ma_node_state_started. */
ma_uint32 inputBusCount; /* Only used if the vtable specifies an input bus count of `MA_NODE_BUS_COUNT_UNKNOWN`, otherwise must be set to `MA_NODE_BUS_COUNT_UNKNOWN` (default). */
ma_uint32 outputBusCount; /* Only used if the vtable specifies an output bus count of `MA_NODE_BUS_COUNT_UNKNOWN`, otherwise be set to `MA_NODE_BUS_COUNT_UNKNOWN` (default). */
const ma_uint32* pInputChannels; /* The number of elements are determined by the input bus count as determined by the vtable, or `inputBusCount` if the vtable specifies `MA_NODE_BUS_COUNT_UNKNOWN`. */
const ma_uint32* pOutputChannels; /* The number of elements are determined by the output bus count as determined by the vtable, or `outputBusCount` if the vtable specifies `MA_NODE_BUS_COUNT_UNKNOWN`. */
} ma_node_config;
MA_API ma_node_config ma_node_config_init(void);
/*
A node has multiple output buses. An output bus is attached to an input bus as an item in a linked
list. Think of the input bus as a linked list, with the output bus being an item in that list.
*/
typedef struct ma_node_output_bus ma_node_output_bus;
struct ma_node_output_bus
{
/* Immutable. */
ma_node* pNode; /* The node that owns this output bus. The input node. Will be null for dummy head and tail nodes. */
ma_uint8 outputBusIndex; /* The index of the output bus on pNode that this output bus represents. */
ma_uint8 channels; /* The number of channels in the audio stream for this bus. */
/* Mutable via multiple threads. Must be used atomically. The weird ordering here is for packing reasons. */
MA_ATOMIC(1, ma_uint8) inputNodeInputBusIndex; /* The index of the input bus on the input. Required for detaching. */
MA_ATOMIC(4, ma_uint32) flags; /* Some state flags for tracking the read state of the output buffer. A combination of MA_NODE_OUTPUT_BUS_FLAG_*. */
MA_ATOMIC(4, ma_uint32) refCount; /* Reference count for some thread-safety when detaching. */
MA_ATOMIC(4, ma_bool32) isAttached; /* This is used to prevent iteration of nodes that are in the middle of being detached. Used for thread safety. */
MA_ATOMIC(4, ma_spinlock) lock; /* Unfortunate lock, but significantly simplifies the implementation. Required for thread-safe attaching and detaching. */
MA_ATOMIC(4, float) volume; /* Linear. */
MA_ATOMIC(MA_SIZEOF_PTR, ma_node_output_bus*) pNext; /* If null, it's the tail node or detached. */
MA_ATOMIC(MA_SIZEOF_PTR, ma_node_output_bus*) pPrev; /* If null, it's the head node or detached. */
MA_ATOMIC(MA_SIZEOF_PTR, ma_node*) pInputNode; /* The node that this output bus is attached to. Required for detaching. */
};
/*
A node has multiple input buses. The output buses of a node are connecting to the input busses of
another. An input bus is essentially just a linked list of output buses.
*/
typedef struct ma_node_input_bus ma_node_input_bus;
struct ma_node_input_bus
{
/* Mutable via multiple threads. */
ma_node_output_bus head; /* Dummy head node for simplifying some lock-free thread-safety stuff. */
MA_ATOMIC(4, ma_uint32) nextCounter; /* This is used to determine whether or not the input bus is finding the next node in the list. Used for thread safety when detaching output buses. */
MA_ATOMIC(4, ma_spinlock) lock; /* Unfortunate lock, but significantly simplifies the implementation. Required for thread-safe attaching and detaching. */
/* Set once at startup. */
ma_uint8 channels; /* The number of channels in the audio stream for this bus. */
};
typedef struct ma_node_base ma_node_base;
struct ma_node_base
{
/* These variables are set once at startup. */
ma_node_graph* pNodeGraph; /* The graph this node belongs to. */
const ma_node_vtable* vtable;
float* pCachedData; /* Allocated on the heap. Fixed size. Needs to be stored on the heap because reading from output buses is done in separate function calls. */
ma_uint16 cachedDataCapInFramesPerBus; /* The capacity of the input data cache in frames, per bus. */
/* These variables are read and written only from the audio thread. */
ma_uint16 cachedFrameCountOut;
ma_uint16 cachedFrameCountIn;
ma_uint16 consumedFrameCountIn;
/* These variables are read and written between different threads. */
MA_ATOMIC(4, ma_node_state) state; /* When set to stopped, nothing will be read, regardless of the times in stateTimes. */
MA_ATOMIC(8, ma_uint64) stateTimes[2]; /* Indexed by ma_node_state. Specifies the time based on the global clock that a node should be considered to be in the relevant state. */
MA_ATOMIC(8, ma_uint64) localTime; /* The node's local clock. This is just a running sum of the number of output frames that have been processed. Can be modified by any thread with `ma_node_set_time()`. */
ma_uint32 inputBusCount;
ma_uint32 outputBusCount;
ma_node_input_bus* pInputBuses;
ma_node_output_bus* pOutputBuses;
/* Memory management. */
ma_node_input_bus _inputBuses[MA_MAX_NODE_LOCAL_BUS_COUNT];
ma_node_output_bus _outputBuses[MA_MAX_NODE_LOCAL_BUS_COUNT];
void* _pHeap; /* A heap allocation for internal use only. pInputBuses and/or pOutputBuses will point to this if the bus count exceeds MA_MAX_NODE_LOCAL_BUS_COUNT. */
ma_bool32 _ownsHeap; /* If set to true, the node owns the heap allocation and _pHeap will be freed in ma_node_uninit(). */
};
MA_API ma_result ma_node_get_heap_size(ma_node_graph* pNodeGraph, const ma_node_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_node_init_preallocated(ma_node_graph* pNodeGraph, const ma_node_config* pConfig, void* pHeap, ma_node* pNode);
MA_API ma_result ma_node_init(ma_node_graph* pNodeGraph, const ma_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_node* pNode);
MA_API void ma_node_uninit(ma_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_node_graph* ma_node_get_node_graph(const ma_node* pNode);
MA_API ma_uint32 ma_node_get_input_bus_count(const ma_node* pNode);
MA_API ma_uint32 ma_node_get_output_bus_count(const ma_node* pNode);
MA_API ma_uint32 ma_node_get_input_channels(const ma_node* pNode, ma_uint32 inputBusIndex);
MA_API ma_uint32 ma_node_get_output_channels(const ma_node* pNode, ma_uint32 outputBusIndex);
MA_API ma_result ma_node_attach_output_bus(ma_node* pNode, ma_uint32 outputBusIndex, ma_node* pOtherNode, ma_uint32 otherNodeInputBusIndex);
MA_API ma_result ma_node_detach_output_bus(ma_node* pNode, ma_uint32 outputBusIndex);
MA_API ma_result ma_node_detach_all_output_buses(ma_node* pNode);
MA_API ma_result ma_node_set_output_bus_volume(ma_node* pNode, ma_uint32 outputBusIndex, float volume);
MA_API float ma_node_get_output_bus_volume(const ma_node* pNode, ma_uint32 outputBusIndex);
MA_API ma_result ma_node_set_state(ma_node* pNode, ma_node_state state);
MA_API ma_node_state ma_node_get_state(const ma_node* pNode);
MA_API ma_result ma_node_set_state_time(ma_node* pNode, ma_node_state state, ma_uint64 globalTime);
MA_API ma_uint64 ma_node_get_state_time(const ma_node* pNode, ma_node_state state);
MA_API ma_node_state ma_node_get_state_by_time(const ma_node* pNode, ma_uint64 globalTime);
MA_API ma_node_state ma_node_get_state_by_time_range(const ma_node* pNode, ma_uint64 globalTimeBeg, ma_uint64 globalTimeEnd);
MA_API ma_uint64 ma_node_get_time(const ma_node* pNode);
MA_API ma_result ma_node_set_time(ma_node* pNode, ma_uint64 localTime);
typedef struct
{
ma_uint32 channels;
ma_uint16 nodeCacheCapInFrames;
} ma_node_graph_config;
MA_API ma_node_graph_config ma_node_graph_config_init(ma_uint32 channels);
struct ma_node_graph
{
/* Immutable. */
ma_node_base base; /* The node graph itself is a node so it can be connected as an input to different node graph. This has zero inputs and calls ma_node_graph_read_pcm_frames() to generate it's output. */
ma_node_base endpoint; /* Special node that all nodes eventually connect to. Data is read from this node in ma_node_graph_read_pcm_frames(). */
ma_uint16 nodeCacheCapInFrames;
/* Read and written by multiple threads. */
MA_ATOMIC(4, ma_bool32) isReading;
};
MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_node_graph* pNodeGraph);
MA_API void ma_node_graph_uninit(ma_node_graph* pNodeGraph, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_node* ma_node_graph_get_endpoint(ma_node_graph* pNodeGraph);
MA_API ma_result ma_node_graph_read_pcm_frames(ma_node_graph* pNodeGraph, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_uint32 ma_node_graph_get_channels(const ma_node_graph* pNodeGraph);
MA_API ma_uint64 ma_node_graph_get_time(const ma_node_graph* pNodeGraph);
MA_API ma_result ma_node_graph_set_time(ma_node_graph* pNodeGraph, ma_uint64 globalTime);
/* Data source node. 0 input buses, 1 output bus. Used for reading from a data source. */
typedef struct
{
ma_node_config nodeConfig;
ma_data_source* pDataSource;
} ma_data_source_node_config;
MA_API ma_data_source_node_config ma_data_source_node_config_init(ma_data_source* pDataSource);
typedef struct
{
ma_node_base base;
ma_data_source* pDataSource;
} ma_data_source_node;
MA_API ma_result ma_data_source_node_init(ma_node_graph* pNodeGraph, const ma_data_source_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source_node* pDataSourceNode);
MA_API void ma_data_source_node_uninit(ma_data_source_node* pDataSourceNode, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_data_source_node_set_looping(ma_data_source_node* pDataSourceNode, ma_bool32 isLooping);
MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSourceNode);
/* Splitter Node. 1 input, 2 outputs. Used for splitting/copying a stream so it can be as input into two separate output nodes. */
typedef struct
{
ma_node_config nodeConfig;
ma_uint32 channels;
} ma_splitter_node_config;
MA_API ma_splitter_node_config ma_splitter_node_config_init(ma_uint32 channels);
typedef struct
{
ma_node_base base;
} ma_splitter_node;
MA_API ma_result ma_splitter_node_init(ma_node_graph* pNodeGraph, const ma_splitter_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_splitter_node* pSplitterNode);
MA_API void ma_splitter_node_uninit(ma_splitter_node* pSplitterNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Biquad Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_biquad_config biquad;
} ma_biquad_node_config;
MA_API ma_biquad_node_config ma_biquad_node_config_init(ma_uint32 channels, float b0, float b1, float b2, float a0, float a1, float a2);
typedef struct
{
ma_node_base baseNode;
ma_biquad biquad;
} ma_biquad_node;
MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad_node* pNode);
MA_API ma_result ma_biquad_node_reinit(const ma_biquad_config* pConfig, ma_biquad_node* pNode);
MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Low Pass Filter Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_lpf_config lpf;
} ma_lpf_node_config;
MA_API ma_lpf_node_config ma_lpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct
{
ma_node_base baseNode;
ma_lpf lpf;
} ma_lpf_node;
MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf_node* pNode);
MA_API ma_result ma_lpf_node_reinit(const ma_lpf_config* pConfig, ma_lpf_node* pNode);
MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
High Pass Filter Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_hpf_config hpf;
} ma_hpf_node_config;
MA_API ma_hpf_node_config ma_hpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct
{
ma_node_base baseNode;
ma_hpf hpf;
} ma_hpf_node;
MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf_node* pNode);
MA_API ma_result ma_hpf_node_reinit(const ma_hpf_config* pConfig, ma_hpf_node* pNode);
MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Band Pass Filter Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_bpf_config bpf;
} ma_bpf_node_config;
MA_API ma_bpf_node_config ma_bpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order);
typedef struct
{
ma_node_base baseNode;
ma_bpf bpf;
} ma_bpf_node;
MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf_node* pNode);
MA_API ma_result ma_bpf_node_reinit(const ma_bpf_config* pConfig, ma_bpf_node* pNode);
MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Notching Filter Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_notch_config notch;
} ma_notch_node_config;
MA_API ma_notch_node_config ma_notch_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency);
typedef struct
{
ma_node_base baseNode;
ma_notch2 notch;
} ma_notch_node;
MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch_node* pNode);
MA_API ma_result ma_notch_node_reinit(const ma_notch_config* pConfig, ma_notch_node* pNode);
MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Peaking Filter Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_peak_config peak;
} ma_peak_node_config;
MA_API ma_peak_node_config ma_peak_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
typedef struct
{
ma_node_base baseNode;
ma_peak2 peak;
} ma_peak_node;
MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak_node* pNode);
MA_API ma_result ma_peak_node_reinit(const ma_peak_config* pConfig, ma_peak_node* pNode);
MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
Low Shelf Filter Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_loshelf_config loshelf;
} ma_loshelf_node_config;
MA_API ma_loshelf_node_config ma_loshelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
typedef struct
{
ma_node_base baseNode;
ma_loshelf2 loshelf;
} ma_loshelf_node;
MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf_node* pNode);
MA_API ma_result ma_loshelf_node_reinit(const ma_loshelf_config* pConfig, ma_loshelf_node* pNode);
MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
/*
High Shelf Filter Node
*/
typedef struct
{
ma_node_config nodeConfig;
ma_hishelf_config hishelf;
} ma_hishelf_node_config;
MA_API ma_hishelf_node_config ma_hishelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency);
typedef struct
{
ma_node_base baseNode;
ma_hishelf2 hishelf;
} ma_hishelf_node;
MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf_node* pNode);
MA_API ma_result ma_hishelf_node_reinit(const ma_hishelf_config* pConfig, ma_hishelf_node* pNode);
MA_API void ma_hishelf_node_uninit(ma_hishelf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks);
typedef struct
{
ma_node_config nodeConfig;
ma_delay_config delay;
} ma_delay_node_config;
MA_API ma_delay_node_config ma_delay_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay);
typedef struct
{
ma_node_base baseNode;
ma_delay delay;
} ma_delay_node;
MA_API ma_result ma_delay_node_init(ma_node_graph* pNodeGraph, const ma_delay_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay_node* pDelayNode);
MA_API void ma_delay_node_uninit(ma_delay_node* pDelayNode, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API void ma_delay_node_set_wet(ma_delay_node* pDelayNode, float value);
MA_API float ma_delay_node_get_wet(const ma_delay_node* pDelayNode);
MA_API void ma_delay_node_set_dry(ma_delay_node* pDelayNode, float value);
MA_API float ma_delay_node_get_dry(const ma_delay_node* pDelayNode);
MA_API void ma_delay_node_set_decay(ma_delay_node* pDelayNode, float value);
MA_API float ma_delay_node_get_decay(const ma_delay_node* pDelayNode);
#endif /* MA_NO_NODE_GRAPH */
/************************************************************************************************************************************************************
Engine
************************************************************************************************************************************************************/
#if !defined(MA_NO_ENGINE) && !defined(MA_NO_NODE_GRAPH)
typedef struct ma_engine ma_engine;
typedef struct ma_sound ma_sound;
/* Sound flags. */
typedef enum
{
MA_SOUND_FLAG_STREAM = 0x00000001, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM */
MA_SOUND_FLAG_DECODE = 0x00000002, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE */
MA_SOUND_FLAG_ASYNC = 0x00000004, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC */
MA_SOUND_FLAG_WAIT_INIT = 0x00000008, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT */
MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT = 0x00000010, /* Do not attach to the endpoint by default. Useful for when setting up nodes in a complex graph system. */
MA_SOUND_FLAG_NO_PITCH = 0x00000020, /* Disable pitch shifting with ma_sound_set_pitch() and ma_sound_group_set_pitch(). This is an optimization. */
MA_SOUND_FLAG_NO_SPATIALIZATION = 0x00000040 /* Disable spatialization. */
} ma_sound_flags;
#ifndef MA_ENGINE_MAX_LISTENERS
#define MA_ENGINE_MAX_LISTENERS 4
#endif
#define MA_LISTENER_INDEX_CLOSEST ((ma_uint8)-1)
typedef enum
{
ma_engine_node_type_sound,
ma_engine_node_type_group
} ma_engine_node_type;
typedef struct
{
ma_engine* pEngine;
ma_engine_node_type type;
ma_uint32 channelsIn;
ma_uint32 channelsOut;
ma_uint32 sampleRate; /* Only used when the type is set to ma_engine_node_type_sound. */
ma_bool8 isPitchDisabled; /* Pitching can be explicitly disable with MA_SOUND_FLAG_NO_PITCH to optimize processing. */
ma_bool8 isSpatializationDisabled; /* Spatialization can be explicitly disabled with MA_SOUND_FLAG_NO_SPATIALIZATION. */
ma_uint8 pinnedListenerIndex; /* The index of the listener this node should always use for spatialization. If set to MA_LISTENER_INDEX_CLOSEST the engine will use the closest listener. */
} ma_engine_node_config;
MA_API ma_engine_node_config ma_engine_node_config_init(ma_engine* pEngine, ma_engine_node_type type, ma_uint32 flags);
/* Base node object for both ma_sound and ma_sound_group. */
typedef struct
{
ma_node_base baseNode; /* Must be the first member for compatiblity with the ma_node API. */
ma_engine* pEngine; /* A pointer to the engine. Set based on the value from the config. */
ma_uint32 sampleRate; /* The sample rate of the input data. For sounds backed by a data source, this will be the data source's sample rate. Otherwise it'll be the engine's sample rate. */
ma_fader fader;
ma_linear_resampler resampler; /* For pitch shift. */
ma_spatializer spatializer;
ma_panner panner;
MA_ATOMIC(4, float) pitch;
float oldPitch; /* For determining whether or not the resampler needs to be updated to reflect the new pitch. The resampler will be updated on the mixing thread. */
float oldDopplerPitch; /* For determining whether or not the resampler needs to be updated to take a new doppler pitch into account. */
MA_ATOMIC(4, ma_bool32) isPitchDisabled; /* When set to true, pitching will be disabled which will allow the resampler to be bypassed to save some computation. */
MA_ATOMIC(4, ma_bool32) isSpatializationDisabled; /* Set to false by default. When set to false, will not have spatialisation applied. */
MA_ATOMIC(4, ma_uint32) pinnedListenerIndex; /* The index of the listener this node should always use for spatialization. If set to MA_LISTENER_INDEX_CLOSEST the engine will use the closest listener. */
/* Memory management. */
ma_bool8 _ownsHeap;
void* _pHeap;
} ma_engine_node;
MA_API ma_result ma_engine_node_get_heap_size(const ma_engine_node_config* pConfig, size_t* pHeapSizeInBytes);
MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* pConfig, void* pHeap, ma_engine_node* pEngineNode);
MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_engine_node* pEngineNode);
MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocation_callbacks* pAllocationCallbacks);
#define MA_SOUND_SOURCE_CHANNEL_COUNT 0xFFFFFFFF
typedef struct
{
const char* pFilePath; /* Set this to load from the resource manager. */
const wchar_t* pFilePathW; /* Set this to load from the resource manager. */
ma_data_source* pDataSource; /* Set this to load from an existing data source. */
ma_node* pInitialAttachment; /* If set, the sound will be attached to an input of this node. This can be set to a ma_sound. If set to NULL, the sound will be attached directly to the endpoint unless MA_SOUND_FLAG_NO_DEFAULT_ATTACHM...
ma_uint32 initialAttachmentInputBusIndex; /* The index of the input bus of pInitialAttachment to attach the sound to. */
ma_uint32 channelsIn; /* Ignored if using a data source as input (the data source's channel count will be used always). Otherwise, setting to 0 will cause the engine's channel count to be used. */
ma_uint32 channelsOut; /* Set this to 0 (default) to use the engine's channel count. Set to MA_SOUND_SOURCE_CHANNEL_COUNT to use the data source's channel count (only used if using a data source as input). */
ma_uint32 flags; /* A combination of MA_SOUND_FLAG_* flags. */
ma_uint64 initialSeekPointInPCMFrames; /* Initializes the sound such that it's seeked to this location by default. */
ma_uint64 rangeBegInPCMFrames;
ma_uint64 rangeEndInPCMFrames;
ma_uint64 loopPointBegInPCMFrames;
ma_uint64 loopPointEndInPCMFrames;
ma_bool32 isLooping;
ma_fence* pDoneFence; /* Released when the resource manager has finished decoding the entire sound. Not used with streams. */
} ma_sound_config;
MA_API ma_sound_config ma_sound_config_init(void);
struct ma_sound
{
ma_engine_node engineNode; /* Must be the first member for compatibility with the ma_node API. */
ma_data_source* pDataSource;
MA_ATOMIC(8, ma_uint64) seekTarget; /* The PCM frame index to seek to in the mixing thread. Set to (~(ma_uint64)0) to not perform any seeking. */
MA_ATOMIC(4, ma_bool32) atEnd;
ma_bool8 ownsDataSource;
/*
We're declaring a resource manager data source object here to save us a malloc when loading a
sound via the resource manager, which I *think* will be the most common scenario.
*/
#ifndef MA_NO_RESOURCE_MANAGER
ma_resource_manager_data_source* pResourceManagerDataSource;
#endif
};
/* Structure specifically for sounds played with ma_engine_play_sound(). Making this a separate structure to reduce overhead. */
typedef struct ma_sound_inlined ma_sound_inlined;
struct ma_sound_inlined
{
ma_sound sound;
ma_sound_inlined* pNext;
ma_sound_inlined* pPrev;
};
/* A sound group is just a sound. */
typedef ma_sound_config ma_sound_group_config;
typedef ma_sound ma_sound_group;
MA_API ma_sound_group_config ma_sound_group_config_init(void);
typedef struct
{
#if !defined(MA_NO_RESOURCE_MANAGER)
ma_resource_manager* pResourceManager; /* Can be null in which case a resource manager will be created for you. */
#endif
#if !defined(MA_NO_DEVICE_IO)
ma_context* pContext;
ma_device* pDevice; /* If set, the caller is responsible for calling ma_engine_data_callback() in the device's data callback. */
ma_device_id* pPlaybackDeviceID; /* The ID of the playback device to use with the default listener. */
#endif
ma_log* pLog; /* When set to NULL, will use the context's log. */
ma_uint32 listenerCount; /* Must be between 1 and MA_ENGINE_MAX_LISTENERS. */
ma_uint32 channels; /* The number of channels to use when mixing and spatializing. When set to 0, will use the native channel count of the device. */
ma_uint32 sampleRate; /* The sample rate. When set to 0 will use the native channel count of the device. */
ma_uint32 periodSizeInFrames; /* If set to something other than 0, updates will always be exactly this size. The underlying device may be a different size, but from the perspective of the mixer that won't matter.*/
ma_uint32 periodSizeInMilliseconds; /* Used if periodSizeInFrames is unset. */
ma_uint32 gainSmoothTimeInFrames; /* The number of frames to interpolate the gain of spatialized sounds across. If set to 0, will use gainSmoothTimeInMilliseconds. */
ma_uint32 gainSmoothTimeInMilliseconds; /* When set to 0, gainSmoothTimeInFrames will be used. If both are set to 0, a default value will be used. */
ma_allocation_callbacks allocationCallbacks;
ma_bool32 noAutoStart; /* When set to true, requires an explicit call to ma_engine_start(). This is false by default, meaning the engine will be started automatically in ma_engine_init(). */
ma_bool32 noDevice; /* When set to true, don't create a default device. ma_engine_read_pcm_frames() can be called manually to read data. */
ma_mono_expansion_mode monoExpansionMode; /* Controls how the mono channel should be expanded to other channels when spatialization is disabled on a sound. */
ma_vfs* pResourceManagerVFS; /* A pointer to a pre-allocated VFS object to use with the resource manager. This is ignored if pResourceManager is not NULL. */
} ma_engine_config;
MA_API ma_engine_config ma_engine_config_init(void);
struct ma_engine
{
ma_node_graph nodeGraph; /* An engine is a node graph. It should be able to be plugged into any ma_node_graph API (with a cast) which means this must be the first member of this struct. */
#if !defined(MA_NO_RESOURCE_MANAGER)
ma_resource_manager* pResourceManager;
#endif
#if !defined(MA_NO_DEVICE_IO)
ma_device* pDevice; /* Optionally set via the config, otherwise allocated by the engine in ma_engine_init(). */
#endif
ma_log* pLog;
ma_uint32 sampleRate;
ma_uint32 listenerCount;
ma_spatializer_listener listeners[MA_ENGINE_MAX_LISTENERS];
ma_allocation_callbacks allocationCallbacks;
ma_bool8 ownsResourceManager;
ma_bool8 ownsDevice;
ma_spinlock inlinedSoundLock; /* For synchronizing access so the inlined sound list. */
ma_sound_inlined* pInlinedSoundHead; /* The first inlined sound. Inlined sounds are tracked in a linked list. */
MA_ATOMIC(4, ma_uint32) inlinedSoundCount; /* The total number of allocated inlined sound objects. Used for debugging. */
ma_uint32 gainSmoothTimeInFrames; /* The number of frames to interpolate the gain of spatialized sounds across. */
ma_mono_expansion_mode monoExpansionMode;
};
MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEngine);
MA_API void ma_engine_uninit(ma_engine* pEngine);
MA_API ma_result ma_engine_read_pcm_frames(ma_engine* pEngine, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_node_graph* ma_engine_get_node_graph(ma_engine* pEngine);
#if !defined(MA_NO_RESOURCE_MANAGER)
MA_API ma_resource_manager* ma_engine_get_resource_manager(ma_engine* pEngine);
#endif
MA_API ma_device* ma_engine_get_device(ma_engine* pEngine);
MA_API ma_log* ma_engine_get_log(ma_engine* pEngine);
MA_API ma_node* ma_engine_get_endpoint(ma_engine* pEngine);
MA_API ma_uint64 ma_engine_get_time(const ma_engine* pEngine);
MA_API ma_result ma_engine_set_time(ma_engine* pEngine, ma_uint64 globalTime);
MA_API ma_uint32 ma_engine_get_channels(const ma_engine* pEngine);
MA_API ma_uint32 ma_engine_get_sample_rate(const ma_engine* pEngine);
MA_API ma_result ma_engine_start(ma_engine* pEngine);
MA_API ma_result ma_engine_stop(ma_engine* pEngine);
MA_API ma_result ma_engine_set_volume(ma_engine* pEngine, float volume);
MA_API ma_result ma_engine_set_gain_db(ma_engine* pEngine, float gainDB);
MA_API ma_uint32 ma_engine_get_listener_count(const ma_engine* pEngine);
MA_API ma_uint32 ma_engine_find_closest_listener(const ma_engine* pEngine, float absolutePosX, float absolutePosY, float absolutePosZ);
MA_API void ma_engine_listener_set_position(ma_engine* pEngine, ma_uint32 listenerIndex, float x, float y, float z);
MA_API ma_vec3f ma_engine_listener_get_position(const ma_engine* pEngine, ma_uint32 listenerIndex);
MA_API void ma_engine_listener_set_direction(ma_engine* pEngine, ma_uint32 listenerIndex, float x, float y, float z);
MA_API ma_vec3f ma_engine_listener_get_direction(const ma_engine* pEngine, ma_uint32 listenerIndex);
MA_API void ma_engine_listener_set_velocity(ma_engine* pEngine, ma_uint32 listenerIndex, float x, float y, float z);
MA_API ma_vec3f ma_engine_listener_get_velocity(const ma_engine* pEngine, ma_uint32 listenerIndex);
MA_API void ma_engine_listener_set_cone(ma_engine* pEngine, ma_uint32 listenerIndex, float innerAngleInRadians, float outerAngleInRadians, float outerGain);
MA_API void ma_engine_listener_get_cone(const ma_engine* pEngine, ma_uint32 listenerIndex, float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain);
MA_API void ma_engine_listener_set_world_up(ma_engine* pEngine, ma_uint32 listenerIndex, float x, float y, float z);
MA_API ma_vec3f ma_engine_listener_get_world_up(const ma_engine* pEngine, ma_uint32 listenerIndex);
MA_API void ma_engine_listener_set_enabled(ma_engine* pEngine, ma_uint32 listenerIndex, ma_bool32 isEnabled);
MA_API ma_bool32 ma_engine_listener_is_enabled(const ma_engine* pEngine, ma_uint32 listenerIndex);
#ifndef MA_NO_RESOURCE_MANAGER
MA_API ma_result ma_engine_play_sound_ex(ma_engine* pEngine, const char* pFilePath, ma_node* pNode, ma_uint32 nodeInputBusIndex);
MA_API ma_result ma_engine_play_sound(ma_engine* pEngine, const char* pFilePath, ma_sound_group* pGroup); /* Fire and forget. */
#endif
#ifndef MA_NO_RESOURCE_MANAGER
MA_API ma_result ma_sound_init_from_file(ma_engine* pEngine, const char* pFilePath, ma_uint32 flags, ma_sound_group* pGroup, ma_fence* pDoneFence, ma_sound* pSound);
MA_API ma_result ma_sound_init_from_file_w(ma_engine* pEngine, const wchar_t* pFilePath, ma_uint32 flags, ma_sound_group* pGroup, ma_fence* pDoneFence, ma_sound* pSound);
MA_API ma_result ma_sound_init_copy(ma_engine* pEngine, const ma_sound* pExistingSound, ma_uint32 flags, ma_sound_group* pGroup, ma_sound* pSound);
#endif
MA_API ma_result ma_sound_init_from_data_source(ma_engine* pEngine, ma_data_source* pDataSource, ma_uint32 flags, ma_sound_group* pGroup, ma_sound* pSound);
MA_API ma_result ma_sound_init_ex(ma_engine* pEngine, const ma_sound_config* pConfig, ma_sound* pSound);
MA_API void ma_sound_uninit(ma_sound* pSound);
MA_API ma_engine* ma_sound_get_engine(const ma_sound* pSound);
MA_API ma_data_source* ma_sound_get_data_source(const ma_sound* pSound);
MA_API ma_result ma_sound_start(ma_sound* pSound);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
return 22; /* Ran out of room in the output buffer. */
}
*dstEnd = '\0';
/* At this point the string will be reversed. */
dstEnd -= 1;
while (dst < dstEnd) {
char temp = *dst;
*dst = *dstEnd;
*dstEnd = temp;
dst += 1;
dstEnd -= 1;
}
return 0;
}
MA_API int ma_strcmp(const char* str1, const char* str2)
{
if (str1 == str2) return 0;
/* These checks differ from the standard implementation. It's not important, but I prefer it just for sanity. */
if (str1 == NULL) return -1;
if (str2 == NULL) return 1;
for (;;) {
if (str1[0] == '\0') {
break;
}
if (str1[0] != str2[0]) {
break;
}
str1 += 1;
str2 += 1;
}
return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0];
}
MA_API int ma_strappend(char* dst, size_t dstSize, const char* srcA, const char* srcB)
{
int result;
result = ma_strncpy_s(dst, dstSize, srcA, (size_t)-1);
if (result != 0) {
return result;
}
result = ma_strncat_s(dst, dstSize, srcB, (size_t)-1);
if (result != 0) {
return result;
}
return result;
}
MA_API char* ma_copy_string(const char* src, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (src == NULL) {
return NULL;
}
size_t sz = strlen(src)+1;
char* dst = (char*)ma_malloc(sz, pAllocationCallbacks);
if (dst == NULL) {
return NULL;
}
ma_strcpy_s(dst, sz, src);
return dst;
}
MA_API wchar_t* ma_copy_string_w(const wchar_t* src, const ma_allocation_callbacks* pAllocationCallbacks)
{
size_t sz = wcslen(src)+1;
wchar_t* dst = (wchar_t*)ma_malloc(sz * sizeof(*dst), pAllocationCallbacks);
if (dst == NULL) {
return NULL;
}
ma_wcscpy_s(dst, sz, src);
return dst;
}
#include <errno.h>
static ma_result ma_result_from_errno(int e)
{
switch (e)
{
case 0: return MA_SUCCESS;
#ifdef EPERM
case EPERM: return MA_INVALID_OPERATION;
#endif
#ifdef ENOENT
case ENOENT: return MA_DOES_NOT_EXIST;
#endif
#ifdef ESRCH
case ESRCH: return MA_DOES_NOT_EXIST;
#endif
#ifdef EINTR
case EINTR: return MA_INTERRUPT;
#endif
#ifdef EIO
case EIO: return MA_IO_ERROR;
#endif
#ifdef ENXIO
case ENXIO: return MA_DOES_NOT_EXIST;
#endif
#ifdef E2BIG
case E2BIG: return MA_INVALID_ARGS;
#endif
#ifdef ENOEXEC
case ENOEXEC: return MA_INVALID_FILE;
#endif
#ifdef EBADF
case EBADF: return MA_INVALID_FILE;
#endif
#ifdef ECHILD
case ECHILD: return MA_ERROR;
#endif
#ifdef EAGAIN
case EAGAIN: return MA_UNAVAILABLE;
#endif
#ifdef ENOMEM
case ENOMEM: return MA_OUT_OF_MEMORY;
#endif
#ifdef EACCES
case EACCES: return MA_ACCESS_DENIED;
#endif
#ifdef EFAULT
case EFAULT: return MA_BAD_ADDRESS;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err;
#endif
if (ppFile != NULL) {
*ppFile = NULL; /* Safety. */
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return MA_INVALID_ARGS;
}
#if defined(_MSC_VER) && _MSC_VER >= 1400
err = fopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return ma_result_from_errno(err);
}
#else
#if defined(_WIN32) || defined(__APPLE__)
*ppFile = fopen(pFilePath, pOpenMode);
#else
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
*ppFile = fopen64(pFilePath, pOpenMode);
#else
*ppFile = fopen(pFilePath, pOpenMode);
#endif
#endif
if (*ppFile == NULL) {
ma_result result = ma_result_from_errno(errno);
if (result == MA_SUCCESS) {
result = MA_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
}
return result;
}
#endif
return MA_SUCCESS;
}
/*
_wfopen() isn't always available in all compilation environments.
* Windows only.
* MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
* MinGW-64 (both 32- and 64-bit) seems to support it.
* MinGW wraps it in !defined(__STRICT_ANSI__).
* OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
*/
#if defined(_WIN32)
#if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
#define MA_HAS_WFOPEN
#endif
#endif
MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (ppFile != NULL) {
*ppFile = NULL; /* Safety. */
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return MA_INVALID_ARGS;
}
#if defined(MA_HAS_WFOPEN)
{
/* Use _wfopen() on Windows. */
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return ma_result_from_errno(err);
}
#else
*ppFile = _wfopen(pFilePath, pOpenMode);
if (*ppFile == NULL) {
return ma_result_from_errno(errno);
}
#endif
(void)pAllocationCallbacks;
}
#else
/*
Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
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
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.
*/
{
mbstate_t mbs;
size_t lenMB;
const wchar_t* pFilePathTemp = pFilePath;
char* pFilePathMB = NULL;
char pOpenModeMB[32] = {0};
/* Get the length first. */
MA_ZERO_OBJECT(&mbs);
lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
if (lenMB == (size_t)-1) {
return ma_result_from_errno(errno);
}
pFilePathMB = (char*)ma_malloc(lenMB + 1, pAllocationCallbacks);
if (pFilePathMB == NULL) {
return MA_OUT_OF_MEMORY;
}
pFilePathTemp = pFilePath;
MA_ZERO_OBJECT(&mbs);
wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
/* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
{
size_t i = 0;
for (;;) {
if (pOpenMode[i] == 0) {
pOpenModeMB[i] = '\0';
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
x++;
return x;
}
static MA_INLINE unsigned int ma_prev_power_of_2(unsigned int x)
{
return ma_next_power_of_2(x) >> 1;
}
static MA_INLINE unsigned int ma_round_to_power_of_2(unsigned int x)
{
unsigned int prev = ma_prev_power_of_2(x);
unsigned int next = ma_next_power_of_2(x);
if ((next - x) > (x - prev)) {
return prev;
} else {
return next;
}
}
static MA_INLINE unsigned int ma_count_set_bits(unsigned int x)
{
unsigned int count = 0;
while (x != 0) {
if (x & 1) {
count += 1;
}
x = x >> 1;
}
return count;
}
/**************************************************************************************************************************************************************
Allocation Callbacks
**************************************************************************************************************************************************************/
static void* ma__malloc_default(size_t sz, void* pUserData)
{
(void)pUserData;
return MA_MALLOC(sz);
}
static void* ma__realloc_default(void* p, size_t sz, void* pUserData)
{
(void)pUserData;
return MA_REALLOC(p, sz);
}
static void ma__free_default(void* p, void* pUserData)
{
(void)pUserData;
MA_FREE(p);
}
static ma_allocation_callbacks ma_allocation_callbacks_init_default(void)
{
ma_allocation_callbacks callbacks;
callbacks.pUserData = NULL;
callbacks.onMalloc = ma__malloc_default;
callbacks.onRealloc = ma__realloc_default;
callbacks.onFree = ma__free_default;
return callbacks;
}
static ma_result ma_allocation_callbacks_init_copy(ma_allocation_callbacks* pDst, const ma_allocation_callbacks* pSrc)
{
if (pDst == NULL) {
return MA_INVALID_ARGS;
}
if (pSrc == NULL) {
*pDst = ma_allocation_callbacks_init_default();
} else {
if (pSrc->pUserData == NULL && pSrc->onFree == NULL && pSrc->onMalloc == NULL && pSrc->onRealloc == NULL) {
*pDst = ma_allocation_callbacks_init_default();
} else {
if (pSrc->onFree == NULL || (pSrc->onMalloc == NULL && pSrc->onRealloc == NULL)) {
return MA_INVALID_ARGS; /* Invalid allocation callbacks. */
} else {
*pDst = *pSrc;
}
}
}
return MA_SUCCESS;
}
/**************************************************************************************************************************************************************
Logging
**************************************************************************************************************************************************************/
MA_API const char* ma_log_level_to_string(ma_uint32 logLevel)
{
switch (logLevel)
{
case MA_LOG_LEVEL_DEBUG: return "DEBUG";
case MA_LOG_LEVEL_INFO: return "INFO";
case MA_LOG_LEVEL_WARNING: return "WARNING";
case MA_LOG_LEVEL_ERROR: return "ERROR";
default: return "ERROR";
}
}
#if defined(MA_DEBUG_OUTPUT)
/* Customize this to use a specific tag in __android_log_print() for debug output messages. */
#ifndef MA_ANDROID_LOG_TAG
#define MA_ANDROID_LOG_TAG "miniaudio"
#endif
void ma_log_callback_debug(void* pUserData, ma_uint32 level, const char* pMessage)
{
(void)pUserData;
/* Special handling for some platforms. */
#if defined(MA_ANDROID)
{
/* Android. */
__android_log_print(ANDROID_LOG_DEBUG, MA_ANDROID_LOG_TAG, "%s: %s", ma_log_level_to_string(level), pMessage);
}
#else
{
/* Everything else. */
printf("%s: %s", ma_log_level_to_string(level), pMessage);
}
#endif
}
#endif
MA_API ma_log_callback ma_log_callback_init(ma_log_callback_proc onLog, void* pUserData)
{
ma_log_callback callback;
MA_ZERO_OBJECT(&callback);
callback.onLog = onLog;
callback.pUserData = pUserData;
return callback;
}
MA_API ma_result ma_log_init(const ma_allocation_callbacks* pAllocationCallbacks, ma_log* pLog)
{
if (pLog == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pLog);
ma_allocation_callbacks_init_copy(&pLog->allocationCallbacks, pAllocationCallbacks);
/* We need a mutex for thread safety. */
#ifndef MA_NO_THREADING
{
ma_result result = ma_mutex_init(&pLog->lock);
if (result != MA_SUCCESS) {
return result;
}
}
#endif
/* If we're using debug output, enable it. */
#if defined(MA_DEBUG_OUTPUT)
{
ma_log_register_callback(pLog, ma_log_callback_init(ma_log_callback_debug, NULL)); /* Doesn't really matter if this fails. */
}
#endif
return MA_SUCCESS;
}
MA_API void ma_log_uninit(ma_log* pLog)
{
if (pLog == NULL) {
return;
}
#ifndef MA_NO_THREADING
ma_mutex_uninit(&pLog->lock);
#endif
}
static void ma_log_lock(ma_log* pLog)
{
#ifndef MA_NO_THREADING
ma_mutex_lock(&pLog->lock);
#else
(void)pLog;
#endif
}
static void ma_log_unlock(ma_log* pLog)
{
#ifndef MA_NO_THREADING
ma_mutex_unlock(&pLog->lock);
#else
(void)pLog;
#endif
}
MA_API ma_result ma_log_register_callback(ma_log* pLog, ma_log_callback callback)
{
ma_result result = MA_SUCCESS;
if (pLog == NULL || callback.onLog == NULL) {
return MA_INVALID_ARGS;
}
ma_log_lock(pLog);
{
if (pLog->callbackCount == ma_countof(pLog->callbacks)) {
result = MA_OUT_OF_MEMORY; /* Reached the maximum allowed log callbacks. */
} else {
pLog->callbacks[pLog->callbackCount] = callback;
pLog->callbackCount += 1;
}
}
ma_log_unlock(pLog);
return result;
}
MA_API ma_result ma_log_unregister_callback(ma_log* pLog, ma_log_callback callback)
{
if (pLog == NULL) {
return MA_INVALID_ARGS;
}
ma_log_lock(pLog);
{
ma_uint32 iLog;
for (iLog = 0; iLog < pLog->callbackCount; ) {
if (pLog->callbacks[iLog].onLog == callback.onLog) {
/* Found. Move everything down a slot. */
ma_uint32 jLog;
for (jLog = iLog; jLog < pLog->callbackCount-1; jLog += 1) {
pLog->callbacks[jLog] = pLog->callbacks[jLog + 1];
}
pLog->callbackCount -= 1;
} else {
/* Not found. */
iLog += 1;
}
}
}
ma_log_unlock(pLog);
return MA_SUCCESS;
}
MA_API ma_result ma_log_post(ma_log* pLog, ma_uint32 level, const char* pMessage)
{
if (pLog == NULL || pMessage == NULL) {
return MA_INVALID_ARGS;
}
ma_log_lock(pLog);
{
ma_uint32 iLog;
for (iLog = 0; iLog < pLog->callbackCount; iLog += 1) {
if (pLog->callbacks[iLog].onLog) {
pLog->callbacks[iLog].onLog(pLog->callbacks[iLog].pUserData, level, pMessage);
}
}
}
ma_log_unlock(pLog);
return MA_SUCCESS;
}
/*
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
logging function, I'm happy to keep this simple. In the VC6 build we can implement this in terms of _vsnprintf().
*/
#if defined(_MSC_VER) && _MSC_VER < 1900
static int ma_vscprintf(const ma_allocation_callbacks* pAllocationCallbacks, const char* format, va_list args)
{
#if _MSC_VER > 1200
return _vscprintf(format, args);
#else
int result;
char* pTempBuffer = NULL;
size_t tempBufferCap = 1024;
if (format == NULL) {
errno = EINVAL;
return -1;
}
for (;;) {
char* pNewTempBuffer = (char*)ma_realloc(pTempBuffer, tempBufferCap, pAllocationCallbacks);
if (pNewTempBuffer == NULL) {
ma_free(pTempBuffer, pAllocationCallbacks);
errno = ENOMEM;
return -1; /* Out of memory. */
}
pTempBuffer = pNewTempBuffer;
result = _vsnprintf(pTempBuffer, tempBufferCap, format, args);
ma_free(pTempBuffer, NULL);
if (result != -1) {
break; /* Got it. */
}
/* 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. */
tempBufferCap *= 2;
}
return result;
#endif
}
#endif
MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat, va_list args)
{
if (pLog == NULL || pFormat == NULL) {
return MA_INVALID_ARGS;
}
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || ((!defined(_MSC_VER) || _MSC_VER >= 1900) && !defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
{
ma_result result;
int length;
char pFormattedMessageStack[1024];
char* pFormattedMessageHeap = NULL;
/* First try formatting into our fixed sized stack allocated buffer. If this is too small we'll fallback to a heap allocation. */
length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args);
if (length < 0) {
return MA_INVALID_OPERATION; /* An error occured when trying to convert the buffer. */
}
if ((size_t)length < sizeof(pFormattedMessageStack)) {
/* The string was written to the stack. */
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
result = pthread_cond_init((pthread_cond_t*)&pSemaphore->cond, NULL);
if (result != 0) {
pthread_mutex_destroy((pthread_mutex_t*)&pSemaphore->lock);
return ma_result_from_errno(result); /* Failed to create condition variable. */
}
return MA_SUCCESS;
}
static void ma_semaphore_uninit__posix(ma_semaphore* pSemaphore)
{
if (pSemaphore == NULL) {
return;
}
pthread_cond_destroy((pthread_cond_t*)&pSemaphore->cond);
pthread_mutex_destroy((pthread_mutex_t*)&pSemaphore->lock);
}
static ma_result ma_semaphore_wait__posix(ma_semaphore* pSemaphore)
{
if (pSemaphore == NULL) {
return MA_INVALID_ARGS;
}
pthread_mutex_lock((pthread_mutex_t*)&pSemaphore->lock);
{
/* We need to wait on a condition variable before escaping. We can't return from this function until the semaphore has been signaled. */
while (pSemaphore->value == 0) {
pthread_cond_wait((pthread_cond_t*)&pSemaphore->cond, (pthread_mutex_t*)&pSemaphore->lock);
}
pSemaphore->value -= 1;
}
pthread_mutex_unlock((pthread_mutex_t*)&pSemaphore->lock);
return MA_SUCCESS;
}
static ma_result ma_semaphore_release__posix(ma_semaphore* pSemaphore)
{
if (pSemaphore == NULL) {
return MA_INVALID_ARGS;
}
pthread_mutex_lock((pthread_mutex_t*)&pSemaphore->lock);
{
pSemaphore->value += 1;
pthread_cond_signal((pthread_cond_t*)&pSemaphore->cond);
}
pthread_mutex_unlock((pthread_mutex_t*)&pSemaphore->lock);
return MA_SUCCESS;
}
#endif
typedef struct
{
ma_thread_entry_proc entryProc;
void* pData;
ma_allocation_callbacks allocationCallbacks;
} ma_thread_proxy_data;
static ma_thread_result MA_THREADCALL ma_thread_entry_proxy(void* pData)
{
ma_thread_proxy_data* pProxyData = (ma_thread_proxy_data*)pData;
ma_thread_entry_proc entryProc;
void* pEntryProcData;
ma_thread_result result;
#if defined(MA_ON_THREAD_ENTRY)
MA_ON_THREAD_ENTRY
#endif
entryProc = pProxyData->entryProc;
pEntryProcData = pProxyData->pData;
/* Free the proxy data before getting into the real thread entry proc. */
ma_free(pProxyData, &pProxyData->allocationCallbacks);
result = entryProc(pEntryProcData);
#if defined(MA_ON_THREAD_EXIT)
MA_ON_THREAD_EXIT
#endif
return result;
}
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)
{
ma_result result;
ma_thread_proxy_data* pProxyData;
if (pThread == NULL || entryProc == NULL) {
return MA_INVALID_ARGS;
}
pProxyData = (ma_thread_proxy_data*)ma_malloc(sizeof(*pProxyData), pAllocationCallbacks); /* Will be freed by the proxy entry proc. */
if (pProxyData == NULL) {
return MA_OUT_OF_MEMORY;
}
pProxyData->entryProc = entryProc;
pProxyData->pData = pData;
ma_allocation_callbacks_init_copy(&pProxyData->allocationCallbacks, pAllocationCallbacks);
#ifdef MA_WIN32
result = ma_thread_create__win32(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
#endif
#ifdef MA_POSIX
result = ma_thread_create__posix(pThread, priority, stackSize, ma_thread_entry_proxy, pProxyData);
#endif
if (result != MA_SUCCESS) {
ma_free(pProxyData, pAllocationCallbacks);
return result;
}
return MA_SUCCESS;
}
static void ma_thread_wait(ma_thread* pThread)
{
if (pThread == NULL) {
return;
}
#ifdef MA_WIN32
ma_thread_wait__win32(pThread);
#endif
#ifdef MA_POSIX
ma_thread_wait__posix(pThread);
#endif
}
MA_API ma_result ma_mutex_init(ma_mutex* pMutex)
{
if (pMutex == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
return MA_INVALID_ARGS;
}
#ifdef MA_WIN32
return ma_mutex_init__win32(pMutex);
#endif
#ifdef MA_POSIX
return ma_mutex_init__posix(pMutex);
#endif
}
MA_API void ma_mutex_uninit(ma_mutex* pMutex)
{
if (pMutex == NULL) {
return;
}
#ifdef MA_WIN32
ma_mutex_uninit__win32(pMutex);
#endif
#ifdef MA_POSIX
ma_mutex_uninit__posix(pMutex);
#endif
}
MA_API void ma_mutex_lock(ma_mutex* pMutex)
{
if (pMutex == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
return;
}
#ifdef MA_WIN32
ma_mutex_lock__win32(pMutex);
#endif
#ifdef MA_POSIX
ma_mutex_lock__posix(pMutex);
#endif
}
MA_API void ma_mutex_unlock(ma_mutex* pMutex)
{
if (pMutex == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
return;
}
#ifdef MA_WIN32
ma_mutex_unlock__win32(pMutex);
#endif
#ifdef MA_POSIX
ma_mutex_unlock__posix(pMutex);
#endif
}
MA_API ma_result ma_event_init(ma_event* pEvent)
{
if (pEvent == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
return MA_INVALID_ARGS;
}
#ifdef MA_WIN32
return ma_event_init__win32(pEvent);
#endif
#ifdef MA_POSIX
return ma_event_init__posix(pEvent);
#endif
}
#if 0
static ma_result ma_event_alloc_and_init(ma_event** ppEvent, ma_allocation_callbacks* pAllocationCallbacks)
{
ma_result result;
ma_event* pEvent;
if (ppEvent == NULL) {
return MA_INVALID_ARGS;
}
*ppEvent = NULL;
pEvent = ma_malloc(sizeof(*pEvent), pAllocationCallbacks);
if (pEvent == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_event_init(pEvent);
if (result != MA_SUCCESS) {
ma_free(pEvent, pAllocationCallbacks);
return result;
}
*ppEvent = pEvent;
return result;
}
#endif
MA_API void ma_event_uninit(ma_event* pEvent)
{
if (pEvent == NULL) {
return;
}
#ifdef MA_WIN32
ma_event_uninit__win32(pEvent);
#endif
#ifdef MA_POSIX
ma_event_uninit__posix(pEvent);
#endif
}
#if 0
static void ma_event_uninit_and_free(ma_event* pEvent, ma_allocation_callbacks* pAllocationCallbacks)
{
if (pEvent == NULL) {
return;
}
ma_event_uninit(pEvent);
ma_free(pEvent, pAllocationCallbacks);
}
#endif
MA_API ma_result ma_event_wait(ma_event* pEvent)
{
if (pEvent == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert to the caller is aware of this bug. */
return MA_INVALID_ARGS;
}
#ifdef MA_WIN32
return ma_event_wait__win32(pEvent);
#endif
#ifdef MA_POSIX
return ma_event_wait__posix(pEvent);
#endif
}
MA_API ma_result ma_event_signal(ma_event* pEvent)
{
if (pEvent == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert to the caller is aware of this bug. */
return MA_INVALID_ARGS;
}
#ifdef MA_WIN32
return ma_event_signal__win32(pEvent);
#endif
#ifdef MA_POSIX
return ma_event_signal__posix(pEvent);
#endif
}
MA_API ma_result ma_semaphore_init(int initialValue, ma_semaphore* pSemaphore)
{
if (pSemaphore == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
return MA_INVALID_ARGS;
}
#ifdef MA_WIN32
return ma_semaphore_init__win32(initialValue, pSemaphore);
#endif
#ifdef MA_POSIX
return ma_semaphore_init__posix(initialValue, pSemaphore);
#endif
}
MA_API void ma_semaphore_uninit(ma_semaphore* pSemaphore)
{
if (pSemaphore == NULL) {
MA_ASSERT(MA_FALSE); /* Fire an assert so the caller is aware of this bug. */
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (c89atomic_compare_exchange_weak_32(&pFence->counter, &oldCounter, newCounter)) {
#ifndef MA_NO_THREADING
{
if (newCounter == 0) {
ma_event_signal(&pFence->e); /* <-- ma_fence_wait() will be waiting on this. */
}
}
#endif
return MA_SUCCESS;
} else {
if (oldCounter == 0) {
MA_ASSERT(MA_FALSE);
return MA_INVALID_OPERATION; /* Another thread has taken the 0 slot. Acquire/release mismatch. */
}
}
}
/* Should never get here. */
/*return MA_SUCCESS;*/
}
MA_API ma_result ma_fence_wait(ma_fence* pFence)
{
if (pFence == NULL) {
return MA_INVALID_ARGS;
}
for (;;) {
ma_uint32 counter;
counter = c89atomic_load_32(&pFence->counter);
if (counter == 0) {
/*
Counter has hit zero. By the time we get here some other thread may have acquired the
fence again, but that is where the caller needs to take care with how they se the fence.
*/
return MA_SUCCESS;
}
/* Getting here means the counter is > 0. We'll need to wait for something to happen. */
#ifndef MA_NO_THREADING
{
ma_result result;
result = ma_event_wait(&pFence->e);
if (result != MA_SUCCESS) {
return result;
}
}
#endif
}
/* Should never get here. */
/*return MA_INVALID_OPERATION;*/
}
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification)
{
ma_async_notification_callbacks* pNotificationCallbacks = (ma_async_notification_callbacks*)pNotification;
if (pNotification == NULL) {
return MA_INVALID_ARGS;
}
if (pNotificationCallbacks->onSignal == NULL) {
return MA_NOT_IMPLEMENTED;
}
pNotificationCallbacks->onSignal(pNotification);
return MA_INVALID_ARGS;
}
static void ma_async_notification_poll__on_signal(ma_async_notification* pNotification)
{
((ma_async_notification_poll*)pNotification)->signalled = MA_TRUE;
}
MA_API ma_result ma_async_notification_poll_init(ma_async_notification_poll* pNotificationPoll)
{
if (pNotificationPoll == NULL) {
return MA_INVALID_ARGS;
}
pNotificationPoll->cb.onSignal = ma_async_notification_poll__on_signal;
pNotificationPoll->signalled = MA_FALSE;
return MA_SUCCESS;
}
MA_API ma_bool32 ma_async_notification_poll_is_signalled(const ma_async_notification_poll* pNotificationPoll)
{
if (pNotificationPoll == NULL) {
return MA_FALSE;
}
return pNotificationPoll->signalled;
}
static void ma_async_notification_event__on_signal(ma_async_notification* pNotification)
{
ma_async_notification_event_signal((ma_async_notification_event*)pNotification);
}
MA_API ma_result ma_async_notification_event_init(ma_async_notification_event* pNotificationEvent)
{
if (pNotificationEvent == NULL) {
return MA_INVALID_ARGS;
}
pNotificationEvent->cb.onSignal = ma_async_notification_event__on_signal;
#ifndef MA_NO_THREADING
{
ma_result result;
result = ma_event_init(&pNotificationEvent->e);
if (result != MA_SUCCESS) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pHeapLayout->sizeInBytes += ma_align_64(ma_slot_allocator_calculate_group_capacity(pConfig->capacity) * sizeof(ma_slot_allocator_group));
/* Slots. */
pHeapLayout->slotsOffset = pHeapLayout->sizeInBytes;
pHeapLayout->sizeInBytes += ma_align_64(pConfig->capacity * sizeof(ma_uint32));
return MA_SUCCESS;
}
MA_API ma_result ma_slot_allocator_get_heap_size(const ma_slot_allocator_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_slot_allocator_heap_layout layout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_slot_allocator_get_heap_layout(pConfig, &layout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = layout.sizeInBytes;
return result;
}
MA_API ma_result ma_slot_allocator_init_preallocated(const ma_slot_allocator_config* pConfig, void* pHeap, ma_slot_allocator* pAllocator)
{
ma_result result;
ma_slot_allocator_heap_layout heapLayout;
if (pAllocator == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pAllocator);
if (pHeap == NULL) {
return MA_INVALID_ARGS;
}
result = ma_slot_allocator_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pAllocator->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pAllocator->pGroups = (ma_slot_allocator_group*)ma_offset_ptr(pHeap, heapLayout.groupsOffset);
pAllocator->pSlots = (ma_uint32*)ma_offset_ptr(pHeap, heapLayout.slotsOffset);
pAllocator->capacity = pConfig->capacity;
return MA_SUCCESS;
}
MA_API ma_result ma_slot_allocator_init(const ma_slot_allocator_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_slot_allocator* pAllocator)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_slot_allocator_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result; /* Failed to retrieve the size of the heap allocation. */
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_slot_allocator_init_preallocated(pConfig, pHeap, pAllocator);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pAllocator->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_slot_allocator_uninit(ma_slot_allocator* pAllocator, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocator == NULL) {
return;
}
if (pAllocator->_ownsHeap) {
ma_free(pAllocator->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_slot_allocator_alloc(ma_slot_allocator* pAllocator, ma_uint64* pSlot)
{
ma_uint32 iAttempt;
const ma_uint32 maxAttempts = 2; /* The number of iterations to perform until returning MA_OUT_OF_MEMORY if no slots can be found. */
if (pAllocator == NULL || pSlot == NULL) {
return MA_INVALID_ARGS;
}
for (iAttempt = 0; iAttempt < maxAttempts; iAttempt += 1) {
/* We need to acquire a suitable bitfield first. This is a bitfield that's got an available slot within it. */
ma_uint32 iGroup;
for (iGroup = 0; iGroup < ma_slot_allocator_group_capacity(pAllocator); iGroup += 1) {
/* CAS */
for (;;) {
ma_uint32 oldBitfield;
ma_uint32 newBitfield;
ma_uint32 bitOffset;
oldBitfield = c89atomic_load_32(&pAllocator->pGroups[iGroup].bitfield); /* <-- This copy must happen. The compiler must not optimize this away. */
/* Fast check to see if anything is available. */
if (oldBitfield == 0xFFFFFFFF) {
break; /* No available bits in this bitfield. */
}
bitOffset = ma_ffs_32(~oldBitfield);
MA_ASSERT(bitOffset < 32);
newBitfield = oldBitfield | (1 << bitOffset);
if (c89atomic_compare_and_swap_32(&pAllocator->pGroups[iGroup].bitfield, oldBitfield, newBitfield) == oldBitfield) {
ma_uint32 slotIndex;
/* Increment the counter as soon as possible to have other threads report out-of-memory sooner than later. */
c89atomic_fetch_add_32(&pAllocator->count, 1);
/* The slot index is required for constructing the output value. */
slotIndex = (iGroup << 5) + bitOffset; /* iGroup << 5 = iGroup * 32 */
if (slotIndex >= pAllocator->capacity) {
return MA_OUT_OF_MEMORY;
}
/* Increment the reference count before constructing the output value. */
pAllocator->pSlots[slotIndex] += 1;
/* Construct the output value. */
*pSlot = (((ma_uint64)pAllocator->pSlots[slotIndex] << 32) | slotIndex);
return MA_SUCCESS;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
*pHeapSizeInBytes = layout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_job_queue_init_preallocated(const ma_job_queue_config* pConfig, void* pHeap, ma_job_queue* pQueue)
{
ma_result result;
ma_job_queue_heap_layout heapLayout;
ma_slot_allocator_config allocatorConfig;
if (pQueue == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pQueue);
result = ma_job_queue_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pQueue->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pQueue->flags = pConfig->flags;
pQueue->capacity = pConfig->capacity;
pQueue->pJobs = (ma_job*)ma_offset_ptr(pHeap, heapLayout.jobsOffset);
allocatorConfig = ma_slot_allocator_config_init(pConfig->capacity);
result = ma_slot_allocator_init_preallocated(&allocatorConfig, ma_offset_ptr(pHeap, heapLayout.allocatorOffset), &pQueue->allocator);
if (result != MA_SUCCESS) {
return result;
}
/* We need a semaphore if we're running in non-blocking mode. If threading is disabled we need to return an error. */
if ((pQueue->flags & MA_JOB_QUEUE_FLAG_NON_BLOCKING) == 0) {
#ifndef MA_NO_THREADING
{
ma_semaphore_init(0, &pQueue->sem);
}
#else
{
/* Threading is disabled and we've requested non-blocking mode. */
return MA_INVALID_OPERATION;
}
#endif
}
/*
Our queue needs to be initialized with a free standing node. This should always be slot 0. Required for the lock free algorithm. The first job in the queue is
just a dummy item for giving us the first item in the list which is stored in the "next" member.
*/
ma_slot_allocator_alloc(&pQueue->allocator, &pQueue->head); /* Will never fail. */
pQueue->pJobs[ma_job_extract_slot(pQueue->head)].next = MA_JOB_ID_NONE;
pQueue->tail = pQueue->head;
return MA_SUCCESS;
}
MA_API ma_result ma_job_queue_init(const ma_job_queue_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_job_queue* pQueue)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_job_queue_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_job_queue_init_preallocated(pConfig, pHeap, pQueue);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pQueue->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_job_queue_uninit(ma_job_queue* pQueue, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pQueue == NULL) {
return;
}
/* All we need to do is uninitialize the semaphore. */
if ((pQueue->flags & MA_JOB_QUEUE_FLAG_NON_BLOCKING) == 0) {
#ifndef MA_NO_THREADING
{
ma_semaphore_uninit(&pQueue->sem);
}
#else
{
MA_ASSERT(MA_FALSE); /* Should never get here. Should have been checked at initialization time. */
}
#endif
}
ma_slot_allocator_uninit(&pQueue->allocator, pAllocationCallbacks);
if (pQueue->_ownsHeap) {
ma_free(pQueue->_pHeap, pAllocationCallbacks);
}
}
static ma_bool32 ma_job_queue_cas(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 desired)
{
/* The new counter is taken from the expected value. */
return c89atomic_compare_and_swap_64(dst, expected, ma_job_set_refcount(desired, ma_job_extract_refcount(expected) + 1)) == expected;
}
MA_API ma_result ma_job_queue_post(ma_job_queue* pQueue, const ma_job* pJob)
{
/*
Lock free queue implementation based on the paper by Michael and Scott: Nonblocking Algorithms and Preemption-Safe Locking on Multiprogrammed Shared Memory Multiprocessors
*/
ma_result result;
ma_uint64 slot;
ma_uint64 tail;
ma_uint64 next;
if (pQueue == NULL || pJob == NULL) {
return MA_INVALID_ARGS;
}
/* We need a new slot. */
result = ma_slot_allocator_alloc(&pQueue->allocator, &slot);
if (result != MA_SUCCESS) {
return result; /* Probably ran out of slots. If so, MA_OUT_OF_MEMORY will be returned. */
}
/* At this point we should have a slot to place the job. */
MA_ASSERT(ma_job_extract_slot(slot) < pQueue->capacity);
/* We need to put the job into memory before we do anything. */
pQueue->pJobs[ma_job_extract_slot(slot)] = *pJob;
pQueue->pJobs[ma_job_extract_slot(slot)].toc.allocation = slot; /* This will overwrite the job code. */
pQueue->pJobs[ma_job_extract_slot(slot)].toc.breakup.code = pJob->toc.breakup.code; /* The job code needs to be applied again because the line above overwrote it. */
pQueue->pJobs[ma_job_extract_slot(slot)].next = MA_JOB_ID_NONE; /* Reset for safety. */
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}
#ifdef MA_WIN32
GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
/*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
/*GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
#endif
MA_API ma_uint32 ma_get_format_priority_index(ma_format format) /* Lower = better. */
{
ma_uint32 i;
for (i = 0; i < ma_countof(g_maFormatPriorities); ++i) {
if (g_maFormatPriorities[i] == format) {
return i;
}
}
/* Getting here means the format could not be found or is equal to ma_format_unknown. */
return (ma_uint32)-1;
}
static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type deviceType);
static ma_bool32 ma_device_descriptor_is_valid(const ma_device_descriptor* pDeviceDescriptor)
{
if (pDeviceDescriptor == NULL) {
return MA_FALSE;
}
if (pDeviceDescriptor->format == ma_format_unknown) {
return MA_FALSE;
}
if (pDeviceDescriptor->channels == 0 || pDeviceDescriptor->channels > MA_MAX_CHANNELS) {
return MA_FALSE;
}
if (pDeviceDescriptor->sampleRate == 0) {
return MA_FALSE;
}
return MA_TRUE;
}
static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice)
{
ma_result result = MA_SUCCESS;
ma_bool32 exitLoop = MA_FALSE;
ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint32 capturedDeviceDataCapInFrames = 0;
ma_uint32 playbackDeviceDataCapInFrames = 0;
MA_ASSERT(pDevice != NULL);
/* Just some quick validation on the device type and the available callbacks. */
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
if (pDevice->pContext->callbacks.onDeviceRead == NULL) {
return MA_NOT_IMPLEMENTED;
}
capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
if (pDevice->pContext->callbacks.onDeviceWrite == NULL) {
return MA_NOT_IMPLEMENTED;
}
playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
}
/* NOTE: The device was started outside of this function, in the worker thread. */
while (ma_device_get_state(pDevice) == ma_device_state_started && !exitLoop) {
switch (pDevice->type) {
case ma_device_type_duplex:
{
/* The process is: onDeviceRead() -> convert -> callback -> convert -> onDeviceWrite() */
ma_uint32 totalCapturedDeviceFramesProcessed = 0;
ma_uint32 capturedDevicePeriodSizeInFrames = ma_min(pDevice->capture.internalPeriodSizeInFrames, pDevice->playback.internalPeriodSizeInFrames);
while (totalCapturedDeviceFramesProcessed < capturedDevicePeriodSizeInFrames) {
ma_uint32 capturedDeviceFramesRemaining;
ma_uint32 capturedDeviceFramesProcessed;
ma_uint32 capturedDeviceFramesToProcess;
ma_uint32 capturedDeviceFramesToTryProcessing = capturedDevicePeriodSizeInFrames - totalCapturedDeviceFramesProcessed;
if (capturedDeviceFramesToTryProcessing > capturedDeviceDataCapInFrames) {
capturedDeviceFramesToTryProcessing = capturedDeviceDataCapInFrames;
}
result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, capturedDeviceFramesToTryProcessing, &capturedDeviceFramesToProcess);
if (result != MA_SUCCESS) {
exitLoop = MA_TRUE;
break;
}
capturedDeviceFramesRemaining = capturedDeviceFramesToProcess;
capturedDeviceFramesProcessed = 0;
/* At this point we have our captured data in device format and we now need to convert it to client format. */
for (;;) {
ma_uint8 capturedClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint8 playbackClientData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint32 capturedClientDataCapInFrames = sizeof(capturedClientData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
ma_uint32 playbackClientDataCapInFrames = sizeof(playbackClientData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
ma_uint64 capturedClientFramesToProcessThisIteration = ma_min(capturedClientDataCapInFrames, playbackClientDataCapInFrames);
ma_uint64 capturedDeviceFramesToProcessThisIteration = capturedDeviceFramesRemaining;
ma_uint8* pRunningCapturedDeviceFrames = ma_offset_ptr(capturedDeviceData, capturedDeviceFramesProcessed * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
/* Convert capture data from device format to client format. */
result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningCapturedDeviceFrames, &capturedDeviceFramesToProcessThisIteration, capturedClientData, &capturedClientFramesToProcessThisIteration);
if (result != MA_SUCCESS) {
break;
}
/*
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
which should never be the case when it's of the size MA_DATA_CONVERTER_STACK_BUFFER_SIZE.
*/
if (capturedClientFramesToProcessThisIteration == 0) {
break;
}
ma_device__handle_data_callback(pDevice, playbackClientData, capturedClientData, (ma_uint32)capturedClientFramesToProcessThisIteration); /* Safe cast .*/
capturedDeviceFramesProcessed += (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
capturedDeviceFramesRemaining -= (ma_uint32)capturedDeviceFramesToProcessThisIteration; /* Safe cast. */
/* At this point the playbackClientData buffer should be holding data that needs to be written to the device. */
for (;;) {
ma_uint64 convertedClientFrameCount = capturedClientFramesToProcessThisIteration;
ma_uint64 convertedDeviceFrameCount = playbackDeviceDataCapInFrames;
result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, playbackClientData, &convertedClientFrameCount, playbackDeviceData, &convertedDeviceFrameCount);
if (result != MA_SUCCESS) {
break;
}
result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, (ma_uint32)convertedDeviceFrameCount, NULL); /* Safe cast. */
if (result != MA_SUCCESS) {
exitLoop = MA_TRUE;
break;
}
capturedClientFramesToProcessThisIteration -= (ma_uint32)convertedClientFrameCount; /* Safe cast. */
if (capturedClientFramesToProcessThisIteration == 0) {
break;
}
}
/* In case an error happened from ma_device_write__null()... */
if (result != MA_SUCCESS) {
exitLoop = MA_TRUE;
break;
}
}
/* Make sure we don't get stuck in the inner loop. */
if (capturedDeviceFramesProcessed == 0) {
break;
}
totalCapturedDeviceFramesProcessed += capturedDeviceFramesProcessed;
}
} break;
case ma_device_type_capture:
case ma_device_type_loopback:
{
ma_uint32 periodSizeInFrames = pDevice->capture.internalPeriodSizeInFrames;
ma_uint32 framesReadThisPeriod = 0;
while (framesReadThisPeriod < periodSizeInFrames) {
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
ma_uint32 framesProcessed;
ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
if (framesToReadThisIteration > capturedDeviceDataCapInFrames) {
framesToReadThisIteration = capturedDeviceDataCapInFrames;
}
result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
if (result != MA_SUCCESS) {
exitLoop = MA_TRUE;
break;
}
/* Make sure we don't get stuck in the inner loop. */
if (framesProcessed == 0) {
break;
}
ma_device__send_frames_to_client(pDevice, framesProcessed, capturedDeviceData);
framesReadThisPeriod += framesProcessed;
}
} break;
case ma_device_type_playback:
{
/* We write in chunks of the period size, but use a stack allocated buffer for the intermediary. */
ma_uint32 periodSizeInFrames = pDevice->playback.internalPeriodSizeInFrames;
ma_uint32 framesWrittenThisPeriod = 0;
while (framesWrittenThisPeriod < periodSizeInFrames) {
ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
ma_uint32 framesProcessed;
ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
if (framesToWriteThisIteration > playbackDeviceDataCapInFrames) {
framesToWriteThisIteration = playbackDeviceDataCapInFrames;
}
ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData);
result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed);
if (result != MA_SUCCESS) {
exitLoop = MA_TRUE;
break;
}
/* Make sure we don't get stuck in the inner loop. */
if (framesProcessed == 0) {
break;
}
framesWrittenThisPeriod += framesProcessed;
}
} break;
/* Should never get here. */
default: break;
}
}
return result;
}
/*******************************************************************************
Null Backend
*******************************************************************************/
#ifdef MA_HAS_NULL
#define MA_DEVICE_OP_NONE__NULL 0
#define MA_DEVICE_OP_START__NULL 1
#define MA_DEVICE_OP_SUSPEND__NULL 2
#define MA_DEVICE_OP_KILL__NULL 3
static ma_thread_result MA_THREADCALL ma_device_thread__null(void* pData)
{
ma_device* pDevice = (ma_device*)pData;
MA_ASSERT(pDevice != NULL);
for (;;) { /* Keep the thread alive until the device is uninitialized. */
ma_uint32 operation;
/* Wait for an operation to be requested. */
ma_event_wait(&pDevice->null_device.operationEvent);
/* At this point an event should have been triggered. */
operation = pDevice->null_device.operation;
/* Starting the device needs to put the thread into a loop. */
if (operation == MA_DEVICE_OP_START__NULL) {
/* Reset the timer just in case. */
ma_timer_init(&pDevice->null_device.timer);
/* Getting here means a suspend or kill operation has been requested. */
pDevice->null_device.operationResult = MA_SUCCESS;
ma_event_signal(&pDevice->null_device.operationCompletionEvent);
ma_semaphore_release(&pDevice->null_device.operationSemaphore);
continue;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
framesToProcess = framesRemaining;
}
/* We need to ensure the output buffer is zeroed. */
MA_ZERO_MEMORY(ma_offset_ptr(pPCMFrames, totalPCMFramesProcessed*bpf), framesToProcess*bpf);
pDevice->null_device.currentPeriodFramesRemainingCapture -= framesToProcess;
totalPCMFramesProcessed += framesToProcess;
}
/* 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. */
if (pDevice->null_device.currentPeriodFramesRemainingCapture == 0) {
pDevice->null_device.currentPeriodFramesRemainingCapture = 0;
}
/* If we've consumed the whole buffer we can return now. */
MA_ASSERT(totalPCMFramesProcessed <= frameCount);
if (totalPCMFramesProcessed == frameCount) {
break;
}
/* Getting here means we've still got more frames to consume, we but need to wait for it to become available. */
targetFrame = pDevice->null_device.lastProcessedFrameCapture + pDevice->capture.internalPeriodSizeInFrames;
for (;;) {
ma_uint64 currentFrame;
/* Stop waiting if the device has been stopped. */
if (!c89atomic_load_32(&pDevice->null_device.isStarted)) {
break;
}
currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
if (currentFrame >= targetFrame) {
break;
}
/* Getting here means we haven't yet reached the target sample, so continue waiting. */
ma_sleep(10);
}
pDevice->null_device.lastProcessedFrameCapture += pDevice->capture.internalPeriodSizeInFrames;
pDevice->null_device.currentPeriodFramesRemainingCapture = pDevice->capture.internalPeriodSizeInFrames;
}
if (pFramesRead != NULL) {
*pFramesRead = totalPCMFramesProcessed;
}
return result;
}
static ma_result ma_context_uninit__null(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_null);
(void)pContext;
return MA_SUCCESS;
}
static ma_result ma_context_init__null(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
MA_ASSERT(pContext != NULL);
(void)pConfig;
(void)pContext;
pCallbacks->onContextInit = ma_context_init__null;
pCallbacks->onContextUninit = ma_context_uninit__null;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__null;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__null;
pCallbacks->onDeviceInit = ma_device_init__null;
pCallbacks->onDeviceUninit = ma_device_uninit__null;
pCallbacks->onDeviceStart = ma_device_start__null;
pCallbacks->onDeviceStop = ma_device_stop__null;
pCallbacks->onDeviceRead = ma_device_read__null;
pCallbacks->onDeviceWrite = ma_device_write__null;
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. */
/* The null backend always works. */
return MA_SUCCESS;
}
#endif
/*******************************************************************************
WIN32 COMMON
*******************************************************************************/
#if defined(MA_WIN32)
#if defined(MA_WIN32_DESKTOP)
#define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit)
#define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
#define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) ((MA_PFN_CoCreateInstance)pContext->win32.CoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv)
#define ma_CoTaskMemFree(pContext, pv) ((MA_PFN_CoTaskMemFree)pContext->win32.CoTaskMemFree)(pv)
#define ma_PropVariantClear(pContext, pvar) ((MA_PFN_PropVariantClear)pContext->win32.PropVariantClear)(pvar)
#else
#define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) CoInitializeEx(pvReserved, dwCoInit)
#define ma_CoUninitialize(pContext) CoUninitialize()
#define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv)
#define ma_CoTaskMemFree(pContext, pv) CoTaskMemFree(pv)
#define ma_PropVariantClear(pContext, pvar) PropVariantClear(pvar)
#endif
#if !defined(MAXULONG_PTR) && !defined(__WATCOMC__)
typedef size_t DWORD_PTR;
#endif
#if !defined(WAVE_FORMAT_44M08)
#define WAVE_FORMAT_44M08 0x00000100
#define WAVE_FORMAT_44S08 0x00000200
#define WAVE_FORMAT_44M16 0x00000400
#define WAVE_FORMAT_44S16 0x00000800
#define WAVE_FORMAT_48M08 0x00001000
#define WAVE_FORMAT_48S08 0x00002000
#define WAVE_FORMAT_48M16 0x00004000
#define WAVE_FORMAT_48S16 0x00008000
#define WAVE_FORMAT_96M08 0x00010000
#define WAVE_FORMAT_96S08 0x00020000
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pDevice->wasapi.mappedBufferPlaybackCap = bufferSizeInFrames;
pDevice->wasapi.mappedBufferPlaybackLen = 0;
} else {
if (hr == MA_AUDCLNT_E_BUFFER_TOO_LARGE || hr == MA_AUDCLNT_E_BUFFER_ERROR) {
/* Not enough data available. We need to wait for more. */
if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) {
result = MA_ERROR;
break; /* Wait failed. Probably timed out. */
}
} else {
/* Some error occurred. We'll need to abort. */
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to retrieve internal buffer from playback device in preparation for writing to the device. HRESULT = %d. Stopping device.\n", (int)hr);
result = ma_result_from_HRESULT(hr);
break;
}
}
}
}
if (pFramesWritten != NULL) {
*pFramesWritten = totalFramesProcessed;
}
return result;
}
static ma_result ma_device_data_loop_wakeup__wasapi(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
SetEvent((HANDLE)pDevice->wasapi.hEventCapture);
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
SetEvent((HANDLE)pDevice->wasapi.hEventPlayback);
}
return MA_SUCCESS;
}
static ma_result ma_context_uninit__wasapi(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_wasapi);
if (pContext->wasapi.commandThread != NULL) {
ma_context_command__wasapi cmd = ma_context_init_command__wasapi(MA_CONTEXT_COMMAND_QUIT__WASAPI);
ma_context_post_command__wasapi(pContext, &cmd);
ma_thread_wait(&pContext->wasapi.commandThread);
/* Only after the thread has been terminated can we uninitialize the sync objects for the command thread. */
ma_semaphore_uninit(&pContext->wasapi.commandSem);
ma_mutex_uninit(&pContext->wasapi.commandLock);
}
return MA_SUCCESS;
}
static ma_result ma_context_init__wasapi(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
ma_result result = MA_SUCCESS;
MA_ASSERT(pContext != NULL);
(void)pConfig;
#ifdef MA_WIN32_DESKTOP
/*
WASAPI is only supported in Vista SP1 and newer. The reason for SP1 and not the base version of Vista is that event-driven
exclusive mode does not work until SP1.
Unfortunately older compilers don't define these functions so we need to dynamically load them in order to avoid a link error.
*/
{
ma_OSVERSIONINFOEXW osvi;
ma_handle kernel32DLL;
ma_PFNVerifyVersionInfoW _VerifyVersionInfoW;
ma_PFNVerSetConditionMask _VerSetConditionMask;
kernel32DLL = ma_dlopen(pContext, "kernel32.dll");
if (kernel32DLL == NULL) {
return MA_NO_BACKEND;
}
_VerifyVersionInfoW = (ma_PFNVerifyVersionInfoW )ma_dlsym(pContext, kernel32DLL, "VerifyVersionInfoW");
_VerSetConditionMask = (ma_PFNVerSetConditionMask)ma_dlsym(pContext, kernel32DLL, "VerSetConditionMask");
if (_VerifyVersionInfoW == NULL || _VerSetConditionMask == NULL) {
ma_dlclose(pContext, kernel32DLL);
return MA_NO_BACKEND;
}
MA_ZERO_OBJECT(&osvi);
osvi.dwOSVersionInfoSize = sizeof(osvi);
osvi.dwMajorVersion = ((MA_WIN32_WINNT_VISTA >> 8) & 0xFF);
osvi.dwMinorVersion = ((MA_WIN32_WINNT_VISTA >> 0) & 0xFF);
osvi.wServicePackMajor = 1;
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_GREA...
result = MA_SUCCESS;
} else {
result = MA_NO_BACKEND;
}
ma_dlclose(pContext, kernel32DLL);
}
#endif
if (result != MA_SUCCESS) {
return result;
}
MA_ZERO_OBJECT(&pContext->wasapi);
/*
Annoyingly, WASAPI does not allow you to release an IAudioClient object from a different thread
than the one that retrieved it with GetService(). This can result in a deadlock in two
situations:
1) When calling ma_device_uninit() from a different thread to ma_device_init(); and
2) When uninitializing and reinitializing the internal IAudioClient object in response to
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
DWORD availableBytesPlayback = 0;
DWORD physicalPlayCursorInBytes;
DWORD physicalWriteCursorInBytes;
hr = ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes);
if (FAILED(hr)) {
break;
}
if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
}
prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
/* Same loop iteration. The available bytes wraps all the way around from the virtual write cursor to the physical play cursor. */
if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
availableBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
availableBytesPlayback += physicalPlayCursorInBytes; /* Wrap around. */
} else {
break;
}
} else {
/* Different loop iterations. The available bytes only goes from the virtual write cursor to the physical play cursor. */
if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
} else {
break;
}
}
if (availableBytesPlayback >= (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback)) {
break;
}
ma_sleep(waitTimeInMilliseconds);
}
}
hr = ma_IDirectSoundBuffer_Stop((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer);
if (FAILED(hr)) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Stop() failed.");
return ma_result_from_HRESULT(hr);
}
ma_IDirectSoundBuffer_SetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0);
}
return MA_SUCCESS;
}
static ma_result ma_context_uninit__dsound(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_dsound);
ma_dlclose(pContext, pContext->dsound.hDSoundDLL);
return MA_SUCCESS;
}
static ma_result ma_context_init__dsound(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
MA_ASSERT(pContext != NULL);
(void)pConfig;
pContext->dsound.hDSoundDLL = ma_dlopen(pContext, "dsound.dll");
if (pContext->dsound.hDSoundDLL == NULL) {
return MA_API_NOT_FOUND;
}
pContext->dsound.DirectSoundCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCreate");
pContext->dsound.DirectSoundEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundEnumerateA");
pContext->dsound.DirectSoundCaptureCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCaptureCreate");
pContext->dsound.DirectSoundCaptureEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL, "DirectSoundCaptureEnumerateA");
pCallbacks->onContextInit = ma_context_init__dsound;
pCallbacks->onContextUninit = ma_context_uninit__dsound;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__dsound;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__dsound;
pCallbacks->onDeviceInit = ma_device_init__dsound;
pCallbacks->onDeviceUninit = ma_device_uninit__dsound;
pCallbacks->onDeviceStart = NULL; /* Not used. Started in onDeviceDataLoop. */
pCallbacks->onDeviceStop = NULL; /* Not used. Stopped in onDeviceDataLoop. */
pCallbacks->onDeviceRead = NULL; /* Not used. Data is read directly in onDeviceDataLoop. */
pCallbacks->onDeviceWrite = NULL; /* Not used. Data is written directly in onDeviceDataLoop. */
pCallbacks->onDeviceDataLoop = ma_device_data_loop__dsound;
return MA_SUCCESS;
}
#endif
/******************************************************************************
WinMM Backend
******************************************************************************/
#ifdef MA_HAS_WINMM
/*
Some older compilers don't have WAVEOUTCAPS2A and WAVEINCAPS2A, so we'll need to write this ourselves. These structures
are exactly the same as the older ones but they have a few GUIDs for manufacturer/product/name identification. I'm keeping
the names the same as the Win32 library for consistency, but namespaced to avoid naming conflicts with the Win32 version.
*/
typedef struct
{
WORD wMid;
WORD wPid;
MMVERSION vDriverVersion;
CHAR szPname[MAXPNAMELEN];
DWORD dwFormats;
WORD wChannels;
WORD wReserved1;
DWORD dwSupport;
GUID ManufacturerGuid;
GUID ProductGuid;
GUID NameGuid;
} MA_WAVEOUTCAPS2A;
typedef struct
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
/* Make sure the event is reset to a non-signaled state to ensure we don't prematurely return from WaitForSingleObject(). */
ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
/* The device will be started here. */
resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[pDevice->winmm.iNextHeaderCapture], sizeof(WAVEHDR));
if (resultMM != MMSYSERR_NOERROR) {
result = ma_result_from_MMRESULT(resultMM);
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WinMM] waveInAddBuffer() failed.");
break;
}
/* Make sure we move to the next header. */
pDevice->winmm.iNextHeaderCapture = (pDevice->winmm.iNextHeaderCapture + 1) % pDevice->capture.internalPeriods;
pDevice->winmm.headerFramesConsumedCapture = 0;
}
/* If at this point we have filled the entire input buffer we can return. */
MA_ASSERT(totalFramesRead <= frameCount);
if (totalFramesRead == frameCount) {
break;
}
/* Getting here means there's more to process. */
continue;
}
/* Getting here means there isn't enough any data left to send to the client which means we need to wait for more. */
if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
result = MA_ERROR;
break;
}
/* Something happened. If the next buffer has been marked as done we need to reset a bit of state. */
if ((pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags & WHDR_DONE) != 0) {
pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 0; /* 0 = unlocked (make it available for reading). */
pDevice->winmm.headerFramesConsumedCapture = 0;
}
/* If the device has been stopped we need to break. */
if (ma_device_get_state(pDevice) != ma_device_state_started) {
break;
}
}
if (pFramesRead != NULL) {
*pFramesRead = totalFramesRead;
}
return result;
}
static ma_result ma_context_uninit__winmm(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_winmm);
ma_dlclose(pContext, pContext->winmm.hWinMM);
return MA_SUCCESS;
}
static ma_result ma_context_init__winmm(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
MA_ASSERT(pContext != NULL);
(void)pConfig;
pContext->winmm.hWinMM = ma_dlopen(pContext, "winmm.dll");
if (pContext->winmm.hWinMM == NULL) {
return MA_NO_BACKEND;
}
pContext->winmm.waveOutGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutGetNumDevs");
pContext->winmm.waveOutGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutGetDevCapsA");
pContext->winmm.waveOutOpen = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutOpen");
pContext->winmm.waveOutClose = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutClose");
pContext->winmm.waveOutPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutPrepareHeader");
pContext->winmm.waveOutUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutUnprepareHeader");
pContext->winmm.waveOutWrite = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutWrite");
pContext->winmm.waveOutReset = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveOutReset");
pContext->winmm.waveInGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInGetNumDevs");
pContext->winmm.waveInGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInGetDevCapsA");
pContext->winmm.waveInOpen = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInOpen");
pContext->winmm.waveInClose = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInClose");
pContext->winmm.waveInPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInPrepareHeader");
pContext->winmm.waveInUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInUnprepareHeader");
pContext->winmm.waveInAddBuffer = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInAddBuffer");
pContext->winmm.waveInStart = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInStart");
pContext->winmm.waveInReset = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInReset");
pCallbacks->onContextInit = ma_context_init__winmm;
pCallbacks->onContextUninit = ma_context_uninit__winmm;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__winmm;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__winmm;
pCallbacks->onDeviceInit = ma_device_init__winmm;
pCallbacks->onDeviceUninit = ma_device_uninit__winmm;
pCallbacks->onDeviceStart = ma_device_start__winmm;
pCallbacks->onDeviceStop = ma_device_stop__winmm;
pCallbacks->onDeviceRead = ma_device_read__winmm;
pCallbacks->onDeviceWrite = ma_device_write__winmm;
pCallbacks->onDeviceDataLoop = NULL; /* This is a blocking read-write API, so this can be NULL since miniaudio will manage the audio thread for us. */
return MA_SUCCESS;
}
#endif
/******************************************************************************
ALSA Backend
******************************************************************************/
#ifdef MA_HAS_ALSA
#include <poll.h> /* poll(), struct pollfd */
#include <sys/eventfd.h> /* eventfd() */
#ifdef MA_NO_RUNTIME_LINKING
/* asoundlib.h marks some functions with "inline" which isn't always supported. Need to emulate it. */
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] Failed to start device after underrun.");
return ma_result_from_errno((int)-resultALSA);
}
continue; /* Try writing again. */
}
}
}
if (pFramesWritten != NULL) {
*pFramesWritten = resultALSA;
}
return MA_SUCCESS;
}
static ma_result ma_device_data_loop_wakeup__alsa(ma_device* pDevice)
{
ma_uint64 t = 1;
int resultWrite = 0;
MA_ASSERT(pDevice != NULL);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Waking up...\n");
/* Write to an eventfd to trigger a wakeup from poll() and abort any reading or writing. */
if (pDevice->alsa.pPollDescriptorsCapture != NULL) {
resultWrite = write(pDevice->alsa.wakeupfdCapture, &t, sizeof(t));
}
if (pDevice->alsa.pPollDescriptorsPlayback != NULL) {
resultWrite = write(pDevice->alsa.wakeupfdPlayback, &t, sizeof(t));
}
if (resultWrite < 0) {
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[ALSA] write() failed.\n");
return ma_result_from_errno(errno);
}
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[ALSA] Waking up completed successfully.\n");
return MA_SUCCESS;
}
static ma_result ma_context_uninit__alsa(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_alsa);
/* Clean up memory for memory leak checkers. */
((ma_snd_config_update_free_global_proc)pContext->alsa.snd_config_update_free_global)();
#ifndef MA_NO_RUNTIME_LINKING
ma_dlclose(pContext, pContext->alsa.asoundSO);
#endif
ma_mutex_uninit(&pContext->alsa.internalDeviceEnumLock);
return MA_SUCCESS;
}
static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
ma_result result;
#ifndef MA_NO_RUNTIME_LINKING
const char* libasoundNames[] = {
"libasound.so.2",
"libasound.so"
};
size_t i;
for (i = 0; i < ma_countof(libasoundNames); ++i) {
pContext->alsa.asoundSO = ma_dlopen(pContext, libasoundNames[i]);
if (pContext->alsa.asoundSO != NULL) {
break;
}
}
if (pContext->alsa.asoundSO == NULL) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "[ALSA] Failed to open shared object.\n");
return MA_NO_BACKEND;
}
pContext->alsa.snd_pcm_open = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_open");
pContext->alsa.snd_pcm_close = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_close");
pContext->alsa.snd_pcm_hw_params_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_sizeof");
pContext->alsa.snd_pcm_hw_params_any = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_any");
pContext->alsa.snd_pcm_hw_params_set_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_format");
pContext->alsa.snd_pcm_hw_params_set_format_first = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_format_first");
pContext->alsa.snd_pcm_hw_params_get_format_mask = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_format_mask");
pContext->alsa.snd_pcm_hw_params_set_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels");
pContext->alsa.snd_pcm_hw_params_set_channels_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels_near");
pContext->alsa.snd_pcm_hw_params_set_channels_minmax = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_channels_minmax");
pContext->alsa.snd_pcm_hw_params_set_rate_resample = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate_resample");
pContext->alsa.snd_pcm_hw_params_set_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate");
pContext->alsa.snd_pcm_hw_params_set_rate_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_rate_near");
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");
pContext->alsa.snd_pcm_hw_params_set_periods_near = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_periods_near");
pContext->alsa.snd_pcm_hw_params_set_access = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_set_access");
pContext->alsa.snd_pcm_hw_params_get_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_format");
pContext->alsa.snd_pcm_hw_params_get_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels");
pContext->alsa.snd_pcm_hw_params_get_channels_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels_min");
pContext->alsa.snd_pcm_hw_params_get_channels_max = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_channels_max");
pContext->alsa.snd_pcm_hw_params_get_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate");
pContext->alsa.snd_pcm_hw_params_get_rate_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate_min");
pContext->alsa.snd_pcm_hw_params_get_rate_max = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_rate_max");
pContext->alsa.snd_pcm_hw_params_get_buffer_size = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_buffer_size");
pContext->alsa.snd_pcm_hw_params_get_periods = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_periods");
pContext->alsa.snd_pcm_hw_params_get_access = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_get_access");
pContext->alsa.snd_pcm_hw_params_test_format = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_format");
pContext->alsa.snd_pcm_hw_params_test_channels = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_channels");
pContext->alsa.snd_pcm_hw_params_test_rate = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params_test_rate");
pContext->alsa.snd_pcm_hw_params = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_hw_params");
pContext->alsa.snd_pcm_sw_params_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_sizeof");
pContext->alsa.snd_pcm_sw_params_current = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_current");
pContext->alsa.snd_pcm_sw_params_get_boundary = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_get_boundary");
pContext->alsa.snd_pcm_sw_params_set_avail_min = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_avail_min");
pContext->alsa.snd_pcm_sw_params_set_start_threshold = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_start_threshold");
pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params_set_stop_threshold");
pContext->alsa.snd_pcm_sw_params = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_sw_params");
pContext->alsa.snd_pcm_format_mask_sizeof = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_format_mask_sizeof");
pContext->alsa.snd_pcm_format_mask_test = (ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO, "snd_pcm_format_mask_test");
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
in the PulseAudio backend. I apologize if this gets a bit ranty for your liking - you might want to skip this discussion.
PulseAudio has something they call the "Simple API", which unfortunately isn't suitable for miniaudio. I've not seen anywhere where it
allows you to enumerate over devices, nor does it seem to support the ability to stop and start streams. Looking at the documentation, it
appears as though the stream is constantly running and you prevent sound from being emitted or captured by simply not calling the read or
write functions. This is not a professional solution as it would be much better to *actually* stop the underlying stream. Perhaps the
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
when you want to have multiple streams to a single context. For these reasons, miniaudio is not using the simple API.
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
get fun, and I don't mean that in a good way...
The problems start with the very name of the API - "asynchronous". Yes, this is an asynchronous oriented API which means your commands
don't immediately take effect. You instead need to issue your commands, and then wait for them to complete. The waiting mechanism is
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
all of PulseAudio's problems stem from.
When you first initialize PulseAudio you need an object referred to as "main loop". You can implement this yourself by defining your own
vtable, but it's much easier to just use one of the built-in main loop implementations. There's two generic implementations called
pa_mainloop and pa_threaded_mainloop, and another implementation specific to GLib called pa_glib_mainloop. We're using pa_threaded_mainloop
because it simplifies management of the worker thread. The idea of the main loop object is pretty self explanatory - you're supposed to use
it to implement a worker thread which runs in a loop. The main loop is where operations are actually executed.
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
to the vtable with `pa_threaded_mainloop_get_api()` (the main loop vtable is called `pa_mainloop_api`). Again, you can bypass the threaded
main loop object entirely and just implement `pa_mainloop_api` directly, but there's no need for it unless you're doing something extremely
specialized such as if you want to integrate it into your application's existing main loop infrastructure.
(EDIT 2021-01-26: miniaudio is no longer using `pa_threaded_mainloop` due to this issue: https://github.com/mackron/miniaudio/issues/262.
It is now using `pa_mainloop` which turns out to be a simpler solution anyway. The rest of this rant still applies, however.)
Once you have your main loop vtable (the `pa_mainloop_api` object) you can create the PulseAudio context. This is very similar to
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
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
is done with `pa_context_new()`, it's not actually connected to anything. When you connect, you call `pa_context_connect()`. However, if
you remember, PulseAudio is an asynchronous API. That means you cannot just assume the context is connected after `pa_context_context()`
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
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.
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.
This waiting loop is therefore unavoidable. In order for the waiting to ever complete, however, the main loop needs to be running. Before
attempting to connect the context, the main loop needs to be started with `pa_threaded_mainloop_start()`.
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
internet connection. However, the *VAST* majority of cases don't involve this at all - they just connect to a local "server" running on the
host machine. The fact that this would be the default rather than making `pa_context_connect()` synchronous tends to boggle the mind.
Once the context has been created and connected you can start creating a stream. A PulseAudio stream is analogous to miniaudio's device.
The initialization of a stream is fairly standard - you configure some attributes (analogous to miniaudio's device config) and then call
`pa_stream_new()` to actually create it. Here is where we start to get into "operations". When configuring the stream, you can get
information about the source (such as sample format, sample rate, etc.), however it's not synchronous. Instead, a `pa_operation` object
is returned from `pa_context_get_source_info_by_name()` (capture) or `pa_context_get_sink_info_by_name()` (playback). Then, you need to
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
context. Then, as an added bonus, you need to decrement the reference counter of the `pa_operation` object to ensure memory is cleaned up.
All of that just to retrieve basic information about a device!
Once the basic information about the device has been retrieved, miniaudio can now create the stream with `ma_stream_new()`. Like the
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
choices in PulseAudio.
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
because PulseAudio takes it literally, specifically the "can be". You would think these callbacks would be appropriate as the place for
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
set a flag that tells PulseAudio to not start the stream automatically. This is required because miniaudio does not auto-start devices
straight after initialization - you need to call `ma_device_start()` manually. The problem is that even when this flag is specified,
PulseAudio will immediately fire it's write or read callback. This is *technically* correct (based on the wording in the documentation)
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
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
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
that point (it may still need to load files or whatnot). Instead, this callback should only be fired when the application requests the
stream be started which is how it works with literally *every* other callback-based audio API. Since miniaudio forbids firing of the data
callback until the device has been started (as it should be with *all* callback based APIs), logic needs to be added to ensure miniaudio
doesn't just blindly fire the application-defined data callback from within the PulseAudio callback before the stream has actually been
started. The device state is used for this - if the state is anything other than `ma_device_state_starting` or `ma_device_state_started`, the main data
callback is not fired.
This, unfortunately, is not the end of the problems with the PulseAudio write callback. Any normal callback based audio API will
continuously fire the callback at regular intervals based on the size of the internal buffer. This will only ever be fired when the device
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
PulseAudio. In PulseAudio, the data callback will *only* be called if you wrote something to it previously. That means, if you don't call
`pa_stream_write()`, the callback will not get fired. On the surface you wouldn't think this would matter because you should be always
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
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
*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
important? Because that's how we've defined stopping to work in miniaudio. In miniaudio, stopping the device requires it to be drained
before returning from ma_device_stop(). So we've stopped the device, which requires us to drain, but draining requires us to *not* write
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!
This becomes a problem when stopping and then restarting the device. When the device is stopped, it's drained, which requires us to *not*
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
resume the stream naively. This means that starting the stream requires us to write data to the stream from outside the callback. This
disconnect is something PulseAudio has got seriously wrong - there should only ever be a single source of data delivery, that being the
callback. (I have tried using `pa_stream_flush()` to trigger the write callback to fire, but this just doesn't work for some reason.)
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,
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
"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
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
guessed it, asynchronous. This means you'll need our waiting loop as usual. Again, why this asynchronous design is the default is
absolutely beyond me. Would it really be that hard to just make it run synchronously?
Teardown is pretty simple (what?!). It's just a matter of calling the relevant `_unref()` function on each object in reverse order that
they were initialized in.
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
embarrassingly unpractical. The main loop thing is an easy fix - have synchronous versions of all APIs. If an application wants these to
run asynchronously, they can execute them in a separate thread themselves. The desire to run these asynchronously is such a niche
requirement - it makes no sense to make it the default. The stream write callback needs to be change, or an alternative provided, that is
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
parameter which the program just writes to directly rather than having to call `pa_stream_writable_size()` and `pa_stream_write()`. These
changes alone will change PulseAudio from one of the worst audio APIs to one of the best.
*/
/*
It is assumed pulseaudio.h is available when linking at compile time. When linking at compile time, we use the declarations in the header
to check for type safety. We cannot do this when linking at run time because the header might not be available.
*/
#ifdef MA_NO_RUNTIME_LINKING
/* pulseaudio.h marks some functions with "inline" which isn't always supported. Need to emulate it. */
#if !defined(__cplusplus)
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
/*
We need to fill some data before uncorking. Not doing this will result in the write callback
never getting fired. We're not going to abort if writing fails because I still want the device
to get uncorked.
*/
ma_device_write_to_stream__pulse(pDevice, (ma_pa_stream*)(pDevice->pulse.pStreamPlayback), NULL); /* No need to check the result here. Always want to fall through an uncork.*/
result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 0);
if (result != MA_SUCCESS) {
return result;
}
}
return MA_SUCCESS;
}
static ma_result ma_device_stop__pulse(ma_device* pDevice)
{
ma_result result;
MA_ASSERT(pDevice != NULL);
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
result = ma_device__cork_stream__pulse(pDevice, ma_device_type_capture, 1);
if (result != MA_SUCCESS) {
return result;
}
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
/*
Ideally we would drain the device here, but there's been cases where PulseAudio seems to be
broken on some systems to the point where no audio processing seems to happen. When this
happens, draining never completes and we get stuck here. For now I'm disabling draining of
the device so we don't just freeze the application.
*/
#if 0
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);
ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pDevice->pulse.pMainLoop, pOP);
#endif
result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 1);
if (result != MA_SUCCESS) {
return result;
}
}
return MA_SUCCESS;
}
static ma_result ma_device_data_loop__pulse(ma_device* pDevice)
{
int resultPA;
MA_ASSERT(pDevice != NULL);
/* NOTE: Don't start the device here. It'll be done at a higher level. */
/*
All data is handled through callbacks. All we need to do is iterate over the main loop and let
the callbacks deal with it.
*/
while (ma_device_get_state(pDevice) == ma_device_state_started) {
resultPA = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1, NULL);
if (resultPA < 0) {
break;
}
}
/* NOTE: Don't stop the device here. It'll be done at a higher level. */
return MA_SUCCESS;
}
static ma_result ma_device_data_loop_wakeup__pulse(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
((ma_pa_mainloop_wakeup_proc)pDevice->pContext->pulse.pa_mainloop_wakeup)((ma_pa_mainloop*)pDevice->pulse.pMainLoop);
return MA_SUCCESS;
}
static ma_result ma_context_uninit__pulse(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_pulseaudio);
((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pContext->pulse.pPulseContext);
((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pContext->pulse.pPulseContext);
((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)pContext->pulse.pMainLoop);
ma_free(pContext->pulse.pServerName, &pContext->allocationCallbacks);
ma_free(pContext->pulse.pApplicationName, &pContext->allocationCallbacks);
#ifndef MA_NO_RUNTIME_LINKING
ma_dlclose(pContext, pContext->pulse.pulseSO);
#endif
return MA_SUCCESS;
}
static ma_result ma_context_init__pulse(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
ma_result result;
#ifndef MA_NO_RUNTIME_LINKING
const char* libpulseNames[] = {
"libpulse.so",
"libpulse.so.0"
};
size_t i;
for (i = 0; i < ma_countof(libpulseNames); ++i) {
pContext->pulse.pulseSO = ma_dlopen(pContext, libpulseNames[i]);
if (pContext->pulse.pulseSO != NULL) {
break;
}
}
if (pContext->pulse.pulseSO == NULL) {
return MA_NO_BACKEND;
}
pContext->pulse.pa_mainloop_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_new");
pContext->pulse.pa_mainloop_free = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_free");
pContext->pulse.pa_mainloop_quit = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_quit");
pContext->pulse.pa_mainloop_get_api = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_get_api");
pContext->pulse.pa_mainloop_iterate = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_iterate");
pContext->pulse.pa_mainloop_wakeup = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_mainloop_wakeup");
pContext->pulse.pa_threaded_mainloop_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_new");
pContext->pulse.pa_threaded_mainloop_free = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_free");
pContext->pulse.pa_threaded_mainloop_start = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_start");
pContext->pulse.pa_threaded_mainloop_stop = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_stop");
pContext->pulse.pa_threaded_mainloop_lock = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_lock");
pContext->pulse.pa_threaded_mainloop_unlock = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_unlock");
pContext->pulse.pa_threaded_mainloop_wait = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_wait");
pContext->pulse.pa_threaded_mainloop_signal = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_signal");
pContext->pulse.pa_threaded_mainloop_accept = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_accept");
pContext->pulse.pa_threaded_mainloop_get_retval = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_get_retval");
pContext->pulse.pa_threaded_mainloop_get_api = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_get_api");
pContext->pulse.pa_threaded_mainloop_in_thread = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_in_thread");
pContext->pulse.pa_threaded_mainloop_set_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_threaded_mainloop_set_name");
pContext->pulse.pa_context_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_new");
pContext->pulse.pa_context_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_unref");
pContext->pulse.pa_context_connect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_connect");
pContext->pulse.pa_context_disconnect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_disconnect");
pContext->pulse.pa_context_set_state_callback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_set_state_callback");
pContext->pulse.pa_context_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_state");
pContext->pulse.pa_context_get_sink_info_list = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_sink_info_list");
pContext->pulse.pa_context_get_source_info_list = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_source_info_list");
pContext->pulse.pa_context_get_sink_info_by_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_sink_info_by_name");
pContext->pulse.pa_context_get_source_info_by_name = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_context_get_source_info_by_name");
pContext->pulse.pa_operation_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_operation_unref");
pContext->pulse.pa_operation_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_operation_get_state");
pContext->pulse.pa_channel_map_init_extend = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_init_extend");
pContext->pulse.pa_channel_map_valid = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_valid");
pContext->pulse.pa_channel_map_compatible = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_channel_map_compatible");
pContext->pulse.pa_stream_new = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_new");
pContext->pulse.pa_stream_unref = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_unref");
pContext->pulse.pa_stream_connect_playback = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_connect_playback");
pContext->pulse.pa_stream_connect_record = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_connect_record");
pContext->pulse.pa_stream_disconnect = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_disconnect");
pContext->pulse.pa_stream_get_state = (ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO, "pa_stream_get_state");
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
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);
if (ppServerPorts == NULL) {
((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[JACK] Failed to retrieve physical ports.");
return MA_ERROR;
}
for (i = 0; ppServerPorts[i] != NULL; ++i) {
const char* pServerPort = ppServerPorts[i];
const char* pClientPort = ((ma_jack_port_name_proc)pContext->jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.ppPortsPlayback[i]);
resultJACK = ((ma_jack_connect_proc)pContext->jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pClientPort, pServerPort);
if (resultJACK != 0) {
((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[JACK] Failed to connect ports.");
return MA_ERROR;
}
}
((ma_jack_free_proc)pContext->jack.jack_free)((void*)ppServerPorts);
}
return MA_SUCCESS;
}
static ma_result ma_device_stop__jack(ma_device* pDevice)
{
ma_context* pContext = pDevice->pContext;
if (((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient) != 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[JACK] An error occurred when deactivating the JACK client.");
return MA_ERROR;
}
ma_device__on_notification_stopped(pDevice);
return MA_SUCCESS;
}
static ma_result ma_context_uninit__jack(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_jack);
ma_free(pContext->jack.pClientName, &pContext->allocationCallbacks);
pContext->jack.pClientName = NULL;
#ifndef MA_NO_RUNTIME_LINKING
ma_dlclose(pContext, pContext->jack.jackSO);
#endif
return MA_SUCCESS;
}
static ma_result ma_context_init__jack(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
#ifndef MA_NO_RUNTIME_LINKING
const char* libjackNames[] = {
#ifdef MA_WIN32
"libjack.dll",
"libjack64.dll"
#else
"libjack.so",
"libjack.so.0"
#endif
};
size_t i;
for (i = 0; i < ma_countof(libjackNames); ++i) {
pContext->jack.jackSO = ma_dlopen(pContext, libjackNames[i]);
if (pContext->jack.jackSO != NULL) {
break;
}
}
if (pContext->jack.jackSO == NULL) {
return MA_NO_BACKEND;
}
pContext->jack.jack_client_open = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_open");
pContext->jack.jack_client_close = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_close");
pContext->jack.jack_client_name_size = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_client_name_size");
pContext->jack.jack_set_process_callback = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_set_process_callback");
pContext->jack.jack_set_buffer_size_callback = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_set_buffer_size_callback");
pContext->jack.jack_on_shutdown = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_on_shutdown");
pContext->jack.jack_get_sample_rate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_sample_rate");
pContext->jack.jack_get_buffer_size = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_buffer_size");
pContext->jack.jack_get_ports = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_get_ports");
pContext->jack.jack_activate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_activate");
pContext->jack.jack_deactivate = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_deactivate");
pContext->jack.jack_connect = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_connect");
pContext->jack.jack_port_register = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_register");
pContext->jack.jack_port_name = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_name");
pContext->jack.jack_port_get_buffer = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_port_get_buffer");
pContext->jack.jack_free = (ma_proc)ma_dlsym(pContext, pContext->jack.jackSO, "jack_free");
#else
/*
This strange assignment system is here just to ensure type safety of miniaudio's function pointer
types. If anything differs slightly the compiler should throw a warning.
*/
ma_jack_client_open_proc _jack_client_open = jack_client_open;
ma_jack_client_close_proc _jack_client_close = jack_client_close;
ma_jack_client_name_size_proc _jack_client_name_size = jack_client_name_size;
ma_jack_set_process_callback_proc _jack_set_process_callback = jack_set_process_callback;
ma_jack_set_buffer_size_callback_proc _jack_set_buffer_size_callback = jack_set_buffer_size_callback;
ma_jack_on_shutdown_proc _jack_on_shutdown = jack_on_shutdown;
ma_jack_get_sample_rate_proc _jack_get_sample_rate = jack_get_sample_rate;
ma_jack_get_buffer_size_proc _jack_get_buffer_size = jack_get_buffer_size;
ma_jack_get_ports_proc _jack_get_ports = jack_get_ports;
ma_jack_activate_proc _jack_activate = jack_activate;
ma_jack_deactivate_proc _jack_deactivate = jack_deactivate;
ma_jack_connect_proc _jack_connect = jack_connect;
ma_jack_port_register_proc _jack_port_register = jack_port_register;
ma_jack_port_name_proc _jack_port_name = jack_port_name;
ma_jack_port_get_buffer_proc _jack_port_get_buffer = jack_port_get_buffer;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
Retrieving device information is more annoying on mobile than desktop. For simplicity I'm locking this down to whatever format is
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
retrieve from the AVAudioSession shared instance.
*/
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(NULL, &desc);
if (component == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
}
status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)(component, &audioUnit);
if (status != noErr) {
return ma_result_from_OSStatus(status);
}
formatScope = (deviceType == ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
formatElement = (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
propSize = sizeof(bestFormat);
status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
if (status != noErr) {
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
return ma_result_from_OSStatus(status);
}
((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
audioUnit = NULL;
/* Only a single format is being reported for iOS. */
pDeviceInfo->nativeDataFormatCount = 1;
result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pDeviceInfo->nativeDataFormats[0].format);
if (result != MA_SUCCESS) {
return result;
}
pDeviceInfo->nativeDataFormats[0].channels = bestFormat.mChannelsPerFrame;
/*
It looks like Apple are wanting to push the whole AVAudioSession thing. Thus, we need to use that to determine device settings. To do
this we just get the shared instance and inspect.
*/
@autoreleasepool {
AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
MA_ASSERT(pAudioSession != NULL);
pDeviceInfo->nativeDataFormats[0].sampleRate = (ma_uint32)pAudioSession.sampleRate;
}
}
#endif
(void)pDeviceInfo; /* Unused. */
return MA_SUCCESS;
}
static AudioBufferList* ma_allocate_AudioBufferList__coreaudio(ma_uint32 sizeInFrames, ma_format format, ma_uint32 channels, ma_stream_layout layout, const ma_allocation_callbacks* pAllocationCallbacks)
{
AudioBufferList* pBufferList;
UInt32 audioBufferSizeInBytes;
size_t allocationSize;
MA_ASSERT(sizeInFrames > 0);
MA_ASSERT(format != ma_format_unknown);
MA_ASSERT(channels > 0);
allocationSize = sizeof(AudioBufferList) - sizeof(AudioBuffer); /* Subtract sizeof(AudioBuffer) because that part is dynamically sized. */
if (layout == ma_stream_layout_interleaved) {
/* Interleaved case. This is the simple case because we just have one buffer. */
allocationSize += sizeof(AudioBuffer) * 1;
} else {
/* Non-interleaved case. This is the more complex case because there's more than one buffer. */
allocationSize += sizeof(AudioBuffer) * channels;
}
allocationSize += sizeInFrames * ma_get_bytes_per_frame(format, channels);
pBufferList = (AudioBufferList*)ma_malloc(allocationSize, pAllocationCallbacks);
if (pBufferList == NULL) {
return NULL;
}
audioBufferSizeInBytes = (UInt32)(sizeInFrames * ma_get_bytes_per_sample(format));
if (layout == ma_stream_layout_interleaved) {
pBufferList->mNumberBuffers = 1;
pBufferList->mBuffers[0].mNumberChannels = channels;
pBufferList->mBuffers[0].mDataByteSize = audioBufferSizeInBytes * channels;
pBufferList->mBuffers[0].mData = (ma_uint8*)pBufferList + sizeof(AudioBufferList);
} else {
ma_uint32 iBuffer;
pBufferList->mNumberBuffers = channels;
for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
pBufferList->mBuffers[iBuffer].mNumberChannels = 1;
pBufferList->mBuffers[iBuffer].mDataByteSize = audioBufferSizeInBytes;
pBufferList->mBuffers[iBuffer].mData = (ma_uint8*)pBufferList + ((sizeof(AudioBufferList) - sizeof(AudioBuffer)) + (sizeof(AudioBuffer) * channels)) + (audioBufferSizeInBytes * iBuffer);
}
}
return pBufferList;
}
static ma_result ma_device_realloc_AudioBufferList__coreaudio(ma_device* pDevice, ma_uint32 sizeInFrames, ma_format format, ma_uint32 channels, ma_stream_layout layout)
{
MA_ASSERT(pDevice != NULL);
MA_ASSERT(format != ma_format_unknown);
MA_ASSERT(channels > 0);
/* Only resize the buffer if necessary. */
if (pDevice->coreaudio.audioBufferCapInFrames < sizeInFrames) {
AudioBufferList* pNewAudioBufferList;
pNewAudioBufferList = ma_allocate_AudioBufferList__coreaudio(sizeInFrames, format, channels, layout, &pDevice->pContext->allocationCallbacks);
if (pNewAudioBufferList == NULL) {
return MA_OUT_OF_MEMORY;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (status != noErr) {
return ma_result_from_OSStatus(status);
}
}
/* We need to wait for the callback to finish before returning. */
ma_event_wait(&pDevice->coreaudio.stopEvent);
return MA_SUCCESS;
}
static ma_result ma_context_uninit__coreaudio(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_coreaudio);
#if defined(MA_APPLE_MOBILE)
if (!pContext->coreaudio.noAudioSessionDeactivate) {
if (![[AVAudioSession sharedInstance] setActive:false error:nil]) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "Failed to deactivate audio session.");
return MA_FAILED_TO_INIT_BACKEND;
}
}
#endif
#if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
#endif
#if !defined(MA_APPLE_MOBILE)
ma_context__uninit_device_tracking__coreaudio(pContext);
#endif
(void)pContext;
return MA_SUCCESS;
}
#if defined(MA_APPLE_MOBILE) && defined(__IPHONE_12_0)
static AVAudioSessionCategory ma_to_AVAudioSessionCategory(ma_ios_session_category category)
{
/* The "default" and "none" categories are treated different and should not be used as an input into this function. */
MA_ASSERT(category != ma_ios_session_category_default);
MA_ASSERT(category != ma_ios_session_category_none);
switch (category) {
case ma_ios_session_category_ambient: return AVAudioSessionCategoryAmbient;
case ma_ios_session_category_solo_ambient: return AVAudioSessionCategorySoloAmbient;
case ma_ios_session_category_playback: return AVAudioSessionCategoryPlayback;
case ma_ios_session_category_record: return AVAudioSessionCategoryRecord;
case ma_ios_session_category_play_and_record: return AVAudioSessionCategoryPlayAndRecord;
case ma_ios_session_category_multi_route: return AVAudioSessionCategoryMultiRoute;
case ma_ios_session_category_none: return AVAudioSessionCategoryAmbient;
case ma_ios_session_category_default: return AVAudioSessionCategoryAmbient;
default: return AVAudioSessionCategoryAmbient;
}
}
#endif
static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
#if !defined(MA_APPLE_MOBILE)
ma_result result;
#endif
MA_ASSERT(pConfig != NULL);
MA_ASSERT(pContext != NULL);
#if defined(MA_APPLE_MOBILE)
@autoreleasepool {
AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
AVAudioSessionCategoryOptions options = pConfig->coreaudio.sessionCategoryOptions;
MA_ASSERT(pAudioSession != NULL);
if (pConfig->coreaudio.sessionCategory == ma_ios_session_category_default) {
/*
I'm going to use trial and error to determine our default session category. First we'll try PlayAndRecord. If that fails
we'll try Playback and if that fails we'll try record. If all of these fail we'll just not set the category.
*/
#if !defined(MA_APPLE_TV) && !defined(MA_APPLE_WATCH)
options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
#endif
if ([pAudioSession setCategory: AVAudioSessionCategoryPlayAndRecord withOptions:options error:nil]) {
/* Using PlayAndRecord */
} else if ([pAudioSession setCategory: AVAudioSessionCategoryPlayback withOptions:options error:nil]) {
/* Using Playback */
} else if ([pAudioSession setCategory: AVAudioSessionCategoryRecord withOptions:options error:nil]) {
/* Using Record */
} else {
/* Leave as default? */
}
} else {
if (pConfig->coreaudio.sessionCategory != ma_ios_session_category_none) {
#if defined(__IPHONE_12_0)
if (![pAudioSession setCategory: ma_to_AVAudioSessionCategory(pConfig->coreaudio.sessionCategory) withOptions:options error:nil]) {
return MA_INVALID_OPERATION; /* Failed to set session category. */
}
#else
/* Ignore the session category on version 11 and older, but post a warning. */
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_WARNING, "Session category only supported in iOS 12 and newer.");
#endif
}
}
if (!pConfig->coreaudio.noAudioSessionActivate) {
if (![pAudioSession setActive:true error:nil]) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "Failed to activate audio session.");
return MA_FAILED_TO_INIT_BACKEND;
}
}
}
#endif
#if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
pContext->coreaudio.hCoreFoundation = ma_dlopen(pContext, "CoreFoundation.framework/CoreFoundation");
if (pContext->coreaudio.hCoreFoundation == NULL) {
return MA_API_NOT_FOUND;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
}
return MA_SUCCESS;
}
static ma_result ma_device_write__sndio(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
{
int result;
if (pFramesWritten != NULL) {
*pFramesWritten = 0;
}
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));
if (result == 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[sndio] Failed to send data from the client to the device.");
return MA_IO_ERROR;
}
if (pFramesWritten != NULL) {
*pFramesWritten = frameCount;
}
return MA_SUCCESS;
}
static ma_result ma_device_read__sndio(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
{
int result;
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
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));
if (result == 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[sndio] Failed to read data from the device to be sent to the device.");
return MA_IO_ERROR;
}
if (pFramesRead != NULL) {
*pFramesRead = frameCount;
}
return MA_SUCCESS;
}
static ma_result ma_context_uninit__sndio(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_sndio);
(void)pContext;
return MA_SUCCESS;
}
static ma_result ma_context_init__sndio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
#ifndef MA_NO_RUNTIME_LINKING
const char* libsndioNames[] = {
"libsndio.so"
};
size_t i;
for (i = 0; i < ma_countof(libsndioNames); ++i) {
pContext->sndio.sndioSO = ma_dlopen(pContext, libsndioNames[i]);
if (pContext->sndio.sndioSO != NULL) {
break;
}
}
if (pContext->sndio.sndioSO == NULL) {
return MA_NO_BACKEND;
}
pContext->sndio.sio_open = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_open");
pContext->sndio.sio_close = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_close");
pContext->sndio.sio_setpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_setpar");
pContext->sndio.sio_getpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_getpar");
pContext->sndio.sio_getcap = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_getcap");
pContext->sndio.sio_write = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_write");
pContext->sndio.sio_read = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_read");
pContext->sndio.sio_start = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_start");
pContext->sndio.sio_stop = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_stop");
pContext->sndio.sio_initpar = (ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO, "sio_initpar");
#else
pContext->sndio.sio_open = sio_open;
pContext->sndio.sio_close = sio_close;
pContext->sndio.sio_setpar = sio_setpar;
pContext->sndio.sio_getpar = sio_getpar;
pContext->sndio.sio_getcap = sio_getcap;
pContext->sndio.sio_write = sio_write;
pContext->sndio.sio_read = sio_read;
pContext->sndio.sio_start = sio_start;
pContext->sndio.sio_stop = sio_stop;
pContext->sndio.sio_initpar = sio_initpar;
#endif
pCallbacks->onContextInit = ma_context_init__sndio;
pCallbacks->onContextUninit = ma_context_uninit__sndio;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__sndio;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__sndio;
pCallbacks->onDeviceInit = ma_device_init__sndio;
pCallbacks->onDeviceUninit = ma_device_uninit__sndio;
pCallbacks->onDeviceStart = ma_device_start__sndio;
pCallbacks->onDeviceStop = ma_device_stop__sndio;
pCallbacks->onDeviceRead = ma_device_read__sndio;
pCallbacks->onDeviceWrite = ma_device_write__sndio;
pCallbacks->onDeviceDataLoop = NULL;
(void)pConfig;
return MA_SUCCESS;
}
#endif /* sndio */
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdPlayback);
if (result != MA_SUCCESS) {
return result;
}
}
return MA_SUCCESS;
}
static ma_result ma_device_write__audio4(ma_device* pDevice, const void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
{
int result;
if (pFramesWritten != NULL) {
*pFramesWritten = 0;
}
result = write(pDevice->audio4.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
if (result < 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[audio4] Failed to write data to the device.");
return ma_result_from_errno(errno);
}
if (pFramesWritten != NULL) {
*pFramesWritten = (ma_uint32)result / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
}
return MA_SUCCESS;
}
static ma_result ma_device_read__audio4(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
{
int result;
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
result = read(pDevice->audio4.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
if (result < 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[audio4] Failed to read data from the device.");
return ma_result_from_errno(errno);
}
if (pFramesRead != NULL) {
*pFramesRead = (ma_uint32)result / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
}
return MA_SUCCESS;
}
static ma_result ma_context_uninit__audio4(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_audio4);
(void)pContext;
return MA_SUCCESS;
}
static ma_result ma_context_init__audio4(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
MA_ASSERT(pContext != NULL);
(void)pConfig;
pCallbacks->onContextInit = ma_context_init__audio4;
pCallbacks->onContextUninit = ma_context_uninit__audio4;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__audio4;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__audio4;
pCallbacks->onDeviceInit = ma_device_init__audio4;
pCallbacks->onDeviceUninit = ma_device_uninit__audio4;
pCallbacks->onDeviceStart = ma_device_start__audio4;
pCallbacks->onDeviceStop = ma_device_stop__audio4;
pCallbacks->onDeviceRead = ma_device_read__audio4;
pCallbacks->onDeviceWrite = ma_device_write__audio4;
pCallbacks->onDeviceDataLoop = NULL;
return MA_SUCCESS;
}
#endif /* audio4 */
/******************************************************************************
OSS Backend
******************************************************************************/
#ifdef MA_HAS_OSS
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>
#ifndef SNDCTL_DSP_HALT
#define SNDCTL_DSP_HALT SNDCTL_DSP_RESET
#endif
#define MA_OSS_DEFAULT_DEVICE_NAME "/dev/dsp"
static int ma_open_temp_device__oss()
{
/* The OSS sample code uses "/dev/mixer" as the device for getting system properties so I'm going to do the same. */
int fd = open("/dev/mixer", O_RDONLY, 0);
if (fd >= 0) {
return fd;
}
return -1;
}
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)
{
const char* deviceName;
int flags;
MA_ASSERT(pContext != NULL);
MA_ASSERT(pfd != NULL);
(void)pContext;
*pfd = -1;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (pFramesWritten != NULL) {
*pFramesWritten = 0;
}
/* Don't do any processing if the device is stopped. */
deviceState = ma_device_get_state(pDevice);
if (deviceState != ma_device_state_started && deviceState != ma_device_state_starting) {
return MA_SUCCESS;
}
resultOSS = write(pDevice->oss.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
if (resultOSS < 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[OSS] Failed to send data from the client to the device.");
return ma_result_from_errno(errno);
}
if (pFramesWritten != NULL) {
*pFramesWritten = (ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
}
return MA_SUCCESS;
}
static ma_result ma_device_read__oss(ma_device* pDevice, void* pPCMFrames, ma_uint32 frameCount, ma_uint32* pFramesRead)
{
int resultOSS;
ma_uint32 deviceState;
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
/* Don't do any processing if the device is stopped. */
deviceState = ma_device_get_state(pDevice);
if (deviceState != ma_device_state_started && deviceState != ma_device_state_starting) {
return MA_SUCCESS;
}
resultOSS = read(pDevice->oss.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
if (resultOSS < 0) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[OSS] Failed to read data from the device to be sent to the client.");
return ma_result_from_errno(errno);
}
if (pFramesRead != NULL) {
*pFramesRead = (ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
}
return MA_SUCCESS;
}
static ma_result ma_context_uninit__oss(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_oss);
(void)pContext;
return MA_SUCCESS;
}
static ma_result ma_context_init__oss(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
int fd;
int ossVersion;
int result;
MA_ASSERT(pContext != NULL);
(void)pConfig;
/* Try opening a temporary device first so we can get version information. This is closed at the end. */
fd = ma_open_temp_device__oss();
if (fd == -1) {
ma_log_post(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[OSS] Failed to open temporary device for retrieving system properties."); /* Looks liks OSS isn't installed, or there are no available devices. */
return MA_NO_BACKEND;
}
/* Grab the OSS version. */
ossVersion = 0;
result = ioctl(fd, OSS_GETVERSION, &ossVersion);
if (result == -1) {
close(fd);
ma_log_post(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[OSS] Failed to retrieve OSS version.");
return MA_NO_BACKEND;
}
/* The file handle to temp device is no longer needed. Close ASAP. */
close(fd);
pContext->oss.versionMajor = ((ossVersion & 0xFF0000) >> 16);
pContext->oss.versionMinor = ((ossVersion & 0x00FF00) >> 8);
pCallbacks->onContextInit = ma_context_init__oss;
pCallbacks->onContextUninit = ma_context_uninit__oss;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__oss;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__oss;
pCallbacks->onDeviceInit = ma_device_init__oss;
pCallbacks->onDeviceUninit = ma_device_uninit__oss;
pCallbacks->onDeviceStart = ma_device_start__oss;
pCallbacks->onDeviceStop = ma_device_stop__oss;
pCallbacks->onDeviceRead = ma_device_read__oss;
pCallbacks->onDeviceWrite = ma_device_write__oss;
pCallbacks->onDeviceDataLoop = NULL;
return MA_SUCCESS;
}
#endif /* OSS */
/******************************************************************************
AAudio Backend
******************************************************************************/
#ifdef MA_HAS_AAUDIO
/*#include <AAudio/AAudio.h>*/
typedef int32_t ma_aaudio_result_t;
typedef int32_t ma_aaudio_direction_t;
typedef int32_t ma_aaudio_sharing_mode_t;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
/* We'll only ever do this in response to a reroute. */
ma_device__on_notification_rerouted(pDevice);
/* If the device is started, start the streams. Maybe make this configurable? */
if (ma_device_get_state(pDevice) == ma_device_state_started) {
if (pDevice->aaudio.noAutoStartAfterReroute == MA_FALSE) {
ma_device_start__aaudio(pDevice);
} else {
ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */
}
}
return MA_SUCCESS;
}
}
static ma_result ma_device_get_info__aaudio(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo)
{
ma_AAudioStream* pStream = NULL;
MA_ASSERT(pDevice != NULL);
MA_ASSERT(type != ma_device_type_duplex);
MA_ASSERT(pDeviceInfo != NULL);
if (type == ma_device_type_playback) {
pStream = (ma_AAudioStream*)pDevice->aaudio.pStreamCapture;
pDeviceInfo->id.aaudio = pDevice->capture.id.aaudio;
ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1); /* Only supporting default devices. */
}
if (type == ma_device_type_capture) {
pStream = (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback;
pDeviceInfo->id.aaudio = pDevice->playback.id.aaudio;
ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1); /* Only supporting default devices. */
}
/* Safety. Should never happen. */
if (pStream == NULL) {
return MA_INVALID_OPERATION;
}
pDeviceInfo->nativeDataFormatCount = 0;
ma_context_add_native_data_format_from_AAudioStream__aaudio(pDevice->pContext, pStream, 0, pDeviceInfo);
return MA_SUCCESS;
}
static ma_result ma_context_uninit__aaudio(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_aaudio);
ma_device_job_thread_uninit(&pContext->aaudio.jobThread, &pContext->allocationCallbacks);
ma_dlclose(pContext, pContext->aaudio.hAAudio);
pContext->aaudio.hAAudio = NULL;
return MA_SUCCESS;
}
static ma_result ma_context_init__aaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
size_t i;
const char* libNames[] = {
"libaaudio.so"
};
for (i = 0; i < ma_countof(libNames); ++i) {
pContext->aaudio.hAAudio = ma_dlopen(pContext, libNames[i]);
if (pContext->aaudio.hAAudio != NULL) {
break;
}
}
if (pContext->aaudio.hAAudio == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
}
pContext->aaudio.AAudio_createStreamBuilder = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudio_createStreamBuilder");
pContext->aaudio.AAudioStreamBuilder_delete = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_delete");
pContext->aaudio.AAudioStreamBuilder_setDeviceId = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDeviceId");
pContext->aaudio.AAudioStreamBuilder_setDirection = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDirection");
pContext->aaudio.AAudioStreamBuilder_setSharingMode = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setSharingMode");
pContext->aaudio.AAudioStreamBuilder_setFormat = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setFormat");
pContext->aaudio.AAudioStreamBuilder_setChannelCount = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setChannelCount");
pContext->aaudio.AAudioStreamBuilder_setSampleRate = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setSampleRate");
pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setBufferCapacityInFrames");
pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setFramesPerDataCallback");
pContext->aaudio.AAudioStreamBuilder_setDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setDataCallback");
pContext->aaudio.AAudioStreamBuilder_setErrorCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setErrorCallback");
pContext->aaudio.AAudioStreamBuilder_setPerformanceMode = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setPerformanceMode");
pContext->aaudio.AAudioStreamBuilder_setUsage = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setUsage");
pContext->aaudio.AAudioStreamBuilder_setContentType = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setContentType");
pContext->aaudio.AAudioStreamBuilder_setInputPreset = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_setInputPreset");
pContext->aaudio.AAudioStreamBuilder_openStream = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStreamBuilder_openStream");
pContext->aaudio.AAudioStream_close = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_close");
pContext->aaudio.AAudioStream_getState = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getState");
pContext->aaudio.AAudioStream_waitForStateChange = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_waitForStateChange");
pContext->aaudio.AAudioStream_getFormat = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFormat");
pContext->aaudio.AAudioStream_getChannelCount = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getChannelCount");
pContext->aaudio.AAudioStream_getSampleRate = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getSampleRate");
pContext->aaudio.AAudioStream_getBufferCapacityInFrames = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getBufferCapacityInFrames");
pContext->aaudio.AAudioStream_getFramesPerDataCallback = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerDataCallback");
pContext->aaudio.AAudioStream_getFramesPerBurst = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerBurst");
pContext->aaudio.AAudioStream_requestStart = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStart");
pContext->aaudio.AAudioStream_requestStop = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStop");
pCallbacks->onContextInit = ma_context_init__aaudio;
pCallbacks->onContextUninit = ma_context_uninit__aaudio;
pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__aaudio;
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__aaudio;
pCallbacks->onDeviceInit = ma_device_init__aaudio;
pCallbacks->onDeviceUninit = ma_device_uninit__aaudio;
pCallbacks->onDeviceStart = ma_device_start__aaudio;
pCallbacks->onDeviceStop = ma_device_stop__aaudio;
pCallbacks->onDeviceRead = NULL; /* Not used because AAudio is asynchronous. */
pCallbacks->onDeviceWrite = NULL; /* Not used because AAudio is asynchronous. */
pCallbacks->onDeviceDataLoop = NULL; /* Not used because AAudio is asynchronous. */
pCallbacks->onDeviceGetInfo = ma_device_get_info__aaudio;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
static ma_result ma_context_uninit__opensl(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_opensl);
(void)pContext;
/* Uninit global data. */
ma_spinlock_lock(&g_maOpenSLSpinlock);
{
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(). */
g_maOpenSLInitCounter -= 1;
if (g_maOpenSLInitCounter == 0) {
(*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
}
}
ma_spinlock_unlock(&g_maOpenSLSpinlock);
return MA_SUCCESS;
}
static ma_result ma_dlsym_SLInterfaceID__opensl(ma_context* pContext, const char* pName, ma_handle* pHandle)
{
/* 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. */
ma_handle* p = (ma_handle*)ma_dlsym(pContext, pContext->opensl.libOpenSLES, pName);
if (p == NULL) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_INFO, "[OpenSL] Cannot find symbol %s", pName);
return MA_NO_BACKEND;
}
*pHandle = *p;
return MA_SUCCESS;
}
static ma_result ma_context_init_engine_nolock__opensl(ma_context* pContext)
{
g_maOpenSLInitCounter += 1;
if (g_maOpenSLInitCounter == 1) {
SLresult resultSL;
resultSL = ((ma_slCreateEngine_proc)pContext->opensl.slCreateEngine)(&g_maEngineObjectSL, 0, NULL, 0, NULL, NULL);
if (resultSL != SL_RESULT_SUCCESS) {
g_maOpenSLInitCounter -= 1;
return ma_result_from_OpenSL(resultSL);
}
(*g_maEngineObjectSL)->Realize(g_maEngineObjectSL, SL_BOOLEAN_FALSE);
resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, (SLInterfaceID)pContext->opensl.SL_IID_ENGINE, &g_maEngineSL);
if (resultSL != SL_RESULT_SUCCESS) {
(*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
g_maOpenSLInitCounter -= 1;
return ma_result_from_OpenSL(resultSL);
}
}
return MA_SUCCESS;
}
static ma_result ma_context_init__opensl(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
ma_result result;
#if !defined(MA_NO_RUNTIME_LINKING)
size_t i;
const char* libOpenSLESNames[] = {
"libOpenSLES.so"
};
#endif
MA_ASSERT(pContext != NULL);
(void)pConfig;
#if !defined(MA_NO_RUNTIME_LINKING)
/*
Dynamically link against libOpenSLES.so. I have now had multiple reports that SL_IID_ANDROIDSIMPLEBUFFERQUEUE cannot be found. One
report was happening at compile time and another at runtime. To try working around this, I'm going to link to libOpenSLES at runtime
and extract the symbols rather than reference them directly. This should, hopefully, fix these issues as the compiler won't see any
references to the symbols and will hopefully skip the checks.
*/
for (i = 0; i < ma_countof(libOpenSLESNames); i += 1) {
pContext->opensl.libOpenSLES = ma_dlopen(pContext, libOpenSLESNames[i]);
if (pContext->opensl.libOpenSLES != NULL) {
break;
}
}
if (pContext->opensl.libOpenSLES == NULL) {
ma_log_post(ma_context_get_log(pContext), MA_LOG_LEVEL_INFO, "[OpenSL] Could not find libOpenSLES.so");
return MA_NO_BACKEND;
}
result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ENGINE", &pContext->opensl.SL_IID_ENGINE);
if (result != MA_SUCCESS) {
ma_dlclose(pContext, pContext->opensl.libOpenSLES);
return result;
}
result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_AUDIOIODEVICECAPABILITIES", &pContext->opensl.SL_IID_AUDIOIODEVICECAPABILITIES);
if (result != MA_SUCCESS) {
ma_dlclose(pContext, pContext->opensl.libOpenSLES);
return result;
}
result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_ANDROIDSIMPLEBUFFERQUEUE", &pContext->opensl.SL_IID_ANDROIDSIMPLEBUFFERQUEUE);
if (result != MA_SUCCESS) {
ma_dlclose(pContext, pContext->opensl.libOpenSLES);
return result;
}
result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_RECORD", &pContext->opensl.SL_IID_RECORD);
if (result != MA_SUCCESS) {
ma_dlclose(pContext, pContext->opensl.libOpenSLES);
return result;
}
result = ma_dlsym_SLInterfaceID__opensl(pContext, "SL_IID_PLAY", &pContext->opensl.SL_IID_PLAY);
if (result != MA_SUCCESS) {
ma_dlclose(pContext, pContext->opensl.libOpenSLES);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}, pDevice->webaudio.indexCapture);
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
EM_ASM({
var device = miniaudio.get_device_by_index($0);
device.webaudio.resume();
device.state = 2; /* ma_device_state_started */
}, pDevice->webaudio.indexPlayback);
}
return MA_SUCCESS;
}
static ma_result ma_device_stop__webaudio(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
/*
From the WebAudio API documentation for AudioContext.suspend():
Suspends the progression of AudioContext's currentTime, allows any current context processing blocks that are already processed to be played to the
destination, and then allows the system to release its claim on audio hardware.
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
do any kind of explicit draining.
*/
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
EM_ASM({
var device = miniaudio.get_device_by_index($0);
device.webaudio.suspend();
device.state = 1; /* ma_device_state_stopped */
}, pDevice->webaudio.indexCapture);
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
EM_ASM({
var device = miniaudio.get_device_by_index($0);
device.webaudio.suspend();
device.state = 1; /* ma_device_state_stopped */
}, pDevice->webaudio.indexPlayback);
}
ma_device__on_notification_stopped(pDevice);
return MA_SUCCESS;
}
static ma_result ma_context_uninit__webaudio(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
MA_ASSERT(pContext->backend == ma_backend_webaudio);
/* Nothing needs to be done here. */
(void)pContext;
return MA_SUCCESS;
}
static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
{
int resultFromJS;
MA_ASSERT(pContext != NULL);
(void)pConfig; /* Unused. */
/* Here is where our global JavaScript object is initialized. */
resultFromJS = EM_ASM_INT({
if ((window.AudioContext || window.webkitAudioContext) === undefined) {
return 0; /* Web Audio not supported. */
}
if (typeof(window.miniaudio) === 'undefined') {
window.miniaudio = {};
miniaudio.devices = []; /* Device cache for mapping devices to indexes for JavaScript/C interop. */
miniaudio.track_device = function(device) {
/* Try inserting into a free slot first. */
for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
if (miniaudio.devices[iDevice] == null) {
miniaudio.devices[iDevice] = device;
return iDevice;
}
}
/* Getting here means there is no empty slots in the array so we just push to the end. */
miniaudio.devices.push(device);
return miniaudio.devices.length - 1;
};
miniaudio.untrack_device_by_index = function(deviceIndex) {
/* We just set the device's slot to null. The slot will get reused in the next call to ma_track_device. */
miniaudio.devices[deviceIndex] = null;
/* Trim the array if possible. */
while (miniaudio.devices.length > 0) {
if (miniaudio.devices[miniaudio.devices.length-1] == null) {
miniaudio.devices.pop();
} else {
break;
}
}
};
miniaudio.untrack_device = function(device) {
for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
if (miniaudio.devices[iDevice] == device) {
return miniaudio.untrack_device_by_index(iDevice);
}
}
};
miniaudio.get_device_by_index = function(deviceIndex) {
return miniaudio.devices[deviceIndex];
};
miniaudio.unlock_event_types = (function(){
return ['touchstart', 'touchend', 'click'];
})();
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
result = ma_device_get_info(pDevice, ma_device_type_playback, &deviceInfo);
if (result == MA_SUCCESS) {
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), deviceInfo.name, (size_t)-1);
} else {
/* We failed to retrieve the device info. Fall back to a default name. */
if (pDescriptorPlayback->pDeviceID == NULL) {
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
} else {
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), "Playback Device", (size_t)-1);
}
}
}
}
/* Update data conversion. */
return ma_device__post_init_setup(pDevice, deviceType); /* TODO: Should probably rename ma_device__post_init_setup() to something better. */
}
static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData)
{
ma_device* pDevice = (ma_device*)pData;
MA_ASSERT(pDevice != NULL);
#ifdef MA_WIN32
ma_CoInitializeEx(pDevice->pContext, NULL, MA_COINIT_VALUE);
#endif
/*
When the device is being initialized it's initial state is set to ma_device_state_uninitialized. Before returning from
ma_device_init(), the state needs to be set to something valid. In miniaudio the device's default state immediately
after initialization is stopped, so therefore we need to mark the device as such. miniaudio will wait on the worker
thread to signal an event to know when the worker thread is ready for action.
*/
ma_device__set_state(pDevice, ma_device_state_stopped);
ma_event_signal(&pDevice->stopEvent);
for (;;) { /* <-- This loop just keeps the thread alive. The main audio loop is inside. */
ma_result startResult;
ma_result stopResult; /* <-- This will store the result from onDeviceStop(). If it returns an error, we don't fire the stopped notification callback. */
/* We wait on an event to know when something has requested that the device be started and the main loop entered. */
ma_event_wait(&pDevice->wakeupEvent);
/* Default result code. */
pDevice->workResult = MA_SUCCESS;
/* If the reason for the wake up is that we are terminating, just break from the loop. */
if (ma_device_get_state(pDevice) == ma_device_state_uninitialized) {
break;
}
/*
Getting to this point means the device is wanting to get started. The function that has requested that the device
be started will be waiting on an event (pDevice->startEvent) which means we need to make sure we signal the event
in both the success and error case. It's important that the state of the device is set _before_ signaling the event.
*/
MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_starting);
/* If the device has a start callback, start it now. */
if (pDevice->pContext->callbacks.onDeviceStart != NULL) {
startResult = pDevice->pContext->callbacks.onDeviceStart(pDevice);
} else {
startResult = MA_SUCCESS;
}
/*
If starting was not successful we'll need to loop back to the start and wait for something
to happen (pDevice->wakeupEvent).
*/
if (startResult != MA_SUCCESS) {
pDevice->workResult = startResult;
ma_event_signal(&pDevice->startEvent); /* <-- Always signal the start event so ma_device_start() can return as it'll be waiting on it. */
continue;
}
/* Make sure the state is set appropriately. */
ma_device__set_state(pDevice, ma_device_state_started); /* <-- Set this before signaling the event so that the state is always guaranteed to be good after ma_device_start() has returned. */
ma_event_signal(&pDevice->startEvent);
ma_device__on_notification_started(pDevice);
if (pDevice->pContext->callbacks.onDeviceDataLoop != NULL) {
pDevice->pContext->callbacks.onDeviceDataLoop(pDevice);
} else {
/* The backend is not using a custom main loop implementation, so now fall back to the blocking read-write implementation. */
ma_device_audio_thread__default_read_write(pDevice);
}
/* Getting here means we have broken from the main loop which happens the application has requested that device be stopped. */
if (pDevice->pContext->callbacks.onDeviceStop != NULL) {
stopResult = pDevice->pContext->callbacks.onDeviceStop(pDevice);
} else {
stopResult = MA_SUCCESS; /* No stop callback with the backend. Just assume successful. */
}
/*
After the device has stopped, make sure an event is posted. Don't post a stopped event if
stopping failed. This can happen on some backends when the underlying stream has been
stopped due to the device being physically unplugged or disabled via an OS setting.
*/
if (stopResult == MA_SUCCESS) {
ma_device__on_notification_stopped(pDevice);
}
/* 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. */
ma_device__set_state(pDevice, ma_device_state_stopped);
ma_event_signal(&pDevice->stopEvent);
}
#ifdef MA_WIN32
ma_CoUninitialize(pDevice->pContext);
#endif
return (ma_thread_result)0;
}
/* Helper for determining whether or not the given device is initialized. */
static ma_bool32 ma_device__is_initialized(ma_device* pDevice)
{
if (pDevice == NULL) {
return MA_FALSE;
}
return ma_device_get_state(pDevice) != ma_device_state_uninitialized;
}
#ifdef MA_WIN32
static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
{
/* For some reason UWP complains when CoUninitialize() is called. I'm just not going to call it on UWP. */
#ifdef MA_WIN32_DESKTOP
ma_CoUninitialize(pContext);
ma_dlclose(pContext, pContext->win32.hUser32DLL);
ma_dlclose(pContext, pContext->win32.hOle32DLL);
ma_dlclose(pContext, pContext->win32.hAdvapi32DLL);
#else
(void)pContext;
#endif
return MA_SUCCESS;
}
static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
{
#ifdef MA_WIN32_DESKTOP
/* Ole32.dll */
pContext->win32.hOle32DLL = ma_dlopen(pContext, "ole32.dll");
if (pContext->win32.hOle32DLL == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pContext->posix.pthread_cond_wait = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_wait");
pContext->posix.pthread_cond_signal = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_cond_signal");
pContext->posix.pthread_attr_init = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_init");
pContext->posix.pthread_attr_destroy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_destroy");
pContext->posix.pthread_attr_setschedpolicy = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_setschedpolicy");
pContext->posix.pthread_attr_getschedparam = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_getschedparam");
pContext->posix.pthread_attr_setschedparam = (ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO, "pthread_attr_setschedparam");
#else
pContext->posix.pthread_create = (ma_proc)pthread_create;
pContext->posix.pthread_join = (ma_proc)pthread_join;
pContext->posix.pthread_mutex_init = (ma_proc)pthread_mutex_init;
pContext->posix.pthread_mutex_destroy = (ma_proc)pthread_mutex_destroy;
pContext->posix.pthread_mutex_lock = (ma_proc)pthread_mutex_lock;
pContext->posix.pthread_mutex_unlock = (ma_proc)pthread_mutex_unlock;
pContext->posix.pthread_cond_init = (ma_proc)pthread_cond_init;
pContext->posix.pthread_cond_destroy = (ma_proc)pthread_cond_destroy;
pContext->posix.pthread_cond_wait = (ma_proc)pthread_cond_wait;
pContext->posix.pthread_cond_signal = (ma_proc)pthread_cond_signal;
pContext->posix.pthread_attr_init = (ma_proc)pthread_attr_init;
pContext->posix.pthread_attr_destroy = (ma_proc)pthread_attr_destroy;
#if !defined(__EMSCRIPTEN__)
pContext->posix.pthread_attr_setschedpolicy = (ma_proc)pthread_attr_setschedpolicy;
pContext->posix.pthread_attr_getschedparam = (ma_proc)pthread_attr_getschedparam;
pContext->posix.pthread_attr_setschedparam = (ma_proc)pthread_attr_setschedparam;
#endif
#endif
return MA_SUCCESS;
}
#endif
static ma_result ma_context_init_backend_apis(ma_context* pContext)
{
ma_result result;
#ifdef MA_WIN32
result = ma_context_init_backend_apis__win32(pContext);
#else
result = ma_context_init_backend_apis__nix(pContext);
#endif
return result;
}
static ma_result ma_context_uninit_backend_apis(ma_context* pContext)
{
ma_result result;
#ifdef MA_WIN32
result = ma_context_uninit_backend_apis__win32(pContext);
#else
result = ma_context_uninit_backend_apis__nix(pContext);
#endif
return result;
}
static ma_bool32 ma_context_is_backend_asynchronous(ma_context* pContext)
{
MA_ASSERT(pContext != NULL);
if (pContext->callbacks.onDeviceRead == NULL && pContext->callbacks.onDeviceWrite == NULL) {
if (pContext->callbacks.onDeviceDataLoop == NULL) {
return MA_TRUE;
} else {
return MA_FALSE;
}
} else {
return MA_FALSE;
}
}
/* The default capacity doesn't need to be too big. */
#ifndef MA_DEFAULT_DEVICE_JOB_QUEUE_CAPACITY
#define MA_DEFAULT_DEVICE_JOB_QUEUE_CAPACITY 32
#endif
MA_API ma_device_job_thread_config ma_device_job_thread_config_init(void)
{
ma_device_job_thread_config config;
MA_ZERO_OBJECT(&config);
config.noThread = MA_FALSE;
config.jobQueueCapacity = MA_DEFAULT_DEVICE_JOB_QUEUE_CAPACITY;
config.jobQueueFlags = 0;
return config;
}
static ma_thread_result MA_THREADCALL ma_device_job_thread_entry(void* pUserData)
{
ma_device_job_thread* pJobThread = (ma_device_job_thread*)pUserData;
MA_ASSERT(pJobThread != NULL);
for (;;) {
ma_result result;
ma_job job;
result = ma_device_job_thread_next(pJobThread, &job);
if (result != MA_SUCCESS) {
break;
}
if (job.toc.breakup.code == MA_JOB_TYPE_QUIT) {
break;
}
ma_job_process(&job);
}
return (ma_thread_result)0;
}
MA_API ma_result ma_device_job_thread_init(const ma_device_job_thread_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_device_job_thread* pJobThread)
{
ma_result result;
ma_job_queue_config jobQueueConfig;
if (pJobThread == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pJobThread);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
/* Initialize the job queue before the thread to ensure it's in a valid state. */
jobQueueConfig = ma_job_queue_config_init(pConfig->jobQueueFlags, pConfig->jobQueueCapacity);
result = ma_job_queue_init(&jobQueueConfig, pAllocationCallbacks, &pJobThread->jobQueue);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize job queue. */
}
/* The thread needs to be initialized after the job queue to ensure the thread doesn't try to access it prematurely. */
if (pConfig->noThread == MA_FALSE) {
result = ma_thread_create(&pJobThread->thread, ma_thread_priority_normal, 0, ma_device_job_thread_entry, pJobThread, pAllocationCallbacks);
if (result != MA_SUCCESS) {
ma_job_queue_uninit(&pJobThread->jobQueue, pAllocationCallbacks);
return result; /* Failed to create the job thread. */
}
pJobThread->_hasThread = MA_TRUE;
} else {
pJobThread->_hasThread = MA_FALSE;
}
return MA_SUCCESS;
}
MA_API void ma_device_job_thread_uninit(ma_device_job_thread* pJobThread, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pJobThread == NULL) {
return;
}
/* The first thing to do is post a quit message to the job queue. If we're using a thread we'll need to wait for it. */
{
ma_job job = ma_job_init(MA_JOB_TYPE_QUIT);
ma_device_job_thread_post(pJobThread, &job);
}
/* Wait for the thread to terminate naturally. */
if (pJobThread->_hasThread) {
ma_thread_wait(&pJobThread->thread);
}
/* At this point the thread should be terminated so we can safely uninitialize the job queue. */
ma_job_queue_uninit(&pJobThread->jobQueue, pAllocationCallbacks);
}
MA_API ma_result ma_device_job_thread_post(ma_device_job_thread* pJobThread, const ma_job* pJob)
{
if (pJobThread == NULL || pJob == NULL) {
return MA_INVALID_ARGS;
}
return ma_job_queue_post(&pJobThread->jobQueue, pJob);
}
MA_API ma_result ma_device_job_thread_next(ma_device_job_thread* pJobThread, ma_job* pJob)
{
if (pJob == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pJob);
if (pJobThread == NULL) {
return MA_INVALID_ARGS;
}
return ma_job_queue_next(&pJobThread->jobQueue, pJob);
}
MA_API ma_context_config ma_context_config_init(void)
{
ma_context_config config;
MA_ZERO_OBJECT(&config);
return config;
}
MA_API ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config* pConfig, ma_context* pContext)
{
ma_result result;
ma_context_config defaultConfig;
ma_backend defaultBackends[ma_backend_null+1];
ma_uint32 iBackend;
ma_backend* pBackendsToIterate;
ma_uint32 backendsToIterateCount;
if (pContext == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pContext);
/* Always make sure the config is set first to ensure properties are available as soon as possible. */
if (pConfig == NULL) {
defaultConfig = ma_context_config_init();
pConfig = &defaultConfig;
}
/* Allocation callbacks need to come first because they'll be passed around to other areas. */
result = ma_allocation_callbacks_init_copy(&pContext->allocationCallbacks, &pConfig->allocationCallbacks);
if (result != MA_SUCCESS) {
return result;
}
/* Get a lot set up first so we can start logging ASAP. */
if (pConfig->pLog != NULL) {
pContext->pLog = pConfig->pLog;
} else {
result = ma_log_init(&pContext->allocationCallbacks, &pContext->log);
if (result == MA_SUCCESS) {
pContext->pLog = &pContext->log;
} else {
pContext->pLog = NULL; /* Logging is not available. */
}
}
pContext->threadPriority = pConfig->threadPriority;
pContext->threadStackSize = pConfig->threadStackSize;
pContext->pUserData = pConfig->pUserData;
/* Backend APIs need to be initialized first. This is where external libraries will be loaded and linked. */
result = ma_context_init_backend_apis(pContext);
if (result != MA_SUCCESS) {
return result;
}
for (iBackend = 0; iBackend <= ma_backend_null; ++iBackend) {
defaultBackends[iBackend] = (ma_backend)iBackend;
}
pBackendsToIterate = (ma_backend*)backends;
backendsToIterateCount = backendCount;
if (pBackendsToIterate == NULL) {
pBackendsToIterate = (ma_backend*)defaultBackends;
backendsToIterateCount = ma_countof(defaultBackends);
}
MA_ASSERT(pBackendsToIterate != NULL);
for (iBackend = 0; iBackend < backendsToIterateCount; iBackend += 1) {
ma_backend backend = pBackendsToIterate[iBackend];
/* Make sure all callbacks are reset so we don't accidentally drag in any from previously failed initialization attempts. */
MA_ZERO_OBJECT(&pContext->callbacks);
/* These backends are using the new callback system. */
switch (backend) {
#ifdef MA_HAS_WASAPI
case ma_backend_wasapi:
{
pContext->callbacks.onContextInit = ma_context_init__wasapi;
} break;
#endif
#ifdef MA_HAS_DSOUND
case ma_backend_dsound:
{
pContext->callbacks.onContextInit = ma_context_init__dsound;
} break;
#endif
#ifdef MA_HAS_WINMM
case ma_backend_winmm:
{
pContext->callbacks.onContextInit = ma_context_init__winmm;
} break;
#endif
#ifdef MA_HAS_COREAUDIO
case ma_backend_coreaudio:
{
pContext->callbacks.onContextInit = ma_context_init__coreaudio;
} break;
#endif
#ifdef MA_HAS_SNDIO
case ma_backend_sndio:
{
pContext->callbacks.onContextInit = ma_context_init__sndio;
} break;
#endif
#ifdef MA_HAS_AUDIO4
case ma_backend_audio4:
{
pContext->callbacks.onContextInit = ma_context_init__audio4;
} break;
#endif
#ifdef MA_HAS_OSS
case ma_backend_oss:
{
pContext->callbacks.onContextInit = ma_context_init__oss;
} break;
#endif
#ifdef MA_HAS_PULSEAUDIO
case ma_backend_pulseaudio:
{
pContext->callbacks.onContextInit = ma_context_init__pulse;
} break;
#endif
#ifdef MA_HAS_ALSA
case ma_backend_alsa:
{
pContext->callbacks.onContextInit = ma_context_init__alsa;
} break;
#endif
#ifdef MA_HAS_JACK
case ma_backend_jack:
{
pContext->callbacks.onContextInit = ma_context_init__jack;
} break;
#endif
#ifdef MA_HAS_AAUDIO
case ma_backend_aaudio:
{
pContext->callbacks.onContextInit = ma_context_init__aaudio;
} break;
#endif
#ifdef MA_HAS_OPENSL
case ma_backend_opensl:
{
pContext->callbacks.onContextInit = ma_context_init__opensl;
} break;
#endif
#ifdef MA_HAS_WEBAUDIO
case ma_backend_webaudio:
{
pContext->callbacks.onContextInit = ma_context_init__webaudio;
} break;
#endif
#ifdef MA_HAS_CUSTOM
case ma_backend_custom:
{
/* Slightly different logic for custom backends. Custom backends can optionally set all of their callbacks in the config. */
pContext->callbacks = pConfig->custom;
} break;
#endif
#ifdef MA_HAS_NULL
case ma_backend_null:
{
pContext->callbacks.onContextInit = ma_context_init__null;
} break;
#endif
default: break;
}
if (pContext->callbacks.onContextInit != NULL) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Attempting to initialize %s backend...\n", ma_get_backend_name(backend));
result = pContext->callbacks.onContextInit(pContext, pConfig, &pContext->callbacks);
} else {
result = MA_NO_BACKEND;
}
/* If this iteration was successful, return. */
if (result == MA_SUCCESS) {
result = ma_mutex_init(&pContext->deviceEnumLock);
if (result != MA_SUCCESS) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_WARNING, "Failed to initialize mutex for device enumeration. ma_context_get_devices() is not thread safe.\n");
}
result = ma_mutex_init(&pContext->deviceInfoLock);
if (result != MA_SUCCESS) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_WARNING, "Failed to initialize mutex for device info retrieval. ma_context_get_device_info() is not thread safe.\n");
}
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "System Architecture:\n");
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " Endian: %s\n", ma_is_little_endian() ? "LE" : "BE");
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " SSE2: %s\n", ma_has_sse2() ? "YES" : "NO");
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " AVX2: %s\n", ma_has_avx2() ? "YES" : "NO");
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, " NEON: %s\n", ma_has_neon() ? "YES" : "NO");
pContext->backend = backend;
return result;
} else {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_DEBUG, "Failed to initialize %s backend.\n", ma_get_backend_name(backend));
}
}
/* If we get here it means an error occurred. */
MA_ZERO_OBJECT(pContext); /* Safety. */
return MA_NO_BACKEND;
}
MA_API ma_result ma_context_uninit(ma_context* pContext)
{
if (pContext == NULL) {
return MA_INVALID_ARGS;
}
if (pContext->callbacks.onContextUninit != NULL) {
pContext->callbacks.onContextUninit(pContext);
}
ma_mutex_uninit(&pContext->deviceEnumLock);
ma_mutex_uninit(&pContext->deviceInfoLock);
ma_free(pContext->pDeviceInfos, &pContext->allocationCallbacks);
ma_context_uninit_backend_apis(pContext);
if (pContext->pLog == &pContext->log) {
ma_log_uninit(&pContext->log);
}
return MA_SUCCESS;
}
MA_API size_t ma_context_sizeof()
{
return sizeof(ma_context);
}
MA_API ma_log* ma_context_get_log(ma_context* pContext)
{
if (pContext == NULL) {
return NULL;
}
return pContext->pLog;
}
MA_API ma_result ma_context_enumerate_devices(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
{
ma_result result;
if (pContext == NULL || callback == NULL) {
return MA_INVALID_ARGS;
}
if (pContext->callbacks.onContextEnumerateDevices == NULL) {
return MA_INVALID_OPERATION;
}
ma_mutex_lock(&pContext->deviceEnumLock);
{
result = pContext->callbacks.onContextEnumerateDevices(pContext, callback, pUserData);
}
ma_mutex_unlock(&pContext->deviceEnumLock);
return result;
}
static ma_bool32 ma_context_get_devices__enum_callback(ma_context* pContext, ma_device_type deviceType, const ma_device_info* pInfo, void* pUserData)
{
/*
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
it's just appended to the end. If it's a playback device it's inserted just before the first capture device.
*/
/*
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
simple fixed size increment for buffer expansion.
*/
const ma_uint32 bufferExpansionCount = 2;
const ma_uint32 totalDeviceInfoCount = pContext->playbackDeviceInfoCount + pContext->captureDeviceInfoCount;
if (totalDeviceInfoCount >= pContext->deviceInfoCapacity) {
ma_uint32 newCapacity = pContext->deviceInfoCapacity + bufferExpansionCount;
ma_device_info* pNewInfos = (ma_device_info*)ma_realloc(pContext->pDeviceInfos, sizeof(*pContext->pDeviceInfos)*newCapacity, &pContext->allocationCallbacks);
if (pNewInfos == NULL) {
return MA_FALSE; /* Out of memory. */
}
pContext->pDeviceInfos = pNewInfos;
pContext->deviceInfoCapacity = newCapacity;
}
if (deviceType == ma_device_type_playback) {
/* Playback. Insert just before the first capture device. */
/* The first thing to do is move all of the capture devices down a slot. */
ma_uint32 iFirstCaptureDevice = pContext->playbackDeviceInfoCount;
size_t iCaptureDevice;
for (iCaptureDevice = totalDeviceInfoCount; iCaptureDevice > iFirstCaptureDevice; --iCaptureDevice) {
pContext->pDeviceInfos[iCaptureDevice] = pContext->pDeviceInfos[iCaptureDevice-1];
}
/* Now just insert where the first capture device was before moving it down a slot. */
pContext->pDeviceInfos[iFirstCaptureDevice] = *pInfo;
pContext->playbackDeviceInfoCount += 1;
} else {
/* Capture. Insert at the end. */
pContext->pDeviceInfos[totalDeviceInfoCount] = *pInfo;
pContext->captureDeviceInfoCount += 1;
}
(void)pUserData;
return MA_TRUE;
}
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)
{
ma_result result;
/* Safety. */
if (ppPlaybackDeviceInfos != NULL) *ppPlaybackDeviceInfos = NULL;
if (pPlaybackDeviceCount != NULL) *pPlaybackDeviceCount = 0;
if (ppCaptureDeviceInfos != NULL) *ppCaptureDeviceInfos = NULL;
if (pCaptureDeviceCount != NULL) *pCaptureDeviceCount = 0;
if (pContext == NULL) {
return MA_INVALID_ARGS;
}
if (pContext->callbacks.onContextEnumerateDevices == NULL) {
return MA_INVALID_OPERATION;
}
/* Note that we don't use ma_context_enumerate_devices() here because we want to do locking at a higher level. */
ma_mutex_lock(&pContext->deviceEnumLock);
{
/* Reset everything first. */
pContext->playbackDeviceInfoCount = 0;
pContext->captureDeviceInfoCount = 0;
/* Now enumerate over available devices. */
result = pContext->callbacks.onContextEnumerateDevices(pContext, ma_context_get_devices__enum_callback, NULL);
if (result == MA_SUCCESS) {
/* Playback devices. */
if (ppPlaybackDeviceInfos != NULL) {
*ppPlaybackDeviceInfos = pContext->pDeviceInfos;
}
if (pPlaybackDeviceCount != NULL) {
*pPlaybackDeviceCount = pContext->playbackDeviceInfoCount;
}
/* Capture devices. */
if (ppCaptureDeviceInfos != NULL) {
*ppCaptureDeviceInfos = pContext->pDeviceInfos + pContext->playbackDeviceInfoCount; /* Capture devices come after playback devices. */
}
if (pCaptureDeviceCount != NULL) {
*pCaptureDeviceCount = pContext->captureDeviceInfoCount;
}
}
}
ma_mutex_unlock(&pContext->deviceEnumLock);
return result;
}
MA_API ma_result ma_context_get_device_info(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
{
ma_result result;
ma_device_info deviceInfo;
/* NOTE: Do not clear pDeviceInfo on entry. The reason is the pDeviceID may actually point to pDeviceInfo->id which will break things. */
if (pContext == NULL || pDeviceInfo == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(&deviceInfo);
/* Help the backend out by copying over the device ID if we have one. */
if (pDeviceID != NULL) {
MA_COPY_MEMORY(&deviceInfo.id, pDeviceID, sizeof(*pDeviceID));
}
if (pContext->callbacks.onContextGetDeviceInfo == NULL) {
return MA_INVALID_OPERATION;
}
ma_mutex_lock(&pContext->deviceInfoLock);
{
result = pContext->callbacks.onContextGetDeviceInfo(pContext, deviceType, pDeviceID, &deviceInfo);
}
ma_mutex_unlock(&pContext->deviceInfoLock);
*pDeviceInfo = deviceInfo;
return result;
}
MA_API ma_bool32 ma_context_is_loopback_supported(ma_context* pContext)
{
if (pContext == NULL) {
return MA_FALSE;
}
return ma_is_loopback_supported(pContext->backend);
}
MA_API ma_device_config ma_device_config_init(ma_device_type deviceType)
{
ma_device_config config;
MA_ZERO_OBJECT(&config);
config.deviceType = deviceType;
config.resampling = ma_resampler_config_init(ma_format_unknown, 0, 0, 0, ma_resample_algorithm_linear); /* Format/channels/rate don't matter here. */
return config;
}
MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice)
{
ma_result result;
ma_device_descriptor descriptorPlayback;
ma_device_descriptor descriptorCapture;
/* The context can be null, in which case we self-manage it. */
if (pContext == NULL) {
return ma_device_init_ex(NULL, 0, NULL, pConfig, pDevice);
}
if (pDevice == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDevice);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
/* Check that we have our callbacks defined. */
if (pContext->callbacks.onDeviceInit == NULL) {
return MA_INVALID_OPERATION;
}
/* Basic config validation. */
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
if (pConfig->capture.channels > MA_MAX_CHANNELS) {
return MA_INVALID_ARGS;
}
if (!ma__is_channel_map_valid(pConfig->capture.pChannelMap, pConfig->capture.channels)) {
return MA_INVALID_ARGS;
}
}
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex || pConfig->deviceType == ma_device_type_loopback) {
if (pConfig->playback.channels > MA_MAX_CHANNELS) {
return MA_INVALID_ARGS;
}
if (!ma__is_channel_map_valid(pConfig->playback.pChannelMap, pConfig->playback.channels)) {
return MA_INVALID_ARGS;
}
}
pDevice->pContext = pContext;
/* Set the user data and log callback ASAP to ensure it is available for the entire initialization process. */
pDevice->pUserData = pConfig->pUserData;
pDevice->onData = pConfig->dataCallback;
pDevice->onNotification = pConfig->notificationCallback;
pDevice->onStop = pConfig->stopCallback;
if (pConfig->playback.pDeviceID != NULL) {
MA_COPY_MEMORY(&pDevice->playback.id, pConfig->playback.pDeviceID, sizeof(pDevice->playback.id));
pDevice->playback.pID = &pDevice->playback.id;
} else {
pDevice->playback.pID = NULL;
}
if (pConfig->capture.pDeviceID != NULL) {
MA_COPY_MEMORY(&pDevice->capture.id, pConfig->capture.pDeviceID, sizeof(pDevice->capture.id));
pDevice->capture.pID = &pDevice->capture.id;
} else {
pDevice->capture.pID = NULL;
}
pDevice->noPreSilencedOutputBuffer = pConfig->noPreSilencedOutputBuffer;
pDevice->noClip = pConfig->noClip;
pDevice->noDisableDenormals = pConfig->noDisableDenormals;
pDevice->noFixedSizedCallback = pConfig->noFixedSizedCallback;
pDevice->masterVolumeFactor = 1;
pDevice->type = pConfig->deviceType;
pDevice->sampleRate = pConfig->sampleRate;
pDevice->resampling.algorithm = pConfig->resampling.algorithm;
pDevice->resampling.linear.lpfOrder = pConfig->resampling.linear.lpfOrder;
pDevice->resampling.pBackendVTable = pConfig->resampling.pBackendVTable;
pDevice->resampling.pBackendUserData = pConfig->resampling.pBackendUserData;
pDevice->capture.shareMode = pConfig->capture.shareMode;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
When the device is started, the worker thread is the one that does the actual startup of the backend device. We
use a semaphore to wait for the background thread to finish the work. The same applies for stopping the device.
Each of these semaphores is released internally by the worker thread when the work is completed. The start
semaphore is also used to wake up the worker thread.
*/
result = ma_event_init(&pDevice->wakeupEvent);
if (result != MA_SUCCESS) {
ma_mutex_uninit(&pDevice->startStopLock);
return result;
}
result = ma_event_init(&pDevice->startEvent);
if (result != MA_SUCCESS) {
ma_event_uninit(&pDevice->wakeupEvent);
ma_mutex_uninit(&pDevice->startStopLock);
return result;
}
result = ma_event_init(&pDevice->stopEvent);
if (result != MA_SUCCESS) {
ma_event_uninit(&pDevice->startEvent);
ma_event_uninit(&pDevice->wakeupEvent);
ma_mutex_uninit(&pDevice->startStopLock);
return result;
}
MA_ZERO_OBJECT(&descriptorPlayback);
descriptorPlayback.pDeviceID = pConfig->playback.pDeviceID;
descriptorPlayback.shareMode = pConfig->playback.shareMode;
descriptorPlayback.format = pConfig->playback.format;
descriptorPlayback.channels = pConfig->playback.channels;
descriptorPlayback.sampleRate = pConfig->sampleRate;
ma_channel_map_copy_or_default(descriptorPlayback.channelMap, ma_countof(descriptorPlayback.channelMap), pConfig->playback.pChannelMap, pConfig->playback.channels);
descriptorPlayback.periodSizeInFrames = pConfig->periodSizeInFrames;
descriptorPlayback.periodSizeInMilliseconds = pConfig->periodSizeInMilliseconds;
descriptorPlayback.periodCount = pConfig->periods;
if (descriptorPlayback.periodCount == 0) {
descriptorPlayback.periodCount = MA_DEFAULT_PERIODS;
}
MA_ZERO_OBJECT(&descriptorCapture);
descriptorCapture.pDeviceID = pConfig->capture.pDeviceID;
descriptorCapture.shareMode = pConfig->capture.shareMode;
descriptorCapture.format = pConfig->capture.format;
descriptorCapture.channels = pConfig->capture.channels;
descriptorCapture.sampleRate = pConfig->sampleRate;
ma_channel_map_copy_or_default(descriptorCapture.channelMap, ma_countof(descriptorCapture.channelMap), pConfig->capture.pChannelMap, pConfig->capture.channels);
descriptorCapture.periodSizeInFrames = pConfig->periodSizeInFrames;
descriptorCapture.periodSizeInMilliseconds = pConfig->periodSizeInMilliseconds;
descriptorCapture.periodCount = pConfig->periods;
if (descriptorCapture.periodCount == 0) {
descriptorCapture.periodCount = MA_DEFAULT_PERIODS;
}
result = pContext->callbacks.onDeviceInit(pDevice, pConfig, &descriptorPlayback, &descriptorCapture);
if (result != MA_SUCCESS) {
ma_event_uninit(&pDevice->startEvent);
ma_event_uninit(&pDevice->wakeupEvent);
ma_mutex_uninit(&pDevice->startStopLock);
return result;
}
#if 0
/*
On output the descriptors will contain the *actual* data format of the device. We need this to know how to convert the data between
the requested format and the internal format.
*/
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex || pConfig->deviceType == ma_device_type_loopback) {
if (!ma_device_descriptor_is_valid(&descriptorCapture)) {
ma_device_uninit(pDevice);
return MA_INVALID_ARGS;
}
pDevice->capture.internalFormat = descriptorCapture.format;
pDevice->capture.internalChannels = descriptorCapture.channels;
pDevice->capture.internalSampleRate = descriptorCapture.sampleRate;
ma_channel_map_copy(pDevice->capture.internalChannelMap, descriptorCapture.channelMap, descriptorCapture.channels);
pDevice->capture.internalPeriodSizeInFrames = descriptorCapture.periodSizeInFrames;
pDevice->capture.internalPeriods = descriptorCapture.periodCount;
if (pDevice->capture.internalPeriodSizeInFrames == 0) {
pDevice->capture.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(descriptorCapture.periodSizeInMilliseconds, descriptorCapture.sampleRate);
}
}
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
if (!ma_device_descriptor_is_valid(&descriptorPlayback)) {
ma_device_uninit(pDevice);
return MA_INVALID_ARGS;
}
pDevice->playback.internalFormat = descriptorPlayback.format;
pDevice->playback.internalChannels = descriptorPlayback.channels;
pDevice->playback.internalSampleRate = descriptorPlayback.sampleRate;
ma_channel_map_copy(pDevice->playback.internalChannelMap, descriptorPlayback.channelMap, descriptorPlayback.channels);
pDevice->playback.internalPeriodSizeInFrames = descriptorPlayback.periodSizeInFrames;
pDevice->playback.internalPeriods = descriptorPlayback.periodCount;
if (pDevice->playback.internalPeriodSizeInFrames == 0) {
pDevice->playback.internalPeriodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(descriptorPlayback.periodSizeInMilliseconds, descriptorPlayback.sampleRate);
}
}
/*
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.
For loopback devices, we need to retrieve the name of the playback device.
*/
{
ma_device_info deviceInfo;
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex || pConfig->deviceType == ma_device_type_loopback) {
result = ma_device_get_info(pDevice, (pConfig->deviceType == ma_device_type_loopback) ? ma_device_type_playback : ma_device_type_capture, &deviceInfo);
if (result == MA_SUCCESS) {
ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), deviceInfo.name, (size_t)-1);
} else {
/* We failed to retrieve the device info. Fall back to a default name. */
if (descriptorCapture.pDeviceID == NULL) {
ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
} else {
ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), "Capture Device", (size_t)-1);
}
}
}
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
result = ma_device_get_info(pDevice, ma_device_type_playback, &deviceInfo);
if (result == MA_SUCCESS) {
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), deviceInfo.name, (size_t)-1);
} else {
/* We failed to retrieve the device info. Fall back to a default name. */
if (descriptorPlayback.pDeviceID == NULL) {
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
} else {
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), "Playback Device", (size_t)-1);
}
}
}
}
ma_device__post_init_setup(pDevice, pConfig->deviceType);
#endif
result = ma_device_post_init(pDevice, pConfig->deviceType, &descriptorPlayback, &descriptorCapture);
if (result != MA_SUCCESS) {
ma_device_uninit(pDevice);
return result;
}
/*
If we're using fixed sized callbacks we'll need to make use of an intermediary buffer. Needs to
be done after post_init_setup() because we'll need access to the sample rate.
*/
if (pConfig->noFixedSizedCallback == MA_FALSE) {
/* We're using a fixed sized data callback so we'll need an intermediary buffer. */
ma_uint32 intermediaryBufferCap = pConfig->periodSizeInFrames;
if (intermediaryBufferCap == 0) {
intermediaryBufferCap = ma_calculate_buffer_size_in_frames_from_milliseconds(pConfig->periodSizeInMilliseconds, pDevice->sampleRate);
}
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex || pConfig->deviceType == ma_device_type_loopback) {
ma_uint32 intermediaryBufferSizeInBytes;
pDevice->capture.intermediaryBufferLen = 0;
pDevice->capture.intermediaryBufferCap = intermediaryBufferCap;
if (pDevice->capture.intermediaryBufferCap == 0) {
pDevice->capture.intermediaryBufferCap = pDevice->capture.internalPeriodSizeInFrames;
}
intermediaryBufferSizeInBytes = pDevice->capture.intermediaryBufferCap * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
pDevice->capture.pIntermediaryBuffer = ma_malloc((size_t)intermediaryBufferSizeInBytes, &pContext->allocationCallbacks);
if (pDevice->capture.pIntermediaryBuffer == NULL) {
ma_device_uninit(pDevice);
return MA_OUT_OF_MEMORY;
}
/* Silence the buffer for safety. */
ma_silence_pcm_frames(pDevice->capture.pIntermediaryBuffer, pDevice->capture.intermediaryBufferCap, pDevice->capture.format, pDevice->capture.channels);
pDevice->capture.intermediaryBufferLen = pDevice->capture.intermediaryBufferCap;
}
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
ma_uint64 intermediaryBufferSizeInBytes;
pDevice->playback.intermediaryBufferLen = 0;
if (pConfig->deviceType == ma_device_type_duplex) {
pDevice->playback.intermediaryBufferCap = pDevice->capture.intermediaryBufferCap; /* In duplex mode, make sure the intermediary buffer is always the same size as the capture side. */
} else {
pDevice->playback.intermediaryBufferCap = intermediaryBufferCap;
if (pDevice->playback.intermediaryBufferCap == 0) {
pDevice->playback.intermediaryBufferCap = pDevice->playback.internalPeriodSizeInFrames;
}
}
intermediaryBufferSizeInBytes = pDevice->playback.intermediaryBufferCap * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
pDevice->playback.pIntermediaryBuffer = ma_malloc((size_t)intermediaryBufferSizeInBytes, &pContext->allocationCallbacks);
if (pDevice->playback.pIntermediaryBuffer == NULL) {
ma_device_uninit(pDevice);
return MA_OUT_OF_MEMORY;
}
/* Silence the buffer for safety. */
ma_silence_pcm_frames(pDevice->playback.pIntermediaryBuffer, pDevice->playback.intermediaryBufferCap, pDevice->playback.format, pDevice->playback.channels);
pDevice->playback.intermediaryBufferLen = 0;
}
} else {
/* Not using a fixed sized data callback so no need for an intermediary buffer. */
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
result = ma_duplex_rb_init(pDevice->capture.format, pDevice->capture.channels, pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalPeriodSizeInFrames, &pDevice->pContext->allocationCallbacks, &pDevice->d...
if (result != MA_SUCCESS) {
ma_device_uninit(pDevice);
return result;
}
}
}
ma_device__set_state(pDevice, ma_device_state_stopped);
}
/* Log device information. */
{
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[%s]\n", ma_get_backend_name(pDevice->pContext->backend));
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
char name[MA_MAX_DEVICE_NAME_LENGTH + 1];
ma_device_get_name(pDevice, ma_device_type_capture, name, sizeof(name), NULL);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " %s (%s)\n", name, "Capture");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Format: %s -> %s\n", ma_get_format_name(pDevice->capture.internalFormat), ma_get_format_name(pDevice->capture.format));
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channels: %d -> %d\n", pDevice->capture.internalChannels, pDevice->capture.channels);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Sample Rate: %d -> %d\n", pDevice->capture.internalSampleRate, pDevice->sampleRate);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Buffer Size: %d*%d (%d)\n", pDevice->capture.internalPeriodSizeInFrames, pDevice->capture.internalPeriods, (pDevice->capture.internalPeriodSizeInFrames * pDevice->capture.in...
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Conversion:\n");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Pre Format Conversion: %s\n", pDevice->capture.converter.hasPreFormatConversion ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Post Format Conversion: %s\n", pDevice->capture.converter.hasPostFormatConversion ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Routing: %s\n", pDevice->capture.converter.hasChannelConverter ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s\n", pDevice->capture.converter.hasResampler ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s\n", pDevice->capture.converter.isPassthrough ? "YES" : "NO");
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
char name[MA_MAX_DEVICE_NAME_LENGTH + 1];
ma_device_get_name(pDevice, ma_device_type_playback, name, sizeof(name), NULL);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " %s (%s)\n", name, "Playback");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Format: %s -> %s\n", ma_get_format_name(pDevice->playback.format), ma_get_format_name(pDevice->playback.internalFormat));
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channels: %d -> %d\n", pDevice->playback.channels, pDevice->playback.internalChannels);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->playback.internalSampleRate);
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Buffer Size: %d*%d (%d)\n", pDevice->playback.internalPeriodSizeInFrames, pDevice->playback.internalPeriods, (pDevice->playback.internalPeriodSizeInFrames * pDevice->playbac...
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Conversion:\n");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Pre Format Conversion: %s\n", pDevice->playback.converter.hasPreFormatConversion ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Post Format Conversion: %s\n", pDevice->playback.converter.hasPostFormatConversion ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Channel Routing: %s\n", pDevice->playback.converter.hasChannelConverter ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Resampling: %s\n", pDevice->playback.converter.hasResampler ? "YES" : "NO");
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, " Passthrough: %s\n", pDevice->playback.converter.isPassthrough ? "YES" : "NO");
}
}
MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_stopped);
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_context* pContext;
ma_backend defaultBackends[ma_backend_null+1];
ma_uint32 iBackend;
ma_backend* pBackendsToIterate;
ma_uint32 backendsToIterateCount;
ma_allocation_callbacks allocationCallbacks;
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pContextConfig != NULL) {
result = ma_allocation_callbacks_init_copy(&allocationCallbacks, &pContextConfig->allocationCallbacks);
if (result != MA_SUCCESS) {
return result;
}
} else {
allocationCallbacks = ma_allocation_callbacks_init_default();
}
pContext = (ma_context*)ma_malloc(sizeof(*pContext), &allocationCallbacks);
if (pContext == NULL) {
return MA_OUT_OF_MEMORY;
}
for (iBackend = 0; iBackend <= ma_backend_null; ++iBackend) {
defaultBackends[iBackend] = (ma_backend)iBackend;
}
pBackendsToIterate = (ma_backend*)backends;
backendsToIterateCount = backendCount;
if (pBackendsToIterate == NULL) {
pBackendsToIterate = (ma_backend*)defaultBackends;
backendsToIterateCount = ma_countof(defaultBackends);
}
result = MA_NO_BACKEND;
for (iBackend = 0; iBackend < backendsToIterateCount; ++iBackend) {
result = ma_context_init(&pBackendsToIterate[iBackend], 1, pContextConfig, pContext);
if (result == MA_SUCCESS) {
result = ma_device_init(pContext, pConfig, pDevice);
if (result == MA_SUCCESS) {
break; /* Success. */
} else {
ma_context_uninit(pContext); /* Failure. */
}
}
}
if (result != MA_SUCCESS) {
ma_free(pContext, &allocationCallbacks);
return result;
}
pDevice->isOwnerOfContext = MA_TRUE;
return result;
}
MA_API void ma_device_uninit(ma_device* pDevice)
{
if (!ma_device__is_initialized(pDevice)) {
return;
}
/* 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. */
if (ma_device_is_started(pDevice)) {
ma_device_stop(pDevice);
}
/* Putting the device into an uninitialized state will make the worker thread return. */
ma_device__set_state(pDevice, ma_device_state_uninitialized);
/* Wake up the worker thread and wait for it to properly terminate. */
if (!ma_context_is_backend_asynchronous(pDevice->pContext)) {
ma_event_signal(&pDevice->wakeupEvent);
ma_thread_wait(&pDevice->thread);
}
if (pDevice->pContext->callbacks.onDeviceUninit != NULL) {
pDevice->pContext->callbacks.onDeviceUninit(pDevice);
}
ma_event_uninit(&pDevice->stopEvent);
ma_event_uninit(&pDevice->startEvent);
ma_event_uninit(&pDevice->wakeupEvent);
ma_mutex_uninit(&pDevice->startStopLock);
if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
if (pDevice->type == ma_device_type_duplex) {
ma_duplex_rb_uninit(&pDevice->duplexRB);
}
}
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
ma_data_converter_uninit(&pDevice->capture.converter, &pDevice->pContext->allocationCallbacks);
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
ma_data_converter_uninit(&pDevice->playback.converter, &pDevice->pContext->allocationCallbacks);
}
if (pDevice->playback.pInputCache != NULL) {
ma_free(pDevice->playback.pInputCache, &pDevice->pContext->allocationCallbacks);
}
if (pDevice->capture.pIntermediaryBuffer != NULL) {
ma_free(pDevice->capture.pIntermediaryBuffer, &pDevice->pContext->allocationCallbacks);
}
if (pDevice->playback.pIntermediaryBuffer != NULL) {
ma_free(pDevice->playback.pIntermediaryBuffer, &pDevice->pContext->allocationCallbacks);
}
if (pDevice->isOwnerOfContext) {
ma_allocation_callbacks allocationCallbacks = pDevice->pContext->allocationCallbacks;
ma_context_uninit(pDevice->pContext);
ma_free(pDevice->pContext, &allocationCallbacks);
}
MA_ZERO_OBJECT(pDevice);
}
MA_API ma_context* ma_device_get_context(ma_device* pDevice)
{
if (pDevice == NULL) {
return NULL;
}
return pDevice->pContext;
}
MA_API ma_log* ma_device_get_log(ma_device* pDevice)
{
return ma_context_get_log(ma_device_get_context(pDevice));
}
MA_API ma_result ma_device_get_info(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo)
{
if (pDeviceInfo == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDeviceInfo);
if (pDevice == NULL) {
return MA_INVALID_ARGS;
}
/* If the onDeviceGetInfo() callback is set, use that. Otherwise we'll fall back to ma_context_get_device_info(). */
if (pDevice->pContext->callbacks.onDeviceGetInfo != NULL) {
return pDevice->pContext->callbacks.onDeviceGetInfo(pDevice, type, pDeviceInfo);
}
/* Getting here means onDeviceGetInfo is not implemented so we need to fall back to an alternative. */
if (type == ma_device_type_playback) {
return ma_context_get_device_info(pDevice->pContext, type, pDevice->playback.pID, pDeviceInfo);
} else {
return ma_context_get_device_info(pDevice->pContext, type, pDevice->capture.pID, pDeviceInfo);
}
}
MA_API ma_result ma_device_get_name(ma_device* pDevice, ma_device_type type, char* pName, size_t nameCap, size_t* pLengthNotIncludingNullTerminator)
{
ma_result result;
ma_device_info deviceInfo;
if (pLengthNotIncludingNullTerminator != NULL) {
*pLengthNotIncludingNullTerminator = 0;
}
if (pName != NULL && nameCap > 0) {
pName[0] = '\0';
}
result = ma_device_get_info(pDevice, type, &deviceInfo);
if (result != MA_SUCCESS) {
return result;
}
if (pName != NULL) {
ma_strncpy_s(pName, nameCap, deviceInfo.name, (size_t)-1);
/*
For safety, make sure the length is based on the truncated output string rather than the
source. Otherwise the caller might assume the output buffer contains more content than it
actually does.
*/
if (pLengthNotIncludingNullTerminator != NULL) {
*pLengthNotIncludingNullTerminator = strlen(pName);
}
} else {
/* Name not specified. Just report the length of the source string. */
if (pLengthNotIncludingNullTerminator != NULL) {
*pLengthNotIncludingNullTerminator = strlen(deviceInfo.name);
}
}
return MA_SUCCESS;
}
MA_API ma_result ma_device_start(ma_device* pDevice)
{
ma_result result;
if (pDevice == NULL) {
return MA_INVALID_ARGS;
}
if (ma_device_get_state(pDevice) == ma_device_state_uninitialized) {
return MA_INVALID_OPERATION; /* Not initialized. */
}
if (ma_device_get_state(pDevice) == ma_device_state_started) {
return MA_SUCCESS; /* Already started. */
}
ma_mutex_lock(&pDevice->startStopLock);
{
/* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_stopped);
ma_device__set_state(pDevice, ma_device_state_starting);
/* Asynchronous backends need to be handled differently. */
if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
if (pDevice->pContext->callbacks.onDeviceStart != NULL) {
result = pDevice->pContext->callbacks.onDeviceStart(pDevice);
} else {
result = MA_INVALID_OPERATION;
}
if (result == MA_SUCCESS) {
ma_device__set_state(pDevice, ma_device_state_started);
ma_device__on_notification_started(pDevice);
}
} else {
/*
Synchronous backends are started by signaling an event that's being waited on in the worker thread. We first wake up the
thread and then wait for the start event.
*/
ma_event_signal(&pDevice->wakeupEvent);
/*
Wait for the worker thread to finish starting the device. Note that the worker thread will be the one who puts the device
into the started state. Don't call ma_device__set_state() here.
*/
ma_event_wait(&pDevice->startEvent);
result = pDevice->workResult;
}
/* We changed the state from stopped to started, so if we failed, make sure we put the state back to stopped. */
if (result != MA_SUCCESS) {
ma_device__set_state(pDevice, ma_device_state_stopped);
}
}
ma_mutex_unlock(&pDevice->startStopLock);
return result;
}
MA_API ma_result ma_device_stop(ma_device* pDevice)
{
ma_result result;
if (pDevice == NULL) {
return MA_INVALID_ARGS;
}
if (ma_device_get_state(pDevice) == ma_device_state_uninitialized) {
return MA_INVALID_OPERATION; /* Not initialized. */
}
if (ma_device_get_state(pDevice) == ma_device_state_stopped) {
return MA_SUCCESS; /* Already stopped. */
}
ma_mutex_lock(&pDevice->startStopLock);
{
/* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a started or paused state. */
MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_started);
ma_device__set_state(pDevice, ma_device_state_stopping);
/* Asynchronous backends need to be handled differently. */
if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
/* Asynchronous backends must have a stop operation. */
if (pDevice->pContext->callbacks.onDeviceStop != NULL) {
result = pDevice->pContext->callbacks.onDeviceStop(pDevice);
} else {
result = MA_INVALID_OPERATION;
}
ma_device__set_state(pDevice, ma_device_state_stopped);
} else {
/*
Synchronous backends. The stop callback is always called from the worker thread. Do not call the stop callback here. If
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
sure the state of the device is *not* playing right now, which it shouldn't be since we set it above. This is super
important though, so I'm asserting it here as well for extra safety in case we accidentally change something later.
*/
MA_ASSERT(ma_device_get_state(pDevice) != ma_device_state_started);
if (pDevice->pContext->callbacks.onDeviceDataLoopWakeup != NULL) {
pDevice->pContext->callbacks.onDeviceDataLoopWakeup(pDevice);
}
/*
We need to wait for the worker thread to become available for work before returning. Note that the worker thread will be
the one who puts the device into the stopped state. Don't call ma_device__set_state() here.
*/
ma_event_wait(&pDevice->stopEvent);
result = MA_SUCCESS;
}
}
ma_mutex_unlock(&pDevice->startStopLock);
return result;
}
MA_API ma_bool32 ma_device_is_started(const ma_device* pDevice)
{
return ma_device_get_state(pDevice) == ma_device_state_started;
}
MA_API ma_device_state ma_device_get_state(const ma_device* pDevice)
{
if (pDevice == NULL) {
return ma_device_state_uninitialized;
}
return (ma_device_state)c89atomic_load_i32((ma_int32*)&pDevice->state); /* Naughty cast to get rid of a const warning. */
}
MA_API ma_result ma_device_set_master_volume(ma_device* pDevice, float volume)
{
if (pDevice == NULL) {
return MA_INVALID_ARGS;
}
if (volume < 0.0f) {
return MA_INVALID_ARGS;
}
c89atomic_exchange_f32(&pDevice->masterVolumeFactor, volume);
return MA_SUCCESS;
}
MA_API ma_result ma_device_get_master_volume(ma_device* pDevice, float* pVolume)
{
if (pVolume == NULL) {
return MA_INVALID_ARGS;
}
if (pDevice == NULL) {
*pVolume = 0;
return MA_INVALID_ARGS;
}
*pVolume = c89atomic_load_f32(&pDevice->masterVolumeFactor);
return MA_SUCCESS;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
/* R0 */
pHeapLayout->r1Offset = pHeapLayout->sizeInBytes;
pHeapLayout->sizeInBytes += sizeof(ma_biquad_coefficient) * pConfig->channels;
/* R1 */
pHeapLayout->r2Offset = pHeapLayout->sizeInBytes;
pHeapLayout->sizeInBytes += sizeof(ma_biquad_coefficient) * pConfig->channels;
/* Make sure allocation size is aligned. */
pHeapLayout->sizeInBytes = ma_align_64(pHeapLayout->sizeInBytes);
return MA_SUCCESS;
}
MA_API ma_result ma_biquad_get_heap_size(const ma_biquad_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_biquad_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_biquad_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_biquad_init_preallocated(const ma_biquad_config* pConfig, void* pHeap, ma_biquad* pBQ)
{
ma_result result;
ma_biquad_heap_layout heapLayout;
if (pBQ == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pBQ);
result = ma_biquad_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pBQ->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pBQ->pR1 = (ma_biquad_coefficient*)ma_offset_ptr(pHeap, heapLayout.r1Offset);
pBQ->pR2 = (ma_biquad_coefficient*)ma_offset_ptr(pHeap, heapLayout.r2Offset);
return ma_biquad_reinit(pConfig, pBQ);
}
MA_API ma_result ma_biquad_init(const ma_biquad_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad* pBQ)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_biquad_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_biquad_init_preallocated(pConfig, pHeap, pBQ);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pBQ->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_biquad_uninit(ma_biquad* pBQ, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pBQ == NULL) {
return;
}
if (pBQ->_ownsHeap) {
ma_free(pBQ->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_biquad_reinit(const ma_biquad_config* pConfig, ma_biquad* pBQ)
{
if (pBQ == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->a0 == 0) {
return MA_INVALID_ARGS; /* Division by zero. */
}
/* Only supporting f32 and s16. */
if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
return MA_INVALID_ARGS;
}
/* The format cannot be changed after initialization. */
if (pBQ->format != ma_format_unknown && pBQ->format != pConfig->format) {
return MA_INVALID_OPERATION;
}
/* The channel count cannot be changed after initialization. */
if (pBQ->channels != 0 && pBQ->channels != pConfig->channels) {
return MA_INVALID_OPERATION;
}
pBQ->format = pConfig->format;
pBQ->channels = pConfig->channels;
/* Normalize. */
if (pConfig->format == ma_format_f32) {
pBQ->b0.f32 = (float)(pConfig->b0 / pConfig->a0);
pBQ->b1.f32 = (float)(pConfig->b1 / pConfig->a0);
pBQ->b2.f32 = (float)(pConfig->b2 / pConfig->a0);
pBQ->a1.f32 = (float)(pConfig->a1 / pConfig->a0);
pBQ->a2.f32 = (float)(pConfig->a2 / pConfig->a0);
} else {
pBQ->b0.s32 = ma_biquad_float_to_fp(pConfig->b0 / pConfig->a0);
pBQ->b1.s32 = ma_biquad_float_to_fp(pConfig->b1 / pConfig->a0);
pBQ->b2.s32 = ma_biquad_float_to_fp(pConfig->b2 / pConfig->a0);
pBQ->a1.s32 = ma_biquad_float_to_fp(pConfig->a1 / pConfig->a0);
pBQ->a2.s32 = ma_biquad_float_to_fp(pConfig->a2 / pConfig->a0);
}
return MA_SUCCESS;
}
MA_API ma_result ma_biquad_clear_cache(ma_biquad* pBQ)
{
if (pBQ == NULL) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (pConfig->channels == 0) {
return MA_INVALID_ARGS;
}
pHeapLayout->sizeInBytes = 0;
/* R1 */
pHeapLayout->r1Offset = pHeapLayout->sizeInBytes;
pHeapLayout->sizeInBytes += sizeof(ma_biquad_coefficient) * pConfig->channels;
/* Make sure allocation size is aligned. */
pHeapLayout->sizeInBytes = ma_align_64(pHeapLayout->sizeInBytes);
return MA_SUCCESS;
}
MA_API ma_result ma_lpf1_get_heap_size(const ma_lpf1_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_lpf1_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
result = ma_lpf1_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_lpf1_init_preallocated(const ma_lpf1_config* pConfig, void* pHeap, ma_lpf1* pLPF)
{
ma_result result;
ma_lpf1_heap_layout heapLayout;
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pLPF);
result = ma_lpf1_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pLPF->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pLPF->pR1 = (ma_biquad_coefficient*)ma_offset_ptr(pHeap, heapLayout.r1Offset);
return ma_lpf1_reinit(pConfig, pLPF);
}
MA_API ma_result ma_lpf1_init(const ma_lpf1_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf1* pLPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_lpf1_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_lpf1_init_preallocated(pConfig, pHeap, pLPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pLPF->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_lpf1_uninit(ma_lpf1* pLPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pLPF == NULL) {
return;
}
if (pLPF->_ownsHeap) {
ma_free(pLPF->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_lpf1_reinit(const ma_lpf1_config* pConfig, ma_lpf1* pLPF)
{
double a;
if (pLPF == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
/* Only supporting f32 and s16. */
if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
return MA_INVALID_ARGS;
}
/* The format cannot be changed after initialization. */
if (pLPF->format != ma_format_unknown && pLPF->format != pConfig->format) {
return MA_INVALID_OPERATION;
}
/* The channel count cannot be changed after initialization. */
if (pLPF->channels != 0 && pLPF->channels != pConfig->channels) {
return MA_INVALID_OPERATION;
}
pLPF->format = pConfig->format;
pLPF->channels = pConfig->channels;
a = ma_expd(-2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate);
if (pConfig->format == ma_format_f32) {
pLPF->a.f32 = (float)a;
} else {
pLPF->a.s32 = ma_biquad_float_to_fp(a);
}
return MA_SUCCESS;
}
MA_API ma_result ma_lpf1_clear_cache(ma_lpf1* pLPF)
{
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
if (pLPF->format == ma_format_f32) {
pLPF->a.f32 = 0;
} else {
pLPF->a.s32 = 0;
}
return MA_SUCCESS;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_biquad_config bqConfig;
double q;
double w;
double s;
double c;
double a;
MA_ASSERT(pConfig != NULL);
q = pConfig->q;
w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
s = ma_sind(w);
c = ma_cosd(w);
a = s / (2*q);
bqConfig.b0 = (1 - c) / 2;
bqConfig.b1 = 1 - c;
bqConfig.b2 = (1 - c) / 2;
bqConfig.a0 = 1 + a;
bqConfig.a1 = -2 * c;
bqConfig.a2 = 1 - a;
bqConfig.format = pConfig->format;
bqConfig.channels = pConfig->channels;
return bqConfig;
}
MA_API ma_result ma_lpf2_get_heap_size(const ma_lpf2_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_biquad_config bqConfig;
bqConfig = ma_lpf2__get_biquad_config(pConfig);
return ma_biquad_get_heap_size(&bqConfig, pHeapSizeInBytes);
}
MA_API ma_result ma_lpf2_init_preallocated(const ma_lpf2_config* pConfig, void* pHeap, ma_lpf2* pLPF)
{
ma_result result;
ma_biquad_config bqConfig;
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pLPF);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_lpf2__get_biquad_config(pConfig);
result = ma_biquad_init_preallocated(&bqConfig, pHeap, &pLPF->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_lpf2_init(const ma_lpf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf2* pLPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_lpf2_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_lpf2_init_preallocated(pConfig, pHeap, pLPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pLPF->bq._ownsHeap = MA_TRUE; /* <-- This will cause the biquad to take ownership of the heap and free it when it's uninitialized. */
return MA_SUCCESS;
}
MA_API void ma_lpf2_uninit(ma_lpf2* pLPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pLPF == NULL) {
return;
}
ma_biquad_uninit(&pLPF->bq, pAllocationCallbacks); /* <-- This will free the heap allocation. */
}
MA_API ma_result ma_lpf2_reinit(const ma_lpf2_config* pConfig, ma_lpf2* pLPF)
{
ma_result result;
ma_biquad_config bqConfig;
if (pLPF == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_lpf2__get_biquad_config(pConfig);
result = ma_biquad_reinit(&bqConfig, &pLPF->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_lpf2_clear_cache(ma_lpf2* pLPF)
{
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
ma_biquad_clear_cache(&pLPF->bq);
return MA_SUCCESS;
}
static MA_INLINE void ma_lpf2_process_pcm_frame_s16(ma_lpf2* pLPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
{
ma_biquad_process_pcm_frame_s16(&pLPF->bq, pFrameOut, pFrameIn);
}
static MA_INLINE void ma_lpf2_process_pcm_frame_f32(ma_lpf2* pLPF, float* pFrameOut, const float* pFrameIn)
{
ma_biquad_process_pcm_frame_f32(&pLPF->bq, pFrameOut, pFrameIn);
}
MA_API ma_result ma_lpf2_process_pcm_frames(ma_lpf2* pLPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
return ma_biquad_process_pcm_frames(&pLPF->bq, pFramesOut, pFramesIn, frameCount);
}
MA_API ma_uint32 ma_lpf2_get_latency(const ma_lpf2* pLPF)
{
if (pLPF == NULL) {
return 0;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
return MA_INVALID_ARGS;
}
/* The format cannot be changed after initialization. */
if (pLPF->format != ma_format_unknown && pLPF->format != pConfig->format) {
return MA_INVALID_OPERATION;
}
/* The channel count cannot be changed after initialization. */
if (pLPF->channels != 0 && pLPF->channels != pConfig->channels) {
return MA_INVALID_OPERATION;
}
if (pConfig->order > MA_MAX_FILTER_ORDER) {
return MA_INVALID_ARGS;
}
ma_lpf_calculate_sub_lpf_counts(pConfig->order, &lpf1Count, &lpf2Count);
/* The filter order can't change between reinits. */
if (!isNew) {
if (pLPF->lpf1Count != lpf1Count || pLPF->lpf2Count != lpf2Count) {
return MA_INVALID_OPERATION;
}
}
if (isNew) {
result = ma_lpf_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pLPF->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pLPF->pLPF1 = (ma_lpf1*)ma_offset_ptr(pHeap, heapLayout.lpf1Offset);
pLPF->pLPF2 = (ma_lpf2*)ma_offset_ptr(pHeap, heapLayout.lpf2Offset);
} else {
MA_ZERO_OBJECT(&heapLayout); /* To silence a compiler warning. */
}
for (ilpf1 = 0; ilpf1 < lpf1Count; ilpf1 += 1) {
ma_lpf1_config lpf1Config = ma_lpf1_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency);
if (isNew) {
size_t lpf1HeapSizeInBytes;
result = ma_lpf1_get_heap_size(&lpf1Config, &lpf1HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_lpf1_init_preallocated(&lpf1Config, ma_offset_ptr(pHeap, heapLayout.lpf1Offset + (sizeof(ma_lpf1) * lpf1Count) + (ilpf1 * lpf1HeapSizeInBytes)), &pLPF->pLPF1[ilpf1]);
}
} else {
result = ma_lpf1_reinit(&lpf1Config, &pLPF->pLPF1[ilpf1]);
}
if (result != MA_SUCCESS) {
ma_uint32 jlpf1;
for (jlpf1 = 0; jlpf1 < ilpf1; jlpf1 += 1) {
ma_lpf1_uninit(&pLPF->pLPF1[jlpf1], NULL); /* No need for allocation callbacks here since we used a preallocated heap allocation. */
}
return result;
}
}
for (ilpf2 = 0; ilpf2 < lpf2Count; ilpf2 += 1) {
ma_lpf2_config lpf2Config;
double q;
double a;
/* Tempting to use 0.707107, but won't result in a Butterworth filter if the order is > 2. */
if (lpf1Count == 1) {
a = (1 + ilpf2*1) * (MA_PI_D/(pConfig->order*1)); /* Odd order. */
} else {
a = (1 + ilpf2*2) * (MA_PI_D/(pConfig->order*2)); /* Even order. */
}
q = 1 / (2*ma_cosd(a));
lpf2Config = ma_lpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
if (isNew) {
size_t lpf2HeapSizeInBytes;
result = ma_lpf2_get_heap_size(&lpf2Config, &lpf2HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_lpf2_init_preallocated(&lpf2Config, ma_offset_ptr(pHeap, heapLayout.lpf2Offset + (sizeof(ma_lpf2) * lpf2Count) + (ilpf2 * lpf2HeapSizeInBytes)), &pLPF->pLPF2[ilpf2]);
}
} else {
result = ma_lpf2_reinit(&lpf2Config, &pLPF->pLPF2[ilpf2]);
}
if (result != MA_SUCCESS) {
ma_uint32 jlpf1;
ma_uint32 jlpf2;
for (jlpf1 = 0; jlpf1 < lpf1Count; jlpf1 += 1) {
ma_lpf1_uninit(&pLPF->pLPF1[jlpf1], NULL); /* No need for allocation callbacks here since we used a preallocated heap allocation. */
}
for (jlpf2 = 0; jlpf2 < ilpf2; jlpf2 += 1) {
ma_lpf2_uninit(&pLPF->pLPF2[jlpf2], NULL); /* No need for allocation callbacks here since we used a preallocated heap allocation. */
}
return result;
}
}
pLPF->lpf1Count = lpf1Count;
pLPF->lpf2Count = lpf2Count;
pLPF->format = pConfig->format;
pLPF->channels = pConfig->channels;
pLPF->sampleRate = pConfig->sampleRate;
return MA_SUCCESS;
}
MA_API ma_result ma_lpf_get_heap_size(const ma_lpf_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_lpf_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_lpf_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return result;
}
MA_API ma_result ma_lpf_init_preallocated(const ma_lpf_config* pConfig, void* pHeap, ma_lpf* pLPF)
{
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pLPF);
return ma_lpf_reinit__internal(pConfig, pHeap, pLPF, /*isNew*/MA_TRUE);
}
MA_API ma_result ma_lpf_init(const ma_lpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf* pLPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_lpf_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_lpf_init_preallocated(pConfig, pHeap, pLPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pLPF->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_lpf_uninit(ma_lpf* pLPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_uint32 ilpf1;
ma_uint32 ilpf2;
if (pLPF == NULL) {
return;
}
for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
ma_lpf1_uninit(&pLPF->pLPF1[ilpf1], pAllocationCallbacks);
}
for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
ma_lpf2_uninit(&pLPF->pLPF2[ilpf2], pAllocationCallbacks);
}
if (pLPF->_ownsHeap) {
ma_free(pLPF->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_lpf_reinit(const ma_lpf_config* pConfig, ma_lpf* pLPF)
{
return ma_lpf_reinit__internal(pConfig, NULL, pLPF, /*isNew*/MA_FALSE);
}
MA_API ma_result ma_lpf_clear_cache(ma_lpf* pLPF)
{
ma_uint32 ilpf1;
ma_uint32 ilpf2;
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
ma_lpf1_clear_cache(&pLPF->pLPF1[ilpf1]);
}
for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
ma_lpf2_clear_cache(&pLPF->pLPF2[ilpf2]);
}
return MA_SUCCESS;
}
static MA_INLINE void ma_lpf_process_pcm_frame_f32(ma_lpf* pLPF, float* pY, const void* pX)
{
ma_uint32 ilpf1;
ma_uint32 ilpf2;
MA_ASSERT(pLPF->format == ma_format_f32);
MA_COPY_MEMORY(pY, pX, ma_get_bytes_per_frame(pLPF->format, pLPF->channels));
for (ilpf1 = 0; ilpf1 < pLPF->lpf1Count; ilpf1 += 1) {
ma_lpf1_process_pcm_frame_f32(&pLPF->pLPF1[ilpf1], pY, pY);
}
for (ilpf2 = 0; ilpf2 < pLPF->lpf2Count; ilpf2 += 1) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (pConfig->channels == 0) {
return MA_INVALID_ARGS;
}
pHeapLayout->sizeInBytes = 0;
/* R1 */
pHeapLayout->r1Offset = pHeapLayout->sizeInBytes;
pHeapLayout->sizeInBytes += sizeof(ma_biquad_coefficient) * pConfig->channels;
/* Make sure allocation size is aligned. */
pHeapLayout->sizeInBytes = ma_align_64(pHeapLayout->sizeInBytes);
return MA_SUCCESS;
}
MA_API ma_result ma_hpf1_get_heap_size(const ma_hpf1_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_hpf1_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
result = ma_hpf1_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_hpf1_init_preallocated(const ma_hpf1_config* pConfig, void* pHeap, ma_hpf1* pLPF)
{
ma_result result;
ma_hpf1_heap_layout heapLayout;
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pLPF);
result = ma_hpf1_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pLPF->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pLPF->pR1 = (ma_biquad_coefficient*)ma_offset_ptr(pHeap, heapLayout.r1Offset);
return ma_hpf1_reinit(pConfig, pLPF);
}
MA_API ma_result ma_hpf1_init(const ma_hpf1_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf1* pLPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_hpf1_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_hpf1_init_preallocated(pConfig, pHeap, pLPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pLPF->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_hpf1_uninit(ma_hpf1* pHPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pHPF == NULL) {
return;
}
if (pHPF->_ownsHeap) {
ma_free(pHPF->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_hpf1_reinit(const ma_hpf1_config* pConfig, ma_hpf1* pHPF)
{
double a;
if (pHPF == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
/* Only supporting f32 and s16. */
if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
return MA_INVALID_ARGS;
}
/* The format cannot be changed after initialization. */
if (pHPF->format != ma_format_unknown && pHPF->format != pConfig->format) {
return MA_INVALID_OPERATION;
}
/* The channel count cannot be changed after initialization. */
if (pHPF->channels != 0 && pHPF->channels != pConfig->channels) {
return MA_INVALID_OPERATION;
}
pHPF->format = pConfig->format;
pHPF->channels = pConfig->channels;
a = ma_expd(-2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate);
if (pConfig->format == ma_format_f32) {
pHPF->a.f32 = (float)a;
} else {
pHPF->a.s32 = ma_biquad_float_to_fp(a);
}
return MA_SUCCESS;
}
static MA_INLINE void ma_hpf1_process_pcm_frame_f32(ma_hpf1* pHPF, float* pY, const float* pX)
{
ma_uint32 c;
const ma_uint32 channels = pHPF->channels;
const float a = 1 - pHPF->a.f32;
const float b = 1 - a;
MA_ASSUME(channels > 0);
for (c = 0; c < channels; c += 1) {
float r1 = pHPF->pR1[c].f32;
float x = pX[c];
float y;
y = b*x - a*r1;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_biquad_config bqConfig;
double q;
double w;
double s;
double c;
double a;
MA_ASSERT(pConfig != NULL);
q = pConfig->q;
w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
s = ma_sind(w);
c = ma_cosd(w);
a = s / (2*q);
bqConfig.b0 = (1 + c) / 2;
bqConfig.b1 = -(1 + c);
bqConfig.b2 = (1 + c) / 2;
bqConfig.a0 = 1 + a;
bqConfig.a1 = -2 * c;
bqConfig.a2 = 1 - a;
bqConfig.format = pConfig->format;
bqConfig.channels = pConfig->channels;
return bqConfig;
}
MA_API ma_result ma_hpf2_get_heap_size(const ma_hpf2_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_biquad_config bqConfig;
bqConfig = ma_hpf2__get_biquad_config(pConfig);
return ma_biquad_get_heap_size(&bqConfig, pHeapSizeInBytes);
}
MA_API ma_result ma_hpf2_init_preallocated(const ma_hpf2_config* pConfig, void* pHeap, ma_hpf2* pHPF)
{
ma_result result;
ma_biquad_config bqConfig;
if (pHPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pHPF);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_hpf2__get_biquad_config(pConfig);
result = ma_biquad_init_preallocated(&bqConfig, pHeap, &pHPF->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_hpf2_init(const ma_hpf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf2* pHPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_hpf2_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_hpf2_init_preallocated(pConfig, pHeap, pHPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pHPF->bq._ownsHeap = MA_TRUE; /* <-- This will cause the biquad to take ownership of the heap and free it when it's uninitialized. */
return MA_SUCCESS;
}
MA_API void ma_hpf2_uninit(ma_hpf2* pHPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pHPF == NULL) {
return;
}
ma_biquad_uninit(&pHPF->bq, pAllocationCallbacks); /* <-- This will free the heap allocation. */
}
MA_API ma_result ma_hpf2_reinit(const ma_hpf2_config* pConfig, ma_hpf2* pHPF)
{
ma_result result;
ma_biquad_config bqConfig;
if (pHPF == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_hpf2__get_biquad_config(pConfig);
result = ma_biquad_reinit(&bqConfig, &pHPF->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
static MA_INLINE void ma_hpf2_process_pcm_frame_s16(ma_hpf2* pHPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
{
ma_biquad_process_pcm_frame_s16(&pHPF->bq, pFrameOut, pFrameIn);
}
static MA_INLINE void ma_hpf2_process_pcm_frame_f32(ma_hpf2* pHPF, float* pFrameOut, const float* pFrameIn)
{
ma_biquad_process_pcm_frame_f32(&pHPF->bq, pFrameOut, pFrameIn);
}
MA_API ma_result ma_hpf2_process_pcm_frames(ma_hpf2* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pHPF == NULL) {
return MA_INVALID_ARGS;
}
return ma_biquad_process_pcm_frames(&pHPF->bq, pFramesOut, pFramesIn, frameCount);
}
MA_API ma_uint32 ma_hpf2_get_latency(const ma_hpf2* pHPF)
{
if (pHPF == NULL) {
return 0;
}
return ma_biquad_get_latency(&pHPF->bq);
}
MA_API ma_hpf_config ma_hpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_hpf_config config;
MA_ZERO_OBJECT(&config);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (pConfig->format != ma_format_f32 && pConfig->format != ma_format_s16) {
return MA_INVALID_ARGS;
}
/* The format cannot be changed after initialization. */
if (pHPF->format != ma_format_unknown && pHPF->format != pConfig->format) {
return MA_INVALID_OPERATION;
}
/* The channel count cannot be changed after initialization. */
if (pHPF->channels != 0 && pHPF->channels != pConfig->channels) {
return MA_INVALID_OPERATION;
}
if (pConfig->order > MA_MAX_FILTER_ORDER) {
return MA_INVALID_ARGS;
}
ma_hpf_calculate_sub_hpf_counts(pConfig->order, &hpf1Count, &hpf2Count);
/* The filter order can't change between reinits. */
if (!isNew) {
if (pHPF->hpf1Count != hpf1Count || pHPF->hpf2Count != hpf2Count) {
return MA_INVALID_OPERATION;
}
}
if (isNew) {
result = ma_hpf_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pHPF->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pHPF->pHPF1 = (ma_hpf1*)ma_offset_ptr(pHeap, heapLayout.hpf1Offset);
pHPF->pHPF2 = (ma_hpf2*)ma_offset_ptr(pHeap, heapLayout.hpf2Offset);
} else {
MA_ZERO_OBJECT(&heapLayout); /* To silence a compiler warning. */
}
for (ihpf1 = 0; ihpf1 < hpf1Count; ihpf1 += 1) {
ma_hpf1_config hpf1Config = ma_hpf1_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency);
if (isNew) {
size_t hpf1HeapSizeInBytes;
result = ma_hpf1_get_heap_size(&hpf1Config, &hpf1HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_hpf1_init_preallocated(&hpf1Config, ma_offset_ptr(pHeap, heapLayout.hpf1Offset + (sizeof(ma_hpf1) * hpf1Count) + (ihpf1 * hpf1HeapSizeInBytes)), &pHPF->pHPF1[ihpf1]);
}
} else {
result = ma_hpf1_reinit(&hpf1Config, &pHPF->pHPF1[ihpf1]);
}
if (result != MA_SUCCESS) {
ma_uint32 jhpf1;
for (jhpf1 = 0; jhpf1 < ihpf1; jhpf1 += 1) {
ma_hpf1_uninit(&pHPF->pHPF1[jhpf1], NULL); /* No need for allocation callbacks here since we used a preallocated heap allocation. */
}
return result;
}
}
for (ihpf2 = 0; ihpf2 < hpf2Count; ihpf2 += 1) {
ma_hpf2_config hpf2Config;
double q;
double a;
/* Tempting to use 0.707107, but won't result in a Butterworth filter if the order is > 2. */
if (hpf1Count == 1) {
a = (1 + ihpf2*1) * (MA_PI_D/(pConfig->order*1)); /* Odd order. */
} else {
a = (1 + ihpf2*2) * (MA_PI_D/(pConfig->order*2)); /* Even order. */
}
q = 1 / (2*ma_cosd(a));
hpf2Config = ma_hpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
if (isNew) {
size_t hpf2HeapSizeInBytes;
result = ma_hpf2_get_heap_size(&hpf2Config, &hpf2HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_hpf2_init_preallocated(&hpf2Config, ma_offset_ptr(pHeap, heapLayout.hpf2Offset + (sizeof(ma_hpf2) * hpf2Count) + (ihpf2 * hpf2HeapSizeInBytes)), &pHPF->pHPF2[ihpf2]);
}
} else {
result = ma_hpf2_reinit(&hpf2Config, &pHPF->pHPF2[ihpf2]);
}
if (result != MA_SUCCESS) {
ma_uint32 jhpf1;
ma_uint32 jhpf2;
for (jhpf1 = 0; jhpf1 < hpf1Count; jhpf1 += 1) {
ma_hpf1_uninit(&pHPF->pHPF1[jhpf1], NULL); /* No need for allocation callbacks here since we used a preallocated heap allocation. */
}
for (jhpf2 = 0; jhpf2 < ihpf2; jhpf2 += 1) {
ma_hpf2_uninit(&pHPF->pHPF2[jhpf2], NULL); /* No need for allocation callbacks here since we used a preallocated heap allocation. */
}
return result;
}
}
pHPF->hpf1Count = hpf1Count;
pHPF->hpf2Count = hpf2Count;
pHPF->format = pConfig->format;
pHPF->channels = pConfig->channels;
pHPF->sampleRate = pConfig->sampleRate;
return MA_SUCCESS;
}
MA_API ma_result ma_hpf_get_heap_size(const ma_hpf_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_hpf_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_hpf_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return result;
}
MA_API ma_result ma_hpf_init_preallocated(const ma_hpf_config* pConfig, void* pHeap, ma_hpf* pLPF)
{
if (pLPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pLPF);
return ma_hpf_reinit__internal(pConfig, pHeap, pLPF, /*isNew*/MA_TRUE);
}
MA_API ma_result ma_hpf_init(const ma_hpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf* pHPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_hpf_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_hpf_init_preallocated(pConfig, pHeap, pHPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pHPF->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_hpf_uninit(ma_hpf* pHPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_uint32 ihpf1;
ma_uint32 ihpf2;
if (pHPF == NULL) {
return;
}
for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
ma_hpf1_uninit(&pHPF->pHPF1[ihpf1], pAllocationCallbacks);
}
for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
ma_hpf2_uninit(&pHPF->pHPF2[ihpf2], pAllocationCallbacks);
}
if (pHPF->_ownsHeap) {
ma_free(pHPF->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_hpf_reinit(const ma_hpf_config* pConfig, ma_hpf* pHPF)
{
return ma_hpf_reinit__internal(pConfig, NULL, pHPF, /*isNew*/MA_FALSE);
}
MA_API ma_result ma_hpf_process_pcm_frames(ma_hpf* pHPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
ma_result result;
ma_uint32 ihpf1;
ma_uint32 ihpf2;
if (pHPF == NULL) {
return MA_INVALID_ARGS;
}
/* Faster path for in-place. */
if (pFramesOut == pFramesIn) {
for (ihpf1 = 0; ihpf1 < pHPF->hpf1Count; ihpf1 += 1) {
result = ma_hpf1_process_pcm_frames(&pHPF->pHPF1[ihpf1], pFramesOut, pFramesOut, frameCount);
if (result != MA_SUCCESS) {
return result;
}
}
for (ihpf2 = 0; ihpf2 < pHPF->hpf2Count; ihpf2 += 1) {
result = ma_hpf2_process_pcm_frames(&pHPF->pHPF2[ihpf2], pFramesOut, pFramesOut, frameCount);
if (result != MA_SUCCESS) {
return result;
}
}
}
/* Slightly slower path for copying. */
if (pFramesOut != pFramesIn) {
ma_uint32 iFrame;
/* */ if (pHPF->format == ma_format_f32) {
/* */ float* pFramesOutF32 = ( float*)pFramesOut;
const float* pFramesInF32 = (const float*)pFramesIn;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_biquad_config bqConfig;
double q;
double w;
double s;
double c;
double a;
MA_ASSERT(pConfig != NULL);
q = pConfig->q;
w = 2 * MA_PI_D * pConfig->cutoffFrequency / pConfig->sampleRate;
s = ma_sind(w);
c = ma_cosd(w);
a = s / (2*q);
bqConfig.b0 = q * a;
bqConfig.b1 = 0;
bqConfig.b2 = -q * a;
bqConfig.a0 = 1 + a;
bqConfig.a1 = -2 * c;
bqConfig.a2 = 1 - a;
bqConfig.format = pConfig->format;
bqConfig.channels = pConfig->channels;
return bqConfig;
}
MA_API ma_result ma_bpf2_get_heap_size(const ma_bpf2_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_biquad_config bqConfig;
bqConfig = ma_bpf2__get_biquad_config(pConfig);
return ma_biquad_get_heap_size(&bqConfig, pHeapSizeInBytes);
}
MA_API ma_result ma_bpf2_init_preallocated(const ma_bpf2_config* pConfig, void* pHeap, ma_bpf2* pBPF)
{
ma_result result;
ma_biquad_config bqConfig;
if (pBPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pBPF);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_bpf2__get_biquad_config(pConfig);
result = ma_biquad_init_preallocated(&bqConfig, pHeap, &pBPF->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_bpf2_init(const ma_bpf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf2* pBPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_bpf2_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_bpf2_init_preallocated(pConfig, pHeap, pBPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pBPF->bq._ownsHeap = MA_TRUE; /* <-- This will cause the biquad to take ownership of the heap and free it when it's uninitialized. */
return MA_SUCCESS;
}
MA_API void ma_bpf2_uninit(ma_bpf2* pBPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pBPF == NULL) {
return;
}
ma_biquad_uninit(&pBPF->bq, pAllocationCallbacks); /* <-- This will free the heap allocation. */
}
MA_API ma_result ma_bpf2_reinit(const ma_bpf2_config* pConfig, ma_bpf2* pBPF)
{
ma_result result;
ma_biquad_config bqConfig;
if (pBPF == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_bpf2__get_biquad_config(pConfig);
result = ma_biquad_reinit(&bqConfig, &pBPF->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
static MA_INLINE void ma_bpf2_process_pcm_frame_s16(ma_bpf2* pBPF, ma_int16* pFrameOut, const ma_int16* pFrameIn)
{
ma_biquad_process_pcm_frame_s16(&pBPF->bq, pFrameOut, pFrameIn);
}
static MA_INLINE void ma_bpf2_process_pcm_frame_f32(ma_bpf2* pBPF, float* pFrameOut, const float* pFrameIn)
{
ma_biquad_process_pcm_frame_f32(&pBPF->bq, pFrameOut, pFrameIn);
}
MA_API ma_result ma_bpf2_process_pcm_frames(ma_bpf2* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pBPF == NULL) {
return MA_INVALID_ARGS;
}
return ma_biquad_process_pcm_frames(&pBPF->bq, pFramesOut, pFramesIn, frameCount);
}
MA_API ma_uint32 ma_bpf2_get_latency(const ma_bpf2* pBPF)
{
if (pBPF == NULL) {
return 0;
}
return ma_biquad_get_latency(&pBPF->bq);
}
MA_API ma_bpf_config ma_bpf_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_bpf_config config;
MA_ZERO_OBJECT(&config);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
q = 0.707107;
bpf2Config = ma_bpf2_config_init(pConfig->format, pConfig->channels, pConfig->sampleRate, pConfig->cutoffFrequency, q);
if (isNew) {
size_t bpf2HeapSizeInBytes;
result = ma_bpf2_get_heap_size(&bpf2Config, &bpf2HeapSizeInBytes);
if (result == MA_SUCCESS) {
result = ma_bpf2_init_preallocated(&bpf2Config, ma_offset_ptr(pHeap, heapLayout.bpf2Offset + (sizeof(ma_bpf2) * bpf2Count) + (ibpf2 * bpf2HeapSizeInBytes)), &pBPF->pBPF2[ibpf2]);
}
} else {
result = ma_bpf2_reinit(&bpf2Config, &pBPF->pBPF2[ibpf2]);
}
if (result != MA_SUCCESS) {
return result;
}
}
pBPF->bpf2Count = bpf2Count;
pBPF->format = pConfig->format;
pBPF->channels = pConfig->channels;
return MA_SUCCESS;
}
MA_API ma_result ma_bpf_get_heap_size(const ma_bpf_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_bpf_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_bpf_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_bpf_init_preallocated(const ma_bpf_config* pConfig, void* pHeap, ma_bpf* pBPF)
{
if (pBPF == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pBPF);
return ma_bpf_reinit__internal(pConfig, pHeap, pBPF, /*isNew*/MA_TRUE);
}
MA_API ma_result ma_bpf_init(const ma_bpf_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf* pBPF)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_bpf_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_bpf_init_preallocated(pConfig, pHeap, pBPF);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pBPF->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_bpf_uninit(ma_bpf* pBPF, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_uint32 ibpf2;
if (pBPF == NULL) {
return;
}
for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
ma_bpf2_uninit(&pBPF->pBPF2[ibpf2], pAllocationCallbacks);
}
if (pBPF->_ownsHeap) {
ma_free(pBPF->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_bpf_reinit(const ma_bpf_config* pConfig, ma_bpf* pBPF)
{
return ma_bpf_reinit__internal(pConfig, NULL, pBPF, /*isNew*/MA_FALSE);
}
MA_API ma_result ma_bpf_process_pcm_frames(ma_bpf* pBPF, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
ma_result result;
ma_uint32 ibpf2;
if (pBPF == NULL) {
return MA_INVALID_ARGS;
}
/* Faster path for in-place. */
if (pFramesOut == pFramesIn) {
for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
result = ma_bpf2_process_pcm_frames(&pBPF->pBPF2[ibpf2], pFramesOut, pFramesOut, frameCount);
if (result != MA_SUCCESS) {
return result;
}
}
}
/* Slightly slower path for copying. */
if (pFramesOut != pFramesIn) {
ma_uint32 iFrame;
/* */ if (pBPF->format == ma_format_f32) {
/* */ float* pFramesOutF32 = ( float*)pFramesOut;
const float* pFramesInF32 = (const float*)pFramesIn;
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
MA_COPY_MEMORY(pFramesOutF32, pFramesInF32, ma_get_bytes_per_frame(pBPF->format, pBPF->channels));
for (ibpf2 = 0; ibpf2 < pBPF->bpf2Count; ibpf2 += 1) {
ma_bpf2_process_pcm_frame_f32(&pBPF->pBPF2[ibpf2], pFramesOutF32, pFramesOutF32);
}
pFramesOutF32 += pBPF->channels;
pFramesInF32 += pBPF->channels;
}
} else if (pBPF->format == ma_format_s16) {
/* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_biquad_config bqConfig;
double q;
double w;
double s;
double c;
double a;
MA_ASSERT(pConfig != NULL);
q = pConfig->q;
w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
s = ma_sind(w);
c = ma_cosd(w);
a = s / (2*q);
bqConfig.b0 = 1;
bqConfig.b1 = -2 * c;
bqConfig.b2 = 1;
bqConfig.a0 = 1 + a;
bqConfig.a1 = -2 * c;
bqConfig.a2 = 1 - a;
bqConfig.format = pConfig->format;
bqConfig.channels = pConfig->channels;
return bqConfig;
}
MA_API ma_result ma_notch2_get_heap_size(const ma_notch2_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_biquad_config bqConfig;
bqConfig = ma_notch2__get_biquad_config(pConfig);
return ma_biquad_get_heap_size(&bqConfig, pHeapSizeInBytes);
}
MA_API ma_result ma_notch2_init_preallocated(const ma_notch2_config* pConfig, void* pHeap, ma_notch2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pFilter);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_notch2__get_biquad_config(pConfig);
result = ma_biquad_init_preallocated(&bqConfig, pHeap, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_notch2_init(const ma_notch2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch2* pFilter)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_notch2_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_notch2_init_preallocated(pConfig, pHeap, pFilter);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pFilter->bq._ownsHeap = MA_TRUE; /* <-- This will cause the biquad to take ownership of the heap and free it when it's uninitialized. */
return MA_SUCCESS;
}
MA_API void ma_notch2_uninit(ma_notch2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pFilter == NULL) {
return;
}
ma_biquad_uninit(&pFilter->bq, pAllocationCallbacks); /* <-- This will free the heap allocation. */
}
MA_API ma_result ma_notch2_reinit(const ma_notch2_config* pConfig, ma_notch2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_notch2__get_biquad_config(pConfig);
result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
static MA_INLINE void ma_notch2_process_pcm_frame_s16(ma_notch2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
{
ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
}
static MA_INLINE void ma_notch2_process_pcm_frame_f32(ma_notch2* pFilter, float* pFrameOut, const float* pFrameIn)
{
ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
}
MA_API ma_result ma_notch2_process_pcm_frames(ma_notch2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
}
MA_API ma_uint32 ma_notch2_get_latency(const ma_notch2* pFilter)
{
if (pFilter == NULL) {
return 0;
}
return ma_biquad_get_latency(&pFilter->bq);
}
/**************************************************************************************************************************************************************
Peaking EQ Filter
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
double w;
double s;
double c;
double a;
double A;
MA_ASSERT(pConfig != NULL);
q = pConfig->q;
w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
s = ma_sind(w);
c = ma_cosd(w);
a = s / (2*q);
A = ma_powd(10, (pConfig->gainDB / 40));
bqConfig.b0 = 1 + (a * A);
bqConfig.b1 = -2 * c;
bqConfig.b2 = 1 - (a * A);
bqConfig.a0 = 1 + (a / A);
bqConfig.a1 = -2 * c;
bqConfig.a2 = 1 - (a / A);
bqConfig.format = pConfig->format;
bqConfig.channels = pConfig->channels;
return bqConfig;
}
MA_API ma_result ma_peak2_get_heap_size(const ma_peak2_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_biquad_config bqConfig;
bqConfig = ma_peak2__get_biquad_config(pConfig);
return ma_biquad_get_heap_size(&bqConfig, pHeapSizeInBytes);
}
MA_API ma_result ma_peak2_init_preallocated(const ma_peak2_config* pConfig, void* pHeap, ma_peak2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pFilter);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_peak2__get_biquad_config(pConfig);
result = ma_biquad_init_preallocated(&bqConfig, pHeap, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_peak2_init(const ma_peak2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak2* pFilter)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_peak2_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_peak2_init_preallocated(pConfig, pHeap, pFilter);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pFilter->bq._ownsHeap = MA_TRUE; /* <-- This will cause the biquad to take ownership of the heap and free it when it's uninitialized. */
return MA_SUCCESS;
}
MA_API void ma_peak2_uninit(ma_peak2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pFilter == NULL) {
return;
}
ma_biquad_uninit(&pFilter->bq, pAllocationCallbacks); /* <-- This will free the heap allocation. */
}
MA_API ma_result ma_peak2_reinit(const ma_peak2_config* pConfig, ma_peak2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_peak2__get_biquad_config(pConfig);
result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
static MA_INLINE void ma_peak2_process_pcm_frame_s16(ma_peak2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
{
ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
}
static MA_INLINE void ma_peak2_process_pcm_frame_f32(ma_peak2* pFilter, float* pFrameOut, const float* pFrameIn)
{
ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
}
MA_API ma_result ma_peak2_process_pcm_frames(ma_peak2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
}
MA_API ma_uint32 ma_peak2_get_latency(const ma_peak2* pFilter)
{
if (pFilter == NULL) {
return 0;
}
return ma_biquad_get_latency(&pFilter->bq);
}
/**************************************************************************************************************************************************************
Low Shelf Filter
**************************************************************************************************************************************************************/
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
double A;
double S;
double a;
double sqrtA;
MA_ASSERT(pConfig != NULL);
w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
s = ma_sind(w);
c = ma_cosd(w);
A = ma_powd(10, (pConfig->gainDB / 40));
S = pConfig->shelfSlope;
a = s/2 * ma_sqrtd((A + 1/A) * (1/S - 1) + 2);
sqrtA = 2*ma_sqrtd(A)*a;
bqConfig.b0 = A * ((A + 1) - (A - 1)*c + sqrtA);
bqConfig.b1 = 2 * A * ((A - 1) - (A + 1)*c);
bqConfig.b2 = A * ((A + 1) - (A - 1)*c - sqrtA);
bqConfig.a0 = (A + 1) + (A - 1)*c + sqrtA;
bqConfig.a1 = -2 * ((A - 1) + (A + 1)*c);
bqConfig.a2 = (A + 1) + (A - 1)*c - sqrtA;
bqConfig.format = pConfig->format;
bqConfig.channels = pConfig->channels;
return bqConfig;
}
MA_API ma_result ma_loshelf2_get_heap_size(const ma_loshelf2_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_biquad_config bqConfig;
bqConfig = ma_loshelf2__get_biquad_config(pConfig);
return ma_biquad_get_heap_size(&bqConfig, pHeapSizeInBytes);
}
MA_API ma_result ma_loshelf2_init_preallocated(const ma_loshelf2_config* pConfig, void* pHeap, ma_loshelf2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pFilter);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_loshelf2__get_biquad_config(pConfig);
result = ma_biquad_init_preallocated(&bqConfig, pHeap, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_loshelf2_init(const ma_loshelf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf2* pFilter)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_loshelf2_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_loshelf2_init_preallocated(pConfig, pHeap, pFilter);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pFilter->bq._ownsHeap = MA_TRUE; /* <-- This will cause the biquad to take ownership of the heap and free it when it's uninitialized. */
return MA_SUCCESS;
}
MA_API void ma_loshelf2_uninit(ma_loshelf2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pFilter == NULL) {
return;
}
ma_biquad_uninit(&pFilter->bq, pAllocationCallbacks); /* <-- This will free the heap allocation. */
}
MA_API ma_result ma_loshelf2_reinit(const ma_loshelf2_config* pConfig, ma_loshelf2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_loshelf2__get_biquad_config(pConfig);
result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
static MA_INLINE void ma_loshelf2_process_pcm_frame_s16(ma_loshelf2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
{
ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
}
static MA_INLINE void ma_loshelf2_process_pcm_frame_f32(ma_loshelf2* pFilter, float* pFrameOut, const float* pFrameIn)
{
ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
}
MA_API ma_result ma_loshelf2_process_pcm_frames(ma_loshelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
}
MA_API ma_uint32 ma_loshelf2_get_latency(const ma_loshelf2* pFilter)
{
if (pFilter == NULL) {
return 0;
}
return ma_biquad_get_latency(&pFilter->bq);
}
/**************************************************************************************************************************************************************
High Shelf Filter
**************************************************************************************************************************************************************/
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
double A;
double S;
double a;
double sqrtA;
MA_ASSERT(pConfig != NULL);
w = 2 * MA_PI_D * pConfig->frequency / pConfig->sampleRate;
s = ma_sind(w);
c = ma_cosd(w);
A = ma_powd(10, (pConfig->gainDB / 40));
S = pConfig->shelfSlope;
a = s/2 * ma_sqrtd((A + 1/A) * (1/S - 1) + 2);
sqrtA = 2*ma_sqrtd(A)*a;
bqConfig.b0 = A * ((A + 1) + (A - 1)*c + sqrtA);
bqConfig.b1 = -2 * A * ((A - 1) + (A + 1)*c);
bqConfig.b2 = A * ((A + 1) + (A - 1)*c - sqrtA);
bqConfig.a0 = (A + 1) - (A - 1)*c + sqrtA;
bqConfig.a1 = 2 * ((A - 1) - (A + 1)*c);
bqConfig.a2 = (A + 1) - (A - 1)*c - sqrtA;
bqConfig.format = pConfig->format;
bqConfig.channels = pConfig->channels;
return bqConfig;
}
MA_API ma_result ma_hishelf2_get_heap_size(const ma_hishelf2_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_biquad_config bqConfig;
bqConfig = ma_hishelf2__get_biquad_config(pConfig);
return ma_biquad_get_heap_size(&bqConfig, pHeapSizeInBytes);
}
MA_API ma_result ma_hishelf2_init_preallocated(const ma_hishelf2_config* pConfig, void* pHeap, ma_hishelf2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pFilter);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_hishelf2__get_biquad_config(pConfig);
result = ma_biquad_init_preallocated(&bqConfig, pHeap, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_hishelf2_init(const ma_hishelf2_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf2* pFilter)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_hishelf2_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_hishelf2_init_preallocated(pConfig, pHeap, pFilter);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pFilter->bq._ownsHeap = MA_TRUE; /* <-- This will cause the biquad to take ownership of the heap and free it when it's uninitialized. */
return MA_SUCCESS;
}
MA_API void ma_hishelf2_uninit(ma_hishelf2* pFilter, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pFilter == NULL) {
return;
}
ma_biquad_uninit(&pFilter->bq, pAllocationCallbacks); /* <-- This will free the heap allocation. */
}
MA_API ma_result ma_hishelf2_reinit(const ma_hishelf2_config* pConfig, ma_hishelf2* pFilter)
{
ma_result result;
ma_biquad_config bqConfig;
if (pFilter == NULL || pConfig == NULL) {
return MA_INVALID_ARGS;
}
bqConfig = ma_hishelf2__get_biquad_config(pConfig);
result = ma_biquad_reinit(&bqConfig, &pFilter->bq);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
static MA_INLINE void ma_hishelf2_process_pcm_frame_s16(ma_hishelf2* pFilter, ma_int16* pFrameOut, const ma_int16* pFrameIn)
{
ma_biquad_process_pcm_frame_s16(&pFilter->bq, pFrameOut, pFrameIn);
}
static MA_INLINE void ma_hishelf2_process_pcm_frame_f32(ma_hishelf2* pFilter, float* pFrameOut, const float* pFrameIn)
{
ma_biquad_process_pcm_frame_f32(&pFilter->bq, pFrameOut, pFrameIn);
}
MA_API ma_result ma_hishelf2_process_pcm_frames(ma_hishelf2* pFilter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
if (pFilter == NULL) {
return MA_INVALID_ARGS;
}
return ma_biquad_process_pcm_frames(&pFilter->bq, pFramesOut, pFramesIn, frameCount);
}
MA_API ma_uint32 ma_hishelf2_get_latency(const ma_hishelf2* pFilter)
{
if (pFilter == NULL) {
return 0;
}
return ma_biquad_get_latency(&pFilter->bq);
}
/*
Delay
*/
MA_API ma_delay_config ma_delay_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay)
{
ma_delay_config config;
MA_ZERO_OBJECT(&config);
config.channels = channels;
config.sampleRate = sampleRate;
config.delayInFrames = delayInFrames;
config.delayStart = (decay == 0) ? MA_TRUE : MA_FALSE; /* Delay the start if it looks like we're not configuring an echo. */
config.wet = 1;
config.dry = 1;
config.decay = decay;
return config;
}
MA_API ma_result ma_delay_init(const ma_delay_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay* pDelay)
{
if (pDelay == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDelay);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->decay < 0 || pConfig->decay > 1) {
return MA_INVALID_ARGS;
}
pDelay->config = *pConfig;
pDelay->bufferSizeInFrames = pConfig->delayInFrames;
pDelay->cursor = 0;
pDelay->pBuffer = (float*)ma_malloc((size_t)(pDelay->bufferSizeInFrames * ma_get_bytes_per_frame(ma_format_f32, pConfig->channels)), pAllocationCallbacks);
if (pDelay->pBuffer == NULL) {
return MA_OUT_OF_MEMORY;
}
ma_silence_pcm_frames(pDelay->pBuffer, pDelay->bufferSizeInFrames, ma_format_f32, pConfig->channels);
return MA_SUCCESS;
}
MA_API void ma_delay_uninit(ma_delay* pDelay, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pDelay == NULL) {
return;
}
ma_free(pDelay->pBuffer, pAllocationCallbacks);
}
MA_API ma_result ma_delay_process_pcm_frames(ma_delay* pDelay, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
{
ma_uint32 iFrame;
ma_uint32 iChannel;
float* pFramesOutF32 = (float*)pFramesOut;
const float* pFramesInF32 = (const float*)pFramesIn;
if (pDelay == NULL || pFramesOut == NULL || pFramesIn == NULL) {
return MA_INVALID_ARGS;
}
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
for (iChannel = 0; iChannel < pDelay->config.channels; iChannel += 1) {
ma_uint32 iBuffer = (pDelay->cursor * pDelay->config.channels) + iChannel;
if (pDelay->config.delayStart) {
/* Delayed start. */
/* Read */
pFramesOutF32[iChannel] = pDelay->pBuffer[iBuffer] * pDelay->config.wet;
/* Feedback */
pDelay->pBuffer[iBuffer] = (pDelay->pBuffer[iBuffer] * pDelay->config.decay) + (pFramesInF32[iChannel] * pDelay->config.dry);
} else {
/* Immediate start */
/* Feedback */
pDelay->pBuffer[iBuffer] = (pDelay->pBuffer[iBuffer] * pDelay->config.decay) + (pFramesInF32[iChannel] * pDelay->config.dry);
/* Read */
pFramesOutF32[iChannel] = pDelay->pBuffer[iBuffer] * pDelay->config.wet;
}
}
pDelay->cursor = (pDelay->cursor + 1) % pDelay->bufferSizeInFrames;
pFramesOutF32 += pDelay->config.channels;
pFramesInF32 += pDelay->config.channels;
}
return MA_SUCCESS;
}
MA_API void ma_delay_set_wet(ma_delay* pDelay, float value)
{
if (pDelay == NULL) {
return;
}
pDelay->config.wet = value;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
MA_API ma_result ma_gainer_get_heap_size(const ma_gainer_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_result result;
ma_gainer_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_gainer_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_gainer_init_preallocated(const ma_gainer_config* pConfig, void* pHeap, ma_gainer* pGainer)
{
ma_result result;
ma_gainer_heap_layout heapLayout;
ma_uint32 iChannel;
if (pGainer == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pGainer);
if (pConfig == NULL || pHeap == NULL) {
return MA_INVALID_ARGS;
}
result = ma_gainer_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pGainer->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pGainer->pOldGains = (float*)ma_offset_ptr(pHeap, heapLayout.oldGainsOffset);
pGainer->pNewGains = (float*)ma_offset_ptr(pHeap, heapLayout.newGainsOffset);
pGainer->config = *pConfig;
pGainer->t = (ma_uint32)-1; /* No interpolation by default. */
for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
pGainer->pOldGains[iChannel] = 1;
pGainer->pNewGains[iChannel] = 1;
}
return MA_SUCCESS;
}
MA_API ma_result ma_gainer_init(const ma_gainer_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_gainer* pGainer)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_gainer_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result; /* Failed to retrieve the size of the heap allocation. */
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_gainer_init_preallocated(pConfig, pHeap, pGainer);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pGainer->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_gainer_uninit(ma_gainer* pGainer, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pGainer == NULL) {
return;
}
if (pGainer->_ownsHeap) {
ma_free(pGainer->_pHeap, pAllocationCallbacks);
}
}
static float ma_gainer_calculate_current_gain(const ma_gainer* pGainer, ma_uint32 channel)
{
float a = (float)pGainer->t / pGainer->config.smoothTimeInFrames;
return ma_mix_f32_fast(pGainer->pOldGains[channel], pGainer->pNewGains[channel], a);
}
MA_API ma_result ma_gainer_process_pcm_frames(ma_gainer* pGainer, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
ma_uint64 iFrame;
ma_uint32 iChannel;
float* pFramesOutF32 = (float*)pFramesOut;
const float* pFramesInF32 = (const float*)pFramesIn;
if (pGainer == NULL) {
return MA_INVALID_ARGS;
}
if (pGainer->t >= pGainer->config.smoothTimeInFrames) {
/* Fast path. No gain calculation required. */
ma_copy_and_apply_volume_factor_per_channel_f32(pFramesOutF32, pFramesInF32, frameCount, pGainer->config.channels, pGainer->pNewGains);
/* Now that some frames have been processed we need to make sure future changes to the gain are interpolated. */
if (pGainer->t == (ma_uint32)-1) {
pGainer->t = pGainer->config.smoothTimeInFrames;
}
} else {
/* Slow path. Need to interpolate the gain for each channel individually. */
/* We can allow the input and output buffers to be null in which case we'll just update the internal timer. */
if (pFramesOut != NULL && pFramesIn != NULL) {
float a = (float)pGainer->t / pGainer->config.smoothTimeInFrames;
float d = 1.0f / pGainer->config.smoothTimeInFrames;
ma_uint32 channelCount = pGainer->config.channels;
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
for (iChannel = 0; iChannel < channelCount; iChannel += 1) {
pFramesOutF32[iChannel] = pFramesInF32[iChannel] * ma_mix_f32_fast(pGainer->pOldGains[iChannel], pGainer->pNewGains[iChannel], a);
}
pFramesOutF32 += channelCount;
pFramesInF32 += channelCount;
a += d;
if (a > 1) {
a = 1;
}
}
}
pGainer->t = (ma_uint32)ma_min(pGainer->t + frameCount, pGainer->config.smoothTimeInFrames);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_spatializer_listener_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_spatializer_listener_init_preallocated(const ma_spatializer_listener_config* pConfig, void* pHeap, ma_spatializer_listener* pListener)
{
ma_result result;
ma_spatializer_listener_heap_layout heapLayout;
if (pListener == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pListener);
result = ma_spatializer_listener_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pListener->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pListener->config = *pConfig;
pListener->position = ma_vec3f_init_3f(0, 0, 0);
pListener->direction = ma_vec3f_init_3f(0, 0, -1);
pListener->velocity = ma_vec3f_init_3f(0, 0, 0);
pListener->isEnabled = MA_TRUE;
/* Swap the forward direction if we're left handed (it was initialized based on right handed). */
if (pListener->config.handedness == ma_handedness_left) {
pListener->direction = ma_vec3f_neg(pListener->direction);
}
/* We must always have a valid channel map. */
pListener->config.pChannelMapOut = (ma_channel*)ma_offset_ptr(pHeap, heapLayout.channelMapOutOffset);
/* Use a slightly different default channel map for stereo. */
if (pConfig->pChannelMapOut == NULL) {
ma_get_default_channel_map_for_spatializer(pListener->config.pChannelMapOut, pConfig->channelsOut, pConfig->channelsOut);
} else {
ma_channel_map_copy_or_default(pListener->config.pChannelMapOut, pConfig->channelsOut, pConfig->pChannelMapOut, pConfig->channelsOut);
}
return MA_SUCCESS;
}
MA_API ma_result ma_spatializer_listener_init(const ma_spatializer_listener_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_spatializer_listener* pListener)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_spatializer_listener_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_spatializer_listener_init_preallocated(pConfig, pHeap, pListener);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pListener->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_spatializer_listener_uninit(ma_spatializer_listener* pListener, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pListener == NULL) {
return;
}
if (pListener->_ownsHeap) {
ma_free(pListener->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_channel* ma_spatializer_listener_get_channel_map(ma_spatializer_listener* pListener)
{
if (pListener == NULL) {
return NULL;
}
return pListener->config.pChannelMapOut;
}
MA_API void ma_spatializer_listener_set_cone(ma_spatializer_listener* pListener, float innerAngleInRadians, float outerAngleInRadians, float outerGain)
{
if (pListener == NULL) {
return;
}
pListener->config.coneInnerAngleInRadians = innerAngleInRadians;
pListener->config.coneOuterAngleInRadians = outerAngleInRadians;
pListener->config.coneOuterGain = outerGain;
}
MA_API void ma_spatializer_listener_get_cone(const ma_spatializer_listener* pListener, float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain)
{
if (pListener == NULL) {
return;
}
if (pInnerAngleInRadians != NULL) {
*pInnerAngleInRadians = pListener->config.coneInnerAngleInRadians;
}
if (pOuterAngleInRadians != NULL) {
*pOuterAngleInRadians = pListener->config.coneOuterAngleInRadians;
}
if (pOuterGain != NULL) {
*pOuterGain = pListener->config.coneOuterGain;
}
}
MA_API void ma_spatializer_listener_set_position(ma_spatializer_listener* pListener, float x, float y, float z)
{
if (pListener == NULL) {
return;
}
pListener->position = ma_vec3f_init_3f(x, y, z);
}
MA_API ma_vec3f ma_spatializer_listener_get_position(const ma_spatializer_listener* pListener)
{
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
MA_ZERO_OBJECT(pSpatializer);
if (pConfig == NULL || pHeap == NULL) {
return MA_INVALID_ARGS;
}
result = ma_spatializer_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pSpatializer->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
pSpatializer->channelsIn = pConfig->channelsIn;
pSpatializer->channelsOut = pConfig->channelsOut;
pSpatializer->attenuationModel = pConfig->attenuationModel;
pSpatializer->positioning = pConfig->positioning;
pSpatializer->handedness = pConfig->handedness;
pSpatializer->minGain = pConfig->minGain;
pSpatializer->maxGain = pConfig->maxGain;
pSpatializer->minDistance = pConfig->minDistance;
pSpatializer->maxDistance = pConfig->maxDistance;
pSpatializer->rolloff = pConfig->rolloff;
pSpatializer->coneInnerAngleInRadians = pConfig->coneInnerAngleInRadians;
pSpatializer->coneOuterAngleInRadians = pConfig->coneOuterAngleInRadians;
pSpatializer->coneOuterGain = pConfig->coneOuterGain;
pSpatializer->dopplerFactor = pConfig->dopplerFactor;
pSpatializer->directionalAttenuationFactor = pConfig->directionalAttenuationFactor;
pSpatializer->gainSmoothTimeInFrames = pConfig->gainSmoothTimeInFrames;
pSpatializer->position = ma_vec3f_init_3f(0, 0, 0);
pSpatializer->direction = ma_vec3f_init_3f(0, 0, -1);
pSpatializer->velocity = ma_vec3f_init_3f(0, 0, 0);
pSpatializer->dopplerPitch = 1;
/* Swap the forward direction if we're left handed (it was initialized based on right handed). */
if (pSpatializer->handedness == ma_handedness_left) {
pSpatializer->direction = ma_vec3f_neg(pSpatializer->direction);
}
/* Channel map. This will be on the heap. */
if (pConfig->pChannelMapIn != NULL) {
pSpatializer->pChannelMapIn = (ma_channel*)ma_offset_ptr(pHeap, heapLayout.channelMapInOffset);
ma_channel_map_copy_or_default(pSpatializer->pChannelMapIn, pSpatializer->channelsIn, pConfig->pChannelMapIn, pSpatializer->channelsIn);
}
/* New channel gains for output channels. */
pSpatializer->pNewChannelGainsOut = (float*)ma_offset_ptr(pHeap, heapLayout.newChannelGainsOffset);
/* Gainer. */
gainerConfig = ma_spatializer_gainer_config_init(pConfig);
result = ma_gainer_init_preallocated(&gainerConfig, ma_offset_ptr(pHeap, heapLayout.gainerOffset), &pSpatializer->gainer);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the gainer. */
}
return MA_SUCCESS;
}
MA_API ma_result ma_spatializer_init(const ma_spatializer_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_spatializer* pSpatializer)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
/* We'll need a heap allocation to retrieve the size. */
result = ma_spatializer_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_spatializer_init_preallocated(pConfig, pHeap, pSpatializer);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pSpatializer->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_spatializer_uninit(ma_spatializer* pSpatializer, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pSpatializer == NULL) {
return;
}
ma_gainer_uninit(&pSpatializer->gainer, pAllocationCallbacks);
if (pSpatializer->_ownsHeap) {
ma_free(pSpatializer->_pHeap, pAllocationCallbacks);
}
}
static float ma_calculate_angular_gain(ma_vec3f dirA, ma_vec3f dirB, float coneInnerAngleInRadians, float coneOuterAngleInRadians, float coneOuterGain)
{
/*
Angular attenuation.
Unlike distance gain, the math for this is not specified by the OpenAL spec so we'll just go ahead and figure
this out for ourselves at the expense of possibly being inconsistent with other implementations.
To do cone attenuation, I'm just using the same math that we'd use to implement a basic spotlight in OpenGL. We
just need to get the direction from the source to the listener and then do a dot product against that and the
direction of the spotlight. Then we just compare that dot product against the cosine of the inner and outer
angles. If the dot product is greater than the the outer angle, we just use coneOuterGain. If it's less than
the inner angle, we just use a gain of 1. Otherwise we linearly interpolate between 1 and coneOuterGain.
*/
if (coneInnerAngleInRadians < 6.283185f) {
float angularGain = 1;
float cutoffInner = (float)ma_cosd(coneInnerAngleInRadians*0.5f);
float cutoffOuter = (float)ma_cosd(coneOuterAngleInRadians*0.5f);
float d;
d = ma_vec3f_dot(dirA, dirB);
if (d > cutoffInner) {
/* It's inside the inner angle. */
angularGain = 1;
} else {
/* It's outside the inner angle. */
if (d > cutoffOuter) {
/* It's between the inner and outer angle. We need to linearly interpolate between 1 and coneOuterGain. */
angularGain = ma_mix_f32(coneOuterGain, 1, (d - cutoffOuter) / (cutoffInner - cutoffOuter));
} else {
/* It's outside the outer angle. */
angularGain = coneOuterGain;
}
}
/*printf("d = %f; cutoffInner = %f; cutoffOuter = %f; angularGain = %f\n", d, cutoffInner, cutoffOuter, angularGain);*/
return angularGain;
} else {
/* Inner angle is 360 degrees so no need to do any attenuation. */
return 1;
}
}
MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer, ma_spatializer_listener* pListener, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
ma_channel* pChannelMapIn = pSpatializer->pChannelMapIn;
ma_channel* pChannelMapOut = pListener->config.pChannelMapOut;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
ma_result result;
ma_linear_resampler_heap_layout heapLayout;
if (pHeapSizeInBytes == NULL) {
return MA_INVALID_ARGS;
}
*pHeapSizeInBytes = 0;
result = ma_linear_resampler_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_linear_resampler_init_preallocated(const ma_linear_resampler_config* pConfig, void* pHeap, ma_linear_resampler* pResampler)
{
ma_result result;
ma_linear_resampler_heap_layout heapLayout;
if (pResampler == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pResampler);
result = ma_linear_resampler_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pResampler->config = *pConfig;
pResampler->_pHeap = pHeap;
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
if (pConfig->format == ma_format_f32) {
pResampler->x0.f32 = (float*)ma_offset_ptr(pHeap, heapLayout.x0Offset);
pResampler->x1.f32 = (float*)ma_offset_ptr(pHeap, heapLayout.x1Offset);
} else {
pResampler->x0.s16 = (ma_int16*)ma_offset_ptr(pHeap, heapLayout.x0Offset);
pResampler->x1.s16 = (ma_int16*)ma_offset_ptr(pHeap, heapLayout.x1Offset);
}
/* Setting the rate will set up the filter and time advances for us. */
result = ma_linear_resampler_set_rate_internal(pResampler, pHeap, &heapLayout, pConfig->sampleRateIn, pConfig->sampleRateOut, /* isResamplerAlreadyInitialized = */ MA_FALSE);
if (result != MA_SUCCESS) {
return result;
}
pResampler->inTimeInt = 1; /* Set this to one to force an input sample to always be loaded for the first output frame. */
pResampler->inTimeFrac = 0;
return MA_SUCCESS;
}
MA_API ma_result ma_linear_resampler_init(const ma_linear_resampler_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_linear_resampler* pResampler)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_linear_resampler_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_linear_resampler_init_preallocated(pConfig, pHeap, pResampler);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pResampler->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_linear_resampler_uninit(ma_linear_resampler* pResampler, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pResampler == NULL) {
return;
}
ma_lpf_uninit(&pResampler->lpf, pAllocationCallbacks);
if (pResampler->_ownsHeap) {
ma_free(pResampler->_pHeap, pAllocationCallbacks);
}
}
static MA_INLINE ma_int16 ma_linear_resampler_mix_s16(ma_int16 x, ma_int16 y, ma_int32 a, const ma_int32 shift)
{
ma_int32 b;
ma_int32 c;
ma_int32 r;
MA_ASSERT(a <= (1<<shift));
b = x * ((1<<shift) - a);
c = y * a;
r = b + c;
return (ma_int16)(r >> shift);
}
static void ma_linear_resampler_interpolate_frame_s16(ma_linear_resampler* pResampler, ma_int16* MA_RESTRICT pFrameOut)
{
ma_uint32 c;
ma_uint32 a;
const ma_uint32 channels = pResampler->config.channels;
const ma_uint32 shift = 12;
MA_ASSERT(pResampler != NULL);
MA_ASSERT(pFrameOut != NULL);
a = (pResampler->inTimeFrac << shift) / pResampler->config.sampleRateOut;
MA_ASSUME(channels > 0);
for (c = 0; c < channels; c += 1) {
ma_int16 s = ma_linear_resampler_mix_s16(pResampler->x0.s16[c], pResampler->x1.s16[c], a, shift);
pFrameOut[c] = s;
}
}
static void ma_linear_resampler_interpolate_frame_f32(ma_linear_resampler* pResampler, float* MA_RESTRICT pFrameOut)
{
ma_uint32 c;
float a;
const ma_uint32 channels = pResampler->config.channels;
MA_ASSERT(pResampler != NULL);
MA_ASSERT(pFrameOut != NULL);
a = (float)pResampler->inTimeFrac / pResampler->config.sampleRateOut;
MA_ASSUME(channels > 0);
for (c = 0; c < channels; c += 1) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pResampler->x0.f32[iChannel] = 0;
pResampler->x1.f32[iChannel] = 0;
}
} else {
for (iChannel = 0; iChannel < pResampler->config.channels; iChannel += 1) {
pResampler->x0.s16[iChannel] = 0;
pResampler->x1.s16[iChannel] = 0;
}
}
/* The low pass filter needs to have it's cache reset. */
ma_lpf_clear_cache(&pResampler->lpf);
return MA_SUCCESS;
}
/* Linear resampler backend vtable. */
static ma_linear_resampler_config ma_resampling_backend_get_config__linear(const ma_resampler_config* pConfig)
{
ma_linear_resampler_config linearConfig;
linearConfig = ma_linear_resampler_config_init(pConfig->format, pConfig->channels, pConfig->sampleRateIn, pConfig->sampleRateOut);
linearConfig.lpfOrder = pConfig->linear.lpfOrder;
return linearConfig;
}
static ma_result ma_resampling_backend_get_heap_size__linear(void* pUserData, const ma_resampler_config* pConfig, size_t* pHeapSizeInBytes)
{
ma_linear_resampler_config linearConfig;
(void)pUserData;
linearConfig = ma_resampling_backend_get_config__linear(pConfig);
return ma_linear_resampler_get_heap_size(&linearConfig, pHeapSizeInBytes);
}
static ma_result ma_resampling_backend_init__linear(void* pUserData, const ma_resampler_config* pConfig, void* pHeap, ma_resampling_backend** ppBackend)
{
ma_resampler* pResampler = (ma_resampler*)pUserData;
ma_result result;
ma_linear_resampler_config linearConfig;
(void)pUserData;
linearConfig = ma_resampling_backend_get_config__linear(pConfig);
result = ma_linear_resampler_init_preallocated(&linearConfig, pHeap, &pResampler->state.linear);
if (result != MA_SUCCESS) {
return result;
}
*ppBackend = &pResampler->state.linear;
return MA_SUCCESS;
}
static void ma_resampling_backend_uninit__linear(void* pUserData, ma_resampling_backend* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
(void)pUserData;
ma_linear_resampler_uninit((ma_linear_resampler*)pBackend, pAllocationCallbacks);
}
static ma_result ma_resampling_backend_process__linear(void* pUserData, ma_resampling_backend* pBackend, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
{
(void)pUserData;
return ma_linear_resampler_process_pcm_frames((ma_linear_resampler*)pBackend, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
}
static ma_result ma_resampling_backend_set_rate__linear(void* pUserData, ma_resampling_backend* pBackend, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
{
(void)pUserData;
return ma_linear_resampler_set_rate((ma_linear_resampler*)pBackend, sampleRateIn, sampleRateOut);
}
static ma_uint64 ma_resampling_backend_get_input_latency__linear(void* pUserData, const ma_resampling_backend* pBackend)
{
(void)pUserData;
return ma_linear_resampler_get_input_latency((const ma_linear_resampler*)pBackend);
}
static ma_uint64 ma_resampling_backend_get_output_latency__linear(void* pUserData, const ma_resampling_backend* pBackend)
{
(void)pUserData;
return ma_linear_resampler_get_output_latency((const ma_linear_resampler*)pBackend);
}
static ma_result ma_resampling_backend_get_required_input_frame_count__linear(void* pUserData, const ma_resampling_backend* pBackend, ma_uint64 outputFrameCount, ma_uint64* pInputFrameCount)
{
(void)pUserData;
return ma_linear_resampler_get_required_input_frame_count((const ma_linear_resampler*)pBackend, outputFrameCount, pInputFrameCount);
}
static ma_result ma_resampling_backend_get_expected_output_frame_count__linear(void* pUserData, const ma_resampling_backend* pBackend, ma_uint64 inputFrameCount, ma_uint64* pOutputFrameCount)
{
(void)pUserData;
return ma_linear_resampler_get_expected_output_frame_count((const ma_linear_resampler*)pBackend, inputFrameCount, pOutputFrameCount);
}
static ma_result ma_resampling_backend_reset__linear(void* pUserData, ma_resampling_backend* pBackend)
{
(void)pUserData;
return ma_linear_resampler_reset((ma_linear_resampler*)pBackend);
}
static ma_resampling_backend_vtable g_ma_linear_resampler_vtable =
{
ma_resampling_backend_get_heap_size__linear,
ma_resampling_backend_init__linear,
ma_resampling_backend_uninit__linear,
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
*pHeapSizeInBytes = 0;
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
result = ma_resampler_get_vtable(pConfig, NULL, &pVTable, &pVTableUserData);
if (result != MA_SUCCESS) {
return result;
}
if (pVTable == NULL || pVTable->onGetHeapSize == NULL) {
return MA_NOT_IMPLEMENTED;
}
result = pVTable->onGetHeapSize(pVTableUserData, pConfig, pHeapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_resampler_init_preallocated(const ma_resampler_config* pConfig, void* pHeap, ma_resampler* pResampler)
{
ma_result result;
if (pResampler == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pResampler);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
pResampler->_pHeap = pHeap;
pResampler->format = pConfig->format;
pResampler->channels = pConfig->channels;
pResampler->sampleRateIn = pConfig->sampleRateIn;
pResampler->sampleRateOut = pConfig->sampleRateOut;
result = ma_resampler_get_vtable(pConfig, pResampler, &pResampler->pBackendVTable, &pResampler->pBackendUserData);
if (result != MA_SUCCESS) {
return result;
}
if (pResampler->pBackendVTable == NULL || pResampler->pBackendVTable->onInit == NULL) {
return MA_NOT_IMPLEMENTED; /* onInit not implemented. */
}
result = pResampler->pBackendVTable->onInit(pResampler->pBackendUserData, pConfig, pHeap, &pResampler->pBackend);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_resampler_init(const ma_resampler_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_resampler* pResampler)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_resampler_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_resampler_init_preallocated(pConfig, pHeap, pResampler);
if (result != MA_SUCCESS) {
return result;
}
pResampler->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_resampler_uninit(ma_resampler* pResampler, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pResampler == NULL) {
return;
}
if (pResampler->pBackendVTable == NULL || pResampler->pBackendVTable->onUninit == NULL) {
return;
}
pResampler->pBackendVTable->onUninit(pResampler->pBackendUserData, pResampler->pBackend, pAllocationCallbacks);
if (pResampler->_ownsHeap) {
ma_free(pResampler->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_resampler_process_pcm_frames(ma_resampler* pResampler, const void* pFramesIn, ma_uint64* pFrameCountIn, void* pFramesOut, ma_uint64* pFrameCountOut)
{
if (pResampler == NULL) {
return MA_INVALID_ARGS;
}
if (pFrameCountOut == NULL && pFrameCountIn == NULL) {
return MA_INVALID_ARGS;
}
if (pResampler->pBackendVTable == NULL || pResampler->pBackendVTable->onProcess == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pResampler->pBackendVTable->onProcess(pResampler->pBackendUserData, pResampler->pBackend, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
}
MA_API ma_result ma_resampler_set_rate(ma_resampler* pResampler, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut)
{
ma_result result;
if (pResampler == NULL) {
return MA_INVALID_ARGS;
}
if (sampleRateIn == 0 || sampleRateOut == 0) {
return MA_INVALID_ARGS;
}
if (pResampler->pBackendVTable == NULL || pResampler->pBackendVTable->onSetRate == NULL) {
return MA_NOT_IMPLEMENTED;
}
result = pResampler->pBackendVTable->onSetRate(pResampler->pBackendUserData, pResampler->pBackend, sampleRateIn, sampleRateOut);
if (result != MA_SUCCESS) {
return result;
}
pResampler->sampleRateIn = sampleRateIn;
pResampler->sampleRateOut = sampleRateOut;
return MA_SUCCESS;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (ma_is_spatial_channel_position(channelPosOut)) {
float weight = 0;
if (pConverter->mixingMode == ma_channel_mix_mode_rectangular) {
weight = ma_calculate_channel_position_rectangular_weight(channelPosIn, channelPosOut);
}
/* Only apply the weight if we haven't already got some contribution from the respective channels. */
if (pConverter->format == ma_format_f32) {
if (pConverter->weights.f32[iChannelIn][iChannelOut] == 0) {
pConverter->weights.f32[iChannelIn][iChannelOut] = weight;
}
} else {
if (pConverter->weights.s16[iChannelIn][iChannelOut] == 0) {
pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(weight);
}
}
}
}
}
}
}
/* Unmapped output channels. */
for (iChannelOut = 0; iChannelOut < pConverter->channelsOut; ++iChannelOut) {
ma_channel channelPosOut = pConverter->pChannelMapOut[iChannelOut];
if (ma_is_spatial_channel_position(channelPosOut)) {
if (!ma_channel_map_contains_channel_position(pConverter->channelsIn, pConverter->pChannelMapIn, channelPosOut)) {
for (iChannelIn = 0; iChannelIn < pConverter->channelsIn; ++iChannelIn) {
ma_channel channelPosIn = pConverter->pChannelMapIn[iChannelIn];
if (ma_is_spatial_channel_position(channelPosIn)) {
float weight = 0;
if (pConverter->mixingMode == ma_channel_mix_mode_rectangular) {
weight = ma_calculate_channel_position_rectangular_weight(channelPosIn, channelPosOut);
}
/* Only apply the weight if we haven't already got some contribution from the respective channels. */
if (pConverter->format == ma_format_f32) {
if (pConverter->weights.f32[iChannelIn][iChannelOut] == 0) {
pConverter->weights.f32[iChannelIn][iChannelOut] = weight;
}
} else {
if (pConverter->weights.s16[iChannelIn][iChannelOut] == 0) {
pConverter->weights.s16[iChannelIn][iChannelOut] = ma_channel_converter_float_to_fixed(weight);
}
}
}
}
}
}
}
} break;
}
}
return MA_SUCCESS;
}
MA_API ma_result ma_channel_converter_init(const ma_channel_converter_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_channel_converter* pConverter)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_channel_converter_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_channel_converter_init_preallocated(pConfig, pHeap, pConverter);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pConverter->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_channel_converter_uninit(ma_channel_converter* pConverter, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pConverter == NULL) {
return;
}
if (pConverter->_ownsHeap) {
ma_free(pConverter->_pHeap, pAllocationCallbacks);
}
}
static ma_result ma_channel_converter_process_pcm_frames__passthrough(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
MA_ASSERT(pConverter != NULL);
MA_ASSERT(pFramesOut != NULL);
MA_ASSERT(pFramesIn != NULL);
ma_copy_memory_64(pFramesOut, pFramesIn, frameCount * ma_get_bytes_per_frame(pConverter->format, pConverter->channelsOut));
return MA_SUCCESS;
}
static ma_result ma_channel_converter_process_pcm_frames__shuffle(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
MA_ASSERT(pConverter != NULL);
MA_ASSERT(pFramesOut != NULL);
MA_ASSERT(pFramesIn != NULL);
MA_ASSERT(pConverter->channelsIn == pConverter->channelsOut);
return ma_channel_map_apply_shuffle_table(pFramesOut, pConverter->channelsOut, pFramesIn, pConverter->channelsIn, frameCount, pConverter->pShuffleTable, pConverter->format);
}
static ma_result ma_channel_converter_process_pcm_frames__mono_in(ma_channel_converter* pConverter, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
ma_uint64 iFrame;
MA_ASSERT(pConverter != NULL);
MA_ASSERT(pFramesOut != NULL);
MA_ASSERT(pFramesIn != NULL);
MA_ASSERT(pConverter->channelsIn == 1);
switch (pConverter->format)
{
case ma_format_u8:
{
/* */ ma_uint8* pFramesOutU8 = ( ma_uint8*)pFramesOut;
const ma_uint8* pFramesInU8 = (const ma_uint8*)pFramesIn;
for (iFrame = 0; iFrame < frameCount; ++iFrame) {
ma_uint32 iChannel;
for (iChannel = 0; iChannel < pConverter->channelsOut; iChannel += 1) {
pFramesOutU8[iFrame*pConverter->channelsOut + iChannel] = pFramesInU8[iFrame];
}
}
} break;
case ma_format_s16:
{
/* */ ma_int16* pFramesOutS16 = ( ma_int16*)pFramesOut;
const ma_int16* pFramesInS16 = (const ma_int16*)pFramesIn;
if (pConverter->channelsOut == 2) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pConverter->hasPostFormatConversion = MA_FALSE;
} else {
/* The formats are different so we need to do either pre- or post-format conversion. It doesn't matter which. */
pConverter->hasPreFormatConversion = MA_FALSE;
pConverter->hasPostFormatConversion = MA_TRUE;
}
} else {
/* We have a channel converter and/or resampler so we'll need channel conversion based on the mid format. */
if (pConverter->formatIn != midFormat) {
pConverter->hasPreFormatConversion = MA_TRUE;
}
if (pConverter->formatOut != midFormat) {
pConverter->hasPostFormatConversion = MA_TRUE;
}
}
/* We can enable passthrough optimizations if applicable. Note that we'll only be able to do this if the sample rate is static. */
if (pConverter->hasPreFormatConversion == MA_FALSE &&
pConverter->hasPostFormatConversion == MA_FALSE &&
pConverter->hasChannelConverter == MA_FALSE &&
pConverter->hasResampler == MA_FALSE) {
pConverter->isPassthrough = MA_TRUE;
}
/* We now need to determine our execution path. */
if (pConverter->isPassthrough) {
pConverter->executionPath = ma_data_converter_execution_path_passthrough;
} else {
if (pConverter->channelsIn < pConverter->channelsOut) {
/* Do resampling first, if necessary. */
MA_ASSERT(pConverter->hasChannelConverter == MA_TRUE);
if (pConverter->hasResampler) {
pConverter->executionPath = ma_data_converter_execution_path_resample_first;
} else {
pConverter->executionPath = ma_data_converter_execution_path_channels_only;
}
} else {
/* Do channel conversion first, if necessary. */
if (pConverter->hasChannelConverter) {
if (pConverter->hasResampler) {
pConverter->executionPath = ma_data_converter_execution_path_channels_first;
} else {
pConverter->executionPath = ma_data_converter_execution_path_channels_only;
}
} else {
/* Channel routing not required. */
if (pConverter->hasResampler) {
pConverter->executionPath = ma_data_converter_execution_path_resample_only;
} else {
pConverter->executionPath = ma_data_converter_execution_path_format_only;
}
}
}
}
return MA_SUCCESS;
}
MA_API ma_result ma_data_converter_init(const ma_data_converter_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_converter* pConverter)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_data_converter_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_data_converter_init_preallocated(pConfig, pHeap, pConverter);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pConverter->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_data_converter_uninit(ma_data_converter* pConverter, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pConverter == NULL) {
return;
}
if (pConverter->hasResampler) {
ma_resampler_uninit(&pConverter->resampler, pAllocationCallbacks);
}
ma_channel_converter_uninit(&pConverter->channelConverter, pAllocationCallbacks);
if (pConverter->_ownsHeap) {
ma_free(pConverter->_pHeap, pAllocationCallbacks);
}
}
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)
{
ma_uint64 frameCountIn;
ma_uint64 frameCountOut;
ma_uint64 frameCount;
MA_ASSERT(pConverter != NULL);
frameCountIn = 0;
if (pFrameCountIn != NULL) {
frameCountIn = *pFrameCountIn;
}
frameCountOut = 0;
if (pFrameCountOut != NULL) {
frameCountOut = *pFrameCountOut;
}
frameCount = ma_min(frameCountIn, frameCountOut);
if (pFramesOut != NULL) {
if (pFramesIn != NULL) {
ma_copy_memory_64(pFramesOut, pFramesIn, frameCount * ma_get_bytes_per_frame(pConverter->formatOut, pConverter->channelsOut));
} else {
ma_zero_memory_64(pFramesOut, frameCount * ma_get_bytes_per_frame(pConverter->formatOut, pConverter->channelsOut));
}
}
if (pFrameCountIn != NULL) {
*pFrameCountIn = frameCount;
}
if (pFrameCountOut != NULL) {
*pFrameCountOut = frameCount;
}
return MA_SUCCESS;
}
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)
{
ma_uint64 frameCountIn;
ma_uint64 frameCountOut;
ma_uint64 frameCount;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}
frameCountIn -= framesProcessedIn;
}
}
}
} else {
result = ma_data_converter_process_pcm_frames(&converter, pIn, &frameCountIn, pOut, &frameCountOut);
if (result != MA_SUCCESS) {
frameCountOut = 0;
}
}
ma_data_converter_uninit(&converter, NULL);
return frameCountOut;
}
/**************************************************************************************************************************************************************
Ring Buffer
**************************************************************************************************************************************************************/
static MA_INLINE ma_uint32 ma_rb__extract_offset_in_bytes(ma_uint32 encodedOffset)
{
return encodedOffset & 0x7FFFFFFF;
}
static MA_INLINE ma_uint32 ma_rb__extract_offset_loop_flag(ma_uint32 encodedOffset)
{
return encodedOffset & 0x80000000;
}
static MA_INLINE void* ma_rb__get_read_ptr(ma_rb* pRB)
{
MA_ASSERT(pRB != NULL);
return ma_offset_ptr(pRB->pBuffer, ma_rb__extract_offset_in_bytes(c89atomic_load_32(&pRB->encodedReadOffset)));
}
static MA_INLINE void* ma_rb__get_write_ptr(ma_rb* pRB)
{
MA_ASSERT(pRB != NULL);
return ma_offset_ptr(pRB->pBuffer, ma_rb__extract_offset_in_bytes(c89atomic_load_32(&pRB->encodedWriteOffset)));
}
static MA_INLINE ma_uint32 ma_rb__construct_offset(ma_uint32 offsetInBytes, ma_uint32 offsetLoopFlag)
{
return offsetLoopFlag | offsetInBytes;
}
static MA_INLINE void ma_rb__deconstruct_offset(ma_uint32 encodedOffset, ma_uint32* pOffsetInBytes, ma_uint32* pOffsetLoopFlag)
{
MA_ASSERT(pOffsetInBytes != NULL);
MA_ASSERT(pOffsetLoopFlag != NULL);
*pOffsetInBytes = ma_rb__extract_offset_in_bytes(encodedOffset);
*pOffsetLoopFlag = ma_rb__extract_offset_loop_flag(encodedOffset);
}
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)
{
ma_result result;
const ma_uint32 maxSubBufferSize = 0x7FFFFFFF - (MA_SIMD_ALIGNMENT-1);
if (pRB == NULL) {
return MA_INVALID_ARGS;
}
if (subbufferSizeInBytes == 0 || subbufferCount == 0) {
return MA_INVALID_ARGS;
}
if (subbufferSizeInBytes > maxSubBufferSize) {
return MA_INVALID_ARGS; /* Maximum buffer size is ~2GB. The most significant bit is a flag for use internally. */
}
MA_ZERO_OBJECT(pRB);
result = ma_allocation_callbacks_init_copy(&pRB->allocationCallbacks, pAllocationCallbacks);
if (result != MA_SUCCESS) {
return result;
}
pRB->subbufferSizeInBytes = (ma_uint32)subbufferSizeInBytes;
pRB->subbufferCount = (ma_uint32)subbufferCount;
if (pOptionalPreallocatedBuffer != NULL) {
pRB->subbufferStrideInBytes = (ma_uint32)subbufferStrideInBytes;
pRB->pBuffer = pOptionalPreallocatedBuffer;
} else {
size_t bufferSizeInBytes;
/*
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
we need to make sure the stride is a multiple of MA_SIMD_ALIGNMENT.
*/
pRB->subbufferStrideInBytes = (pRB->subbufferSizeInBytes + (MA_SIMD_ALIGNMENT-1)) & ~MA_SIMD_ALIGNMENT;
bufferSizeInBytes = (size_t)pRB->subbufferCount*pRB->subbufferStrideInBytes;
pRB->pBuffer = ma_aligned_malloc(bufferSizeInBytes, MA_SIMD_ALIGNMENT, &pRB->allocationCallbacks);
if (pRB->pBuffer == NULL) {
return MA_OUT_OF_MEMORY;
}
MA_ZERO_MEMORY(pRB->pBuffer, bufferSizeInBytes);
pRB->ownsBuffer = MA_TRUE;
}
return MA_SUCCESS;
}
MA_API ma_result ma_rb_init(size_t bufferSizeInBytes, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_rb* pRB)
{
return ma_rb_init_ex(bufferSizeInBytes, 1, 0, pOptionalPreallocatedBuffer, pAllocationCallbacks, pRB);
}
MA_API void ma_rb_uninit(ma_rb* pRB)
{
if (pRB == NULL) {
return;
}
if (pRB->ownsBuffer) {
ma_aligned_free(pRB->pBuffer, &pRB->allocationCallbacks);
}
}
MA_API void ma_rb_reset(ma_rb* pRB)
{
if (pRB == NULL) {
return;
}
c89atomic_exchange_32(&pRB->encodedReadOffset, 0);
c89atomic_exchange_32(&pRB->encodedWriteOffset, 0);
}
MA_API ma_result ma_rb_acquire_read(ma_rb* pRB, size_t* pSizeInBytes, void** ppBufferOut)
{
ma_uint32 writeOffset;
ma_uint32 writeOffsetInBytes;
ma_uint32 writeOffsetLoopFlag;
ma_uint32 readOffset;
ma_uint32 readOffsetInBytes;
ma_uint32 readOffsetLoopFlag;
size_t bytesAvailable;
size_t bytesRequested;
if (pRB == NULL || pSizeInBytes == NULL || ppBufferOut == NULL) {
return MA_INVALID_ARGS;
}
/* The returned buffer should never move ahead of the write pointer. */
writeOffset = c89atomic_load_32(&pRB->encodedWriteOffset);
ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
readOffset = c89atomic_load_32(&pRB->encodedReadOffset);
ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
/*
The number of bytes available depends on whether or not the read and write pointers are on the same loop iteration. If so, we
can only read up to the write pointer. If not, we can only read up to the end of the buffer.
*/
if (readOffsetLoopFlag == writeOffsetLoopFlag) {
bytesAvailable = writeOffsetInBytes - readOffsetInBytes;
} else {
bytesAvailable = pRB->subbufferSizeInBytes - readOffsetInBytes;
}
bytesRequested = *pSizeInBytes;
if (bytesRequested > bytesAvailable) {
bytesRequested = bytesAvailable;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}
MA_API ma_uint32 ma_rb_available_write(ma_rb* pRB)
{
if (pRB == NULL) {
return 0;
}
return (ma_uint32)(ma_rb_get_subbuffer_size(pRB) - ma_rb_pointer_distance(pRB));
}
MA_API size_t ma_rb_get_subbuffer_size(ma_rb* pRB)
{
if (pRB == NULL) {
return 0;
}
return pRB->subbufferSizeInBytes;
}
MA_API size_t ma_rb_get_subbuffer_stride(ma_rb* pRB)
{
if (pRB == NULL) {
return 0;
}
if (pRB->subbufferStrideInBytes == 0) {
return (size_t)pRB->subbufferSizeInBytes;
}
return (size_t)pRB->subbufferStrideInBytes;
}
MA_API size_t ma_rb_get_subbuffer_offset(ma_rb* pRB, size_t subbufferIndex)
{
if (pRB == NULL) {
return 0;
}
return subbufferIndex * ma_rb_get_subbuffer_stride(pRB);
}
MA_API void* ma_rb_get_subbuffer_ptr(ma_rb* pRB, size_t subbufferIndex, void* pBuffer)
{
if (pRB == NULL) {
return NULL;
}
return ma_offset_ptr(pBuffer, ma_rb_get_subbuffer_offset(pRB, subbufferIndex));
}
static MA_INLINE ma_uint32 ma_pcm_rb_get_bpf(ma_pcm_rb* pRB)
{
MA_ASSERT(pRB != NULL);
return ma_get_bytes_per_frame(pRB->format, pRB->channels);
}
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* pAllocationCallba...
{
ma_uint32 bpf;
ma_result result;
if (pRB == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pRB);
bpf = ma_get_bytes_per_frame(format, channels);
if (bpf == 0) {
return MA_INVALID_ARGS;
}
result = ma_rb_init_ex(subbufferSizeInFrames*bpf, subbufferCount, subbufferStrideInFrames*bpf, pOptionalPreallocatedBuffer, pAllocationCallbacks, &pRB->rb);
if (result != MA_SUCCESS) {
return result;
}
pRB->format = format;
pRB->channels = channels;
return MA_SUCCESS;
}
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)
{
return ma_pcm_rb_init_ex(format, channels, bufferSizeInFrames, 1, 0, pOptionalPreallocatedBuffer, pAllocationCallbacks, pRB);
}
MA_API void ma_pcm_rb_uninit(ma_pcm_rb* pRB)
{
if (pRB == NULL) {
return;
}
ma_rb_uninit(&pRB->rb);
}
MA_API void ma_pcm_rb_reset(ma_pcm_rb* pRB)
{
if (pRB == NULL) {
return;
}
ma_rb_reset(&pRB->rb);
}
MA_API ma_result ma_pcm_rb_acquire_read(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut)
{
size_t sizeInBytes;
ma_result result;
if (pRB == NULL || pSizeInFrames == NULL) {
return MA_INVALID_ARGS;
}
sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
result = ma_rb_acquire_read(&pRB->rb, &sizeInBytes, ppBufferOut);
if (result != MA_SUCCESS) {
return result;
}
*pSizeInFrames = (ma_uint32)(sizeInBytes / (size_t)ma_pcm_rb_get_bpf(pRB));
return MA_SUCCESS;
}
MA_API ma_result ma_pcm_rb_commit_read(ma_pcm_rb* pRB, ma_uint32 sizeInFrames)
{
if (pRB == NULL) {
return MA_INVALID_ARGS;
}
return ma_rb_commit_read(&pRB->rb, sizeInFrames * ma_pcm_rb_get_bpf(pRB));
}
MA_API ma_result ma_pcm_rb_acquire_write(ma_pcm_rb* pRB, ma_uint32* pSizeInFrames, void** ppBufferOut)
{
size_t sizeInBytes;
ma_result result;
if (pRB == NULL) {
return MA_INVALID_ARGS;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
return ma_rb_pointer_distance(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
}
MA_API ma_uint32 ma_pcm_rb_available_read(ma_pcm_rb* pRB)
{
if (pRB == NULL) {
return 0;
}
return ma_rb_available_read(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
}
MA_API ma_uint32 ma_pcm_rb_available_write(ma_pcm_rb* pRB)
{
if (pRB == NULL) {
return 0;
}
return ma_rb_available_write(&pRB->rb) / ma_pcm_rb_get_bpf(pRB);
}
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_size(ma_pcm_rb* pRB)
{
if (pRB == NULL) {
return 0;
}
return (ma_uint32)(ma_rb_get_subbuffer_size(&pRB->rb) / ma_pcm_rb_get_bpf(pRB));
}
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_stride(ma_pcm_rb* pRB)
{
if (pRB == NULL) {
return 0;
}
return (ma_uint32)(ma_rb_get_subbuffer_stride(&pRB->rb) / ma_pcm_rb_get_bpf(pRB));
}
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_offset(ma_pcm_rb* pRB, ma_uint32 subbufferIndex)
{
if (pRB == NULL) {
return 0;
}
return (ma_uint32)(ma_rb_get_subbuffer_offset(&pRB->rb, subbufferIndex) / ma_pcm_rb_get_bpf(pRB));
}
MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferIndex, void* pBuffer)
{
if (pRB == NULL) {
return NULL;
}
return ma_rb_get_subbuffer_ptr(&pRB->rb, subbufferIndex, pBuffer);
}
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_dup...
{
ma_result result;
ma_uint32 sizeInFrames;
sizeInFrames = (ma_uint32)ma_calculate_frame_count_after_resampling(sampleRate, captureInternalSampleRate, captureInternalPeriodSizeInFrames * 5);
if (sizeInFrames == 0) {
return MA_INVALID_ARGS;
}
result = ma_pcm_rb_init(captureFormat, captureChannels, sizeInFrames, NULL, pAllocationCallbacks, &pRB->rb);
if (result != MA_SUCCESS) {
return result;
}
/* Seek forward a bit so we have a bit of a buffer in case of desyncs. */
ma_pcm_rb_seek_write((ma_pcm_rb*)pRB, captureInternalPeriodSizeInFrames * 2);
return MA_SUCCESS;
}
MA_API ma_result ma_duplex_rb_uninit(ma_duplex_rb* pRB)
{
ma_pcm_rb_uninit((ma_pcm_rb*)pRB);
return MA_SUCCESS;
}
/**************************************************************************************************************************************************************
Miscellaneous Helpers
**************************************************************************************************************************************************************/
MA_API const char* ma_result_description(ma_result result)
{
switch (result)
{
case MA_SUCCESS: return "No error";
case MA_ERROR: return "Unknown error";
case MA_INVALID_ARGS: return "Invalid argument";
case MA_INVALID_OPERATION: return "Invalid operation";
case MA_OUT_OF_MEMORY: return "Out of memory";
case MA_OUT_OF_RANGE: return "Out of range";
case MA_ACCESS_DENIED: return "Permission denied";
case MA_DOES_NOT_EXIST: return "Resource does not exist";
case MA_ALREADY_EXISTS: return "Resource already exists";
case MA_TOO_MANY_OPEN_FILES: return "Too many open files";
case MA_INVALID_FILE: return "Invalid file";
case MA_TOO_BIG: return "Too large";
case MA_PATH_TOO_LONG: return "Path too long";
case MA_NAME_TOO_LONG: return "Name too long";
case MA_NOT_DIRECTORY: return "Not a directory";
case MA_IS_DIRECTORY: return "Is a directory";
case MA_DIRECTORY_NOT_EMPTY: return "Directory not empty";
case MA_AT_END: return "At end";
case MA_NO_SPACE: return "No space available";
case MA_BUSY: return "Device or resource busy";
case MA_IO_ERROR: return "Input/output error";
case MA_INTERRUPT: return "Interrupted";
case MA_UNAVAILABLE: return "Resource unavailable";
case MA_ALREADY_IN_USE: return "Resource already in use";
case MA_BAD_ADDRESS: return "Bad address";
case MA_BAD_SEEK: return "Illegal seek";
case MA_BAD_PIPE: return "Broken pipe";
case MA_DEADLOCK: return "Deadlock";
case MA_TOO_MANY_LINKS: return "Too many links";
case MA_NOT_IMPLEMENTED: return "Not implemented";
case MA_NO_MESSAGE: return "No message of desired type";
case MA_BAD_MESSAGE: return "Invalid message";
case MA_NO_DATA_AVAILABLE: return "No data available";
case MA_INVALID_DATA: return "Invalid data";
case MA_TIMEOUT: return "Timeout";
case MA_NO_NETWORK: return "Network unavailable";
case MA_NOT_UNIQUE: return "Not unique";
case MA_NOT_SOCKET: return "Socket operation on non-socket";
case MA_NO_ADDRESS: return "Destination address required";
case MA_BAD_PROTOCOL: return "Protocol wrong type for socket";
case MA_PROTOCOL_UNAVAILABLE: return "Protocol not available";
case MA_PROTOCOL_NOT_SUPPORTED: return "Protocol not supported";
case MA_PROTOCOL_FAMILY_NOT_SUPPORTED: return "Protocol family not supported";
case MA_ADDRESS_FAMILY_NOT_SUPPORTED: return "Address family not supported";
case MA_SOCKET_NOT_SUPPORTED: return "Socket type not supported";
case MA_CONNECTION_RESET: return "Connection reset";
case MA_ALREADY_CONNECTED: return "Already connected";
case MA_NOT_CONNECTED: return "Not connected";
case MA_CONNECTION_REFUSED: return "Connection refused";
case MA_NO_HOST: return "No host";
case MA_IN_PROGRESS: return "Operation in progress";
case MA_CANCELLED: return "Operation cancelled";
case MA_MEMORY_ALREADY_MAPPED: return "Memory already mapped";
case MA_FORMAT_NOT_SUPPORTED: return "Format not supported";
case MA_DEVICE_TYPE_NOT_SUPPORTED: return "Device type not supported";
case MA_SHARE_MODE_NOT_SUPPORTED: return "Share mode not supported";
case MA_NO_BACKEND: return "No backend";
case MA_NO_DEVICE: return "No device";
case MA_API_NOT_FOUND: return "API not found";
case MA_INVALID_DEVICE_CONFIG: return "Invalid device config";
case MA_DEVICE_NOT_INITIALIZED: return "Device not initialized";
case MA_DEVICE_NOT_STARTED: return "Device not started";
case MA_FAILED_TO_INIT_BACKEND: return "Failed to initialize backend";
case MA_FAILED_TO_OPEN_BACKEND_DEVICE: return "Failed to open backend device";
case MA_FAILED_TO_START_BACKEND_DEVICE: return "Failed to start backend device";
case MA_FAILED_TO_STOP_BACKEND_DEVICE: return "Failed to stop backend device";
default: return "Unknown error";
}
}
MA_API void* ma_malloc(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
if (pAllocationCallbacks->onMalloc != NULL) {
return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
} else {
return NULL; /* Do not fall back to the default implementation. */
}
} else {
return ma__malloc_default(sz, NULL);
}
}
MA_API void* ma_calloc(size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
{
void* p = ma_malloc(sz, pAllocationCallbacks);
if (p != NULL) {
MA_ZERO_MEMORY(p, sz);
}
return p;
}
MA_API void* ma_realloc(void* p, size_t sz, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(p, sz, pAllocationCallbacks->pUserData);
} else {
return NULL; /* Do not fall back to the default implementation. */
}
} else {
return ma__realloc_default(p, sz, NULL);
}
}
MA_API void ma_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (p == NULL) {
return;
}
if (pAllocationCallbacks != NULL) {
if (pAllocationCallbacks->onFree != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
} else {
return; /* Do no fall back to the default implementation. */
}
} else {
ma__free_default(p, NULL);
}
}
MA_API void* ma_aligned_malloc(size_t sz, size_t alignment, const ma_allocation_callbacks* pAllocationCallbacks)
{
size_t extraBytes;
void* pUnaligned;
void* pAligned;
if (alignment == 0) {
return 0;
}
extraBytes = alignment-1 + sizeof(void*);
pUnaligned = ma_malloc(sz + extraBytes, pAllocationCallbacks);
if (pUnaligned == NULL) {
return NULL;
}
pAligned = (void*)(((ma_uintptr)pUnaligned + extraBytes) & ~((ma_uintptr)(alignment-1)));
((void**)pAligned)[-1] = pUnaligned;
return pAligned;
}
MA_API void ma_aligned_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_free(((void**)p)[-1], pAllocationCallbacks);
}
MA_API const char* ma_get_format_name(ma_format format)
{
switch (format)
{
case ma_format_unknown: return "Unknown";
case ma_format_u8: return "8-bit Unsigned Integer";
case ma_format_s16: return "16-bit Signed Integer";
case ma_format_s24: return "24-bit Signed Integer (Tightly Packed)";
case ma_format_s32: return "32-bit Signed Integer";
case ma_format_f32: return "32-bit IEEE Floating Point";
default: return "Invalid";
}
}
MA_API void ma_blend_f32(float* pOut, float* pInA, float* pInB, float factor, ma_uint32 channels)
{
ma_uint32 i;
for (i = 0; i < channels; ++i) {
pOut[i] = ma_mix_f32(pInA[i], pInB[i], factor);
}
}
MA_API ma_uint32 ma_get_bytes_per_sample(ma_format format)
{
ma_uint32 sizes[] = {
0, /* unknown */
1, /* u8 */
2, /* s16 */
3, /* s24 */
4, /* s32 */
4, /* f32 */
};
return sizes[format];
}
MA_API ma_data_source_config ma_data_source_config_init(void)
{
ma_data_source_config config;
MA_ZERO_OBJECT(&config);
return config;
}
MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_data_source* pDataSource)
{
ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
if (pDataSource == NULL) {
return MA_INVALID_ARGS;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}
MA_API ma_result ma_audio_buffer_ref_get_cursor_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pCursor)
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0;
if (pAudioBufferRef == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = pAudioBufferRef->cursor;
return MA_SUCCESS;
}
MA_API ma_result ma_audio_buffer_ref_get_length_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pLength)
{
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0;
if (pAudioBufferRef == NULL) {
return MA_INVALID_ARGS;
}
*pLength = pAudioBufferRef->sizeInFrames;
return MA_SUCCESS;
}
MA_API ma_result ma_audio_buffer_ref_get_available_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pAvailableFrames)
{
if (pAvailableFrames == NULL) {
return MA_INVALID_ARGS;
}
*pAvailableFrames = 0;
if (pAudioBufferRef == NULL) {
return MA_INVALID_ARGS;
}
if (pAudioBufferRef->sizeInFrames <= pAudioBufferRef->cursor) {
*pAvailableFrames = 0;
} else {
*pAvailableFrames = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
}
return MA_SUCCESS;
}
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)
{
ma_audio_buffer_config config;
MA_ZERO_OBJECT(&config);
config.format = format;
config.channels = channels;
config.sampleRate = 0; /* TODO: Version 0.12. Set this to sampleRate. */
config.sizeInFrames = sizeInFrames;
config.pData = pData;
ma_allocation_callbacks_init_copy(&config.allocationCallbacks, pAllocationCallbacks);
return config;
}
static ma_result ma_audio_buffer_init_ex(const ma_audio_buffer_config* pConfig, ma_bool32 doCopy, ma_audio_buffer* pAudioBuffer)
{
ma_result result;
if (pAudioBuffer == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_MEMORY(pAudioBuffer, sizeof(*pAudioBuffer) - sizeof(pAudioBuffer->_pExtraData)); /* Safety. Don't overwrite the extra data. */
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->sizeInFrames == 0) {
return MA_INVALID_ARGS; /* Not allowing buffer sizes of 0 frames. */
}
result = ma_audio_buffer_ref_init(pConfig->format, pConfig->channels, NULL, 0, &pAudioBuffer->ref);
if (result != MA_SUCCESS) {
return result;
}
/* TODO: Version 0.12. Set this in ma_audio_buffer_ref_init() instead of here. */
pAudioBuffer->ref.sampleRate = pConfig->sampleRate;
ma_allocation_callbacks_init_copy(&pAudioBuffer->allocationCallbacks, &pConfig->allocationCallbacks);
if (doCopy) {
ma_uint64 allocationSizeInBytes;
void* pData;
allocationSizeInBytes = pConfig->sizeInFrames * ma_get_bytes_per_frame(pConfig->format, pConfig->channels);
if (allocationSizeInBytes > MA_SIZE_MAX) {
return MA_OUT_OF_MEMORY; /* Too big. */
}
pData = ma_malloc((size_t)allocationSizeInBytes, &pAudioBuffer->allocationCallbacks); /* Safe cast to size_t. */
if (pData == NULL) {
return MA_OUT_OF_MEMORY;
}
if (pConfig->pData != NULL) {
ma_copy_pcm_frames(pData, pConfig->pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
} else {
ma_silence_pcm_frames(pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
}
ma_audio_buffer_ref_set_data(&pAudioBuffer->ref, pData, pConfig->sizeInFrames);
pAudioBuffer->ownsData = MA_TRUE;
} else {
ma_audio_buffer_ref_set_data(&pAudioBuffer->ref, pConfig->pData, pConfig->sizeInFrames);
pAudioBuffer->ownsData = MA_FALSE;
}
return MA_SUCCESS;
}
static void ma_audio_buffer_uninit_ex(ma_audio_buffer* pAudioBuffer, ma_bool32 doFree)
{
if (pAudioBuffer == NULL) {
return;
}
if (pAudioBuffer->ownsData && pAudioBuffer->ref.pData != &pAudioBuffer->_pExtraData[0]) {
ma_free((void*)pAudioBuffer->ref.pData, &pAudioBuffer->allocationCallbacks); /* Naugty const cast, but OK in this case since we've guarded it with the ownsData check. */
}
if (doFree) {
ma_free(pAudioBuffer, &pAudioBuffer->allocationCallbacks);
}
ma_audio_buffer_ref_uninit(&pAudioBuffer->ref);
}
MA_API ma_result ma_audio_buffer_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer)
{
return ma_audio_buffer_init_ex(pConfig, MA_FALSE, pAudioBuffer);
}
MA_API ma_result ma_audio_buffer_init_copy(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer)
{
return ma_audio_buffer_init_ex(pConfig, MA_TRUE, pAudioBuffer);
}
MA_API ma_result ma_audio_buffer_alloc_and_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer** ppAudioBuffer)
{
ma_result result;
ma_audio_buffer* pAudioBuffer;
ma_audio_buffer_config innerConfig; /* We'll be making some changes to the config, so need to make a copy. */
ma_uint64 allocationSizeInBytes;
if (ppAudioBuffer == NULL) {
return MA_INVALID_ARGS;
}
*ppAudioBuffer = NULL; /* Safety. */
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
innerConfig = *pConfig;
ma_allocation_callbacks_init_copy(&innerConfig.allocationCallbacks, &pConfig->allocationCallbacks);
allocationSizeInBytes = sizeof(*pAudioBuffer) - sizeof(pAudioBuffer->_pExtraData) + (pConfig->sizeInFrames * ma_get_bytes_per_frame(pConfig->format, pConfig->channels));
if (allocationSizeInBytes > MA_SIZE_MAX) {
return MA_OUT_OF_MEMORY; /* Too big. */
}
pAudioBuffer = (ma_audio_buffer*)ma_malloc((size_t)allocationSizeInBytes, &innerConfig.allocationCallbacks); /* Safe cast to size_t. */
if (pAudioBuffer == NULL) {
return MA_OUT_OF_MEMORY;
}
if (pConfig->pData != NULL) {
ma_copy_pcm_frames(&pAudioBuffer->_pExtraData[0], pConfig->pData, pConfig->sizeInFrames, pConfig->format, pConfig->channels);
} else {
ma_silence_pcm_frames(&pAudioBuffer->_pExtraData[0], pConfig->sizeInFrames, pConfig->format, pConfig->channels);
}
innerConfig.pData = &pAudioBuffer->_pExtraData[0];
result = ma_audio_buffer_init_ex(&innerConfig, MA_FALSE, pAudioBuffer);
if (result != MA_SUCCESS) {
ma_free(pAudioBuffer, &innerConfig.allocationCallbacks);
return result;
}
*ppAudioBuffer = pAudioBuffer;
return MA_SUCCESS;
}
MA_API void ma_audio_buffer_uninit(ma_audio_buffer* pAudioBuffer)
{
ma_audio_buffer_uninit_ex(pAudioBuffer, MA_FALSE);
}
MA_API void ma_audio_buffer_uninit_and_free(ma_audio_buffer* pAudioBuffer)
{
ma_audio_buffer_uninit_ex(pAudioBuffer, MA_TRUE);
}
MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer* pAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop)
{
if (pAudioBuffer == NULL) {
return 0;
}
return ma_audio_buffer_ref_read_pcm_frames(&pAudioBuffer->ref, pFramesOut, frameCount, loop);
}
MA_API ma_result ma_audio_buffer_seek_to_pcm_frame(ma_audio_buffer* pAudioBuffer, ma_uint64 frameIndex)
{
if (pAudioBuffer == NULL) {
return MA_INVALID_ARGS;
}
return ma_audio_buffer_ref_seek_to_pcm_frame(&pAudioBuffer->ref, frameIndex);
}
MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount)
{
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
{
if (pAudioBuffer == NULL) {
return MA_FALSE;
}
return ma_audio_buffer_ref_at_end(&pAudioBuffer->ref);
}
MA_API ma_result ma_audio_buffer_get_cursor_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pCursor)
{
if (pAudioBuffer == NULL) {
return MA_INVALID_ARGS;
}
return ma_audio_buffer_ref_get_cursor_in_pcm_frames(&pAudioBuffer->ref, pCursor);
}
MA_API ma_result ma_audio_buffer_get_length_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pLength)
{
if (pAudioBuffer == NULL) {
return MA_INVALID_ARGS;
}
return ma_audio_buffer_ref_get_length_in_pcm_frames(&pAudioBuffer->ref, pLength);
}
MA_API ma_result ma_audio_buffer_get_available_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames)
{
if (pAvailableFrames == NULL) {
return MA_INVALID_ARGS;
}
*pAvailableFrames = 0;
if (pAudioBuffer == NULL) {
return MA_INVALID_ARGS;
}
return ma_audio_buffer_ref_get_available_frames(&pAudioBuffer->ref, pAvailableFrames);
}
MA_API ma_result ma_paged_audio_buffer_data_init(ma_format format, ma_uint32 channels, ma_paged_audio_buffer_data* pData)
{
if (pData == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pData);
pData->format = format;
pData->channels = channels;
pData->pTail = &pData->head;
return MA_SUCCESS;
}
MA_API void ma_paged_audio_buffer_data_uninit(ma_paged_audio_buffer_data* pData, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_paged_audio_buffer_page* pPage;
if (pData == NULL) {
return;
}
/* All pages need to be freed. */
pPage = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&pData->head.pNext);
while (pPage != NULL) {
ma_paged_audio_buffer_page* pNext = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&pPage->pNext);
ma_free(pPage, pAllocationCallbacks);
pPage = pNext;
}
}
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_head(ma_paged_audio_buffer_data* pData)
{
if (pData == NULL) {
return NULL;
}
return &pData->head;
}
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_tail(ma_paged_audio_buffer_data* pData)
{
if (pData == NULL) {
return NULL;
}
return pData->pTail;
}
MA_API ma_result ma_paged_audio_buffer_data_get_length_in_pcm_frames(ma_paged_audio_buffer_data* pData, ma_uint64* pLength)
{
ma_paged_audio_buffer_page* pPage;
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0;
if (pData == NULL) {
return MA_INVALID_ARGS;
}
/* Calculate the length from the linked list. */
for (pPage = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&pData->head.pNext); pPage != NULL; pPage = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&pPage->pNext)) {
*pLength += pPage->sizeInFrames;
}
return MA_SUCCESS;
}
MA_API ma_result ma_paged_audio_buffer_data_allocate_page(ma_paged_audio_buffer_data* pData, ma_uint64 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks, ma_paged_audio_buffer_page** ppPage)
{
ma_paged_audio_buffer_page* pPage;
ma_uint64 allocationSize;
if (ppPage == NULL) {
return MA_INVALID_ARGS;
}
*ppPage = NULL;
if (pData == NULL) {
return MA_INVALID_ARGS;
}
allocationSize = sizeof(*pPage) + (pageSizeInFrames * ma_get_bytes_per_frame(pData->format, pData->channels));
if (allocationSize > MA_SIZE_MAX) {
return MA_OUT_OF_MEMORY; /* Too big. */
}
pPage = (ma_paged_audio_buffer_page*)ma_malloc((size_t)allocationSize, pAllocationCallbacks); /* Safe cast to size_t. */
if (pPage == NULL) {
return MA_OUT_OF_MEMORY;
}
pPage->pNext = NULL;
pPage->sizeInFrames = pageSizeInFrames;
if (pInitialData != NULL) {
ma_copy_pcm_frames(pPage->pAudioData, pInitialData, pageSizeInFrames, pData->format, pData->channels);
}
*ppPage = pPage;
return MA_SUCCESS;
}
MA_API ma_result ma_paged_audio_buffer_data_free_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pData == NULL || pPage == NULL) {
return MA_INVALID_ARGS;
}
/* It's assumed the page is not attached to the list. */
ma_free(pPage, pAllocationCallbacks);
return MA_SUCCESS;
}
MA_API ma_result ma_paged_audio_buffer_data_append_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage)
{
if (pData == NULL || pPage == NULL) {
return MA_INVALID_ARGS;
}
/* This function assumes the page has been filled with audio data by this point. As soon as we append, the page will be available for reading. */
/* First thing to do is update the tail. */
for (;;) {
ma_paged_audio_buffer_page* pOldTail = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&pData->pTail);
ma_paged_audio_buffer_page* pNewTail = pPage;
if (c89atomic_compare_exchange_weak_ptr((volatile void**)&pData->pTail, (void**)&pOldTail, pNewTail)) {
/* Here is where we append the page to the list. After this, the page is attached to the list and ready to be read from. */
c89atomic_exchange_ptr(&pOldTail->pNext, pPage);
break; /* Done. */
}
}
return MA_SUCCESS;
}
MA_API ma_result ma_paged_audio_buffer_data_allocate_and_append_page(ma_paged_audio_buffer_data* pData, ma_uint32 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_result result;
ma_paged_audio_buffer_page* pPage;
result = ma_paged_audio_buffer_data_allocate_page(pData, pageSizeInFrames, pInitialData, pAllocationCallbacks, &pPage);
if (result != MA_SUCCESS) {
return result;
}
return ma_paged_audio_buffer_data_append_page(pData, pPage); /* <-- Should never fail. */
}
MA_API ma_paged_audio_buffer_config ma_paged_audio_buffer_config_init(ma_paged_audio_buffer_data* pData)
{
ma_paged_audio_buffer_config config;
MA_ZERO_OBJECT(&config);
config.pData = pData;
return config;
}
static ma_result ma_paged_audio_buffer__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
return ma_paged_audio_buffer_read_pcm_frames((ma_paged_audio_buffer*)pDataSource, pFramesOut, frameCount, pFramesRead);
}
static ma_result ma_paged_audio_buffer__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
return ma_paged_audio_buffer_seek_to_pcm_frame((ma_paged_audio_buffer*)pDataSource, frameIndex);
}
static ma_result ma_paged_audio_buffer__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
ma_paged_audio_buffer* pPagedAudioBuffer = (ma_paged_audio_buffer*)pDataSource;
*pFormat = pPagedAudioBuffer->pData->format;
*pChannels = pPagedAudioBuffer->pData->channels;
*pSampleRate = 0; /* There is no notion of a sample rate with audio buffers. */
ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pPagedAudioBuffer->pData->channels);
return MA_SUCCESS;
}
static ma_result ma_paged_audio_buffer__data_source_on_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
return ma_paged_audio_buffer_get_cursor_in_pcm_frames((ma_paged_audio_buffer*)pDataSource, pCursor);
}
static ma_result ma_paged_audio_buffer__data_source_on_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
return ma_paged_audio_buffer_get_length_in_pcm_frames((ma_paged_audio_buffer*)pDataSource, pLength);
}
static ma_data_source_vtable g_ma_paged_audio_buffer_data_source_vtable =
{
ma_paged_audio_buffer__data_source_on_read,
ma_paged_audio_buffer__data_source_on_seek,
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (frameIndex > pPagedAudioBuffer->absoluteCursor) {
/* Moving forward. */
ma_paged_audio_buffer_page* pPage;
ma_uint64 runningCursor = 0;
for (pPage = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&ma_paged_audio_buffer_data_get_head(pPagedAudioBuffer->pData)->pNext); pPage != NULL; pPage = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&pPage->pNext)) {
ma_uint64 pageRangeBeg = runningCursor;
ma_uint64 pageRangeEnd = pageRangeBeg + pPage->sizeInFrames;
if (frameIndex >= pageRangeBeg) {
if (frameIndex < pageRangeEnd || (frameIndex == pageRangeEnd && pPage == (ma_paged_audio_buffer_page*)c89atomic_load_ptr(ma_paged_audio_buffer_data_get_tail(pPagedAudioBuffer->pData)))) { /* A small edge case - allow seeking to the v...
/* We found the page. */
pPagedAudioBuffer->pCurrent = pPage;
pPagedAudioBuffer->absoluteCursor = frameIndex;
pPagedAudioBuffer->relativeCursor = frameIndex - pageRangeBeg;
return MA_SUCCESS;
}
}
runningCursor = pageRangeEnd;
}
/* Getting here means we tried seeking too far forward. Don't change any state. */
return MA_BAD_SEEK;
}
return MA_SUCCESS;
}
MA_API ma_result ma_paged_audio_buffer_get_cursor_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pCursor)
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0; /* Safety. */
if (pPagedAudioBuffer == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = pPagedAudioBuffer->absoluteCursor;
return MA_SUCCESS;
}
MA_API ma_result ma_paged_audio_buffer_get_length_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pLength)
{
return ma_paged_audio_buffer_data_get_length_in_pcm_frames(pPagedAudioBuffer->pData, pLength);
}
/**************************************************************************************************************************************************************
VFS
**************************************************************************************************************************************************************/
MA_API ma_result ma_vfs_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
if (pFile == NULL) {
return MA_INVALID_ARGS;
}
*pFile = NULL;
if (pVFS == NULL || pFilePath == NULL || openMode == 0) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onOpen == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onOpen(pVFS, pFilePath, openMode, pFile);
}
MA_API ma_result ma_vfs_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
if (pFile == NULL) {
return MA_INVALID_ARGS;
}
*pFile = NULL;
if (pVFS == NULL || pFilePath == NULL || openMode == 0) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onOpenW == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onOpenW(pVFS, pFilePath, openMode, pFile);
}
MA_API ma_result ma_vfs_close(ma_vfs* pVFS, ma_vfs_file file)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
if (pVFS == NULL || file == NULL) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onClose == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onClose(pVFS, file);
}
MA_API ma_result ma_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
ma_result result;
size_t bytesRead;
if (pBytesRead != NULL) {
*pBytesRead = 0;
}
if (pVFS == NULL || file == NULL || pDst == NULL) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onRead == NULL) {
return MA_NOT_IMPLEMENTED;
}
result = pCallbacks->onRead(pVFS, file, pDst, sizeInBytes, &bytesRead);
if (pBytesRead != NULL) {
*pBytesRead = bytesRead;
}
if (result == MA_SUCCESS && bytesRead == 0 && sizeInBytes > 0) {
result = MA_AT_END;
}
return result;
}
MA_API ma_result ma_vfs_write(ma_vfs* pVFS, ma_vfs_file file, const void* pSrc, size_t sizeInBytes, size_t* pBytesWritten)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
if (pBytesWritten != NULL) {
*pBytesWritten = 0;
}
if (pVFS == NULL || file == NULL || pSrc == NULL) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onWrite == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onWrite(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
}
MA_API ma_result ma_vfs_seek(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
if (pVFS == NULL || file == NULL) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onSeek == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onSeek(pVFS, file, offset, origin);
}
MA_API ma_result ma_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0;
if (pVFS == NULL || file == NULL) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onTell == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onTell(pVFS, file, pCursor);
}
MA_API ma_result ma_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo)
{
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
if (pInfo == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pInfo);
if (pVFS == NULL || file == NULL) {
return MA_INVALID_ARGS;
}
if (pCallbacks->onInfo == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pCallbacks->onInfo(pVFS, file, pInfo);
}
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_result result;
ma_vfs_file file;
ma_file_info info;
void* pData;
size_t bytesRead;
if (ppData != NULL) {
*ppData = NULL;
}
if (pSize != NULL) {
*pSize = 0;
}
if (ppData == NULL) {
return MA_INVALID_ARGS;
}
if (pFilePath != NULL) {
result = ma_vfs_open(pVFS, pFilePath, MA_OPEN_MODE_READ, &file);
} else {
result = ma_vfs_open_w(pVFS, pFilePathW, MA_OPEN_MODE_READ, &file);
}
if (result != MA_SUCCESS) {
return result;
}
result = ma_vfs_info(pVFS, file, &info);
if (result != MA_SUCCESS) {
ma_vfs_close(pVFS, file);
return result;
}
if (info.sizeInBytes > MA_SIZE_MAX) {
ma_vfs_close(pVFS, file);
return MA_TOO_BIG;
}
pData = ma_malloc((size_t)info.sizeInBytes, pAllocationCallbacks); /* Safe cast. */
if (pData == NULL) {
ma_vfs_close(pVFS, file);
return result;
}
result = ma_vfs_read(pVFS, file, pData, (size_t)info.sizeInBytes, &bytesRead); /* Safe cast. */
ma_vfs_close(pVFS, file);
if (result != MA_SUCCESS) {
ma_free(pData, pAllocationCallbacks);
return result;
}
if (pSize != NULL) {
*pSize = bytesRead;
}
MA_ASSERT(ppData != NULL);
*ppData = pData;
return MA_SUCCESS;
}
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)
{
return ma_vfs_open_and_read_file_ex(pVFS, pFilePath, NULL, ppData, pSize, pAllocationCallbacks);
}
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)
{
return ma_vfs_open_and_read_file_ex(pVFS, NULL, pFilePath, ppData, pSize, pAllocationCallbacks);
}
#if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
static void ma_default_vfs__get_open_settings_win32(ma_uint32 openMode, DWORD* pDesiredAccess, DWORD* pShareMode, DWORD* pCreationDisposition)
{
*pDesiredAccess = 0;
if ((openMode & MA_OPEN_MODE_READ) != 0) {
*pDesiredAccess |= GENERIC_READ;
}
if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
*pDesiredAccess |= GENERIC_WRITE;
}
*pShareMode = 0;
if ((openMode & MA_OPEN_MODE_READ) != 0) {
*pShareMode |= FILE_SHARE_READ;
}
if ((openMode & MA_OPEN_MODE_WRITE) != 0) {
*pCreationDisposition = CREATE_ALWAYS; /* Opening in write mode. Truncate. */
} else {
*pCreationDisposition = OPEN_EXISTING; /* Opening in read mode. File must exist. */
}
}
static ma_result ma_default_vfs_open__win32(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
{
HANDLE hFile;
DWORD dwDesiredAccess;
DWORD dwShareMode;
DWORD dwCreationDisposition;
(void)pVFS;
ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
hFile = CreateFileA(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return ma_result_from_GetLastError(GetLastError());
}
*pFile = hFile;
return MA_SUCCESS;
}
static ma_result ma_default_vfs_open_w__win32(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
{
HANDLE hFile;
DWORD dwDesiredAccess;
DWORD dwShareMode;
DWORD dwCreationDisposition;
(void)pVFS;
ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
hFile = CreateFileW(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
return ma_default_vfs_write__win32(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
#else
return ma_default_vfs_write__stdio(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
#endif
}
static ma_result ma_default_vfs_seek(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
{
if (file == NULL) {
return MA_INVALID_ARGS;
}
#if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
return ma_default_vfs_seek__win32(pVFS, file, offset, origin);
#else
return ma_default_vfs_seek__stdio(pVFS, file, offset, origin);
#endif
}
static ma_result ma_default_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0;
if (file == NULL) {
return MA_INVALID_ARGS;
}
#if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
return ma_default_vfs_tell__win32(pVFS, file, pCursor);
#else
return ma_default_vfs_tell__stdio(pVFS, file, pCursor);
#endif
}
static ma_result ma_default_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo)
{
if (pInfo == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pInfo);
if (file == NULL) {
return MA_INVALID_ARGS;
}
#if defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO)
return ma_default_vfs_info__win32(pVFS, file, pInfo);
#else
return ma_default_vfs_info__stdio(pVFS, file, pInfo);
#endif
}
MA_API ma_result ma_default_vfs_init(ma_default_vfs* pVFS, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pVFS == NULL) {
return MA_INVALID_ARGS;
}
pVFS->cb.onOpen = ma_default_vfs_open;
pVFS->cb.onOpenW = ma_default_vfs_open_w;
pVFS->cb.onClose = ma_default_vfs_close;
pVFS->cb.onRead = ma_default_vfs_read;
pVFS->cb.onWrite = ma_default_vfs_write;
pVFS->cb.onSeek = ma_default_vfs_seek;
pVFS->cb.onTell = ma_default_vfs_tell;
pVFS->cb.onInfo = ma_default_vfs_info;
ma_allocation_callbacks_init_copy(&pVFS->allocationCallbacks, pAllocationCallbacks);
return MA_SUCCESS;
}
MA_API ma_result ma_vfs_or_default_open(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
{
if (pVFS != NULL) {
return ma_vfs_open(pVFS, pFilePath, openMode, pFile);
} else {
return ma_default_vfs_open(pVFS, pFilePath, openMode, pFile);
}
}
MA_API ma_result ma_vfs_or_default_open_w(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
{
if (pVFS != NULL) {
return ma_vfs_open_w(pVFS, pFilePath, openMode, pFile);
} else {
return ma_default_vfs_open_w(pVFS, pFilePath, openMode, pFile);
}
}
MA_API ma_result ma_vfs_or_default_close(ma_vfs* pVFS, ma_vfs_file file)
{
if (pVFS != NULL) {
return ma_vfs_close(pVFS, file);
} else {
return ma_default_vfs_close(pVFS, file);
}
}
MA_API ma_result ma_vfs_or_default_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t sizeInBytes, size_t* pBytesRead)
{
if (pVFS != NULL) {
return ma_vfs_read(pVFS, file, pDst, sizeInBytes, pBytesRead);
} else {
return ma_default_vfs_read(pVFS, file, pDst, sizeInBytes, pBytesRead);
}
}
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)
{
if (pVFS != NULL) {
return ma_vfs_write(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
} else {
return ma_default_vfs_write(pVFS, file, pSrc, sizeInBytes, pBytesWritten);
}
}
MA_API ma_result ma_vfs_or_default_seek(ma_vfs* pVFS, ma_vfs_file file, ma_int64 offset, ma_seek_origin origin)
{
if (pVFS != NULL) {
return ma_vfs_seek(pVFS, file, offset, origin);
} else {
return ma_default_vfs_seek(pVFS, file, offset, origin);
}
}
MA_API ma_result ma_vfs_or_default_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* pCursor)
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#define DRWAV_NO_HOST -49
#define DRWAV_IN_PROGRESS -50
#define DRWAV_CANCELLED -51
#define DRWAV_MEMORY_ALREADY_MAPPED -52
#define DRWAV_AT_END -53
#define DR_WAVE_FORMAT_PCM 0x1
#define DR_WAVE_FORMAT_ADPCM 0x2
#define DR_WAVE_FORMAT_IEEE_FLOAT 0x3
#define DR_WAVE_FORMAT_ALAW 0x6
#define DR_WAVE_FORMAT_MULAW 0x7
#define DR_WAVE_FORMAT_DVI_ADPCM 0x11
#define DR_WAVE_FORMAT_EXTENSIBLE 0xFFFE
#define DRWAV_SEQUENTIAL 0x00000001
DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
DRWAV_API const char* drwav_version_string(void);
typedef enum
{
drwav_seek_origin_start,
drwav_seek_origin_current
} drwav_seek_origin;
typedef enum
{
drwav_container_riff,
drwav_container_w64,
drwav_container_rf64
} drwav_container;
typedef struct
{
union
{
drwav_uint8 fourcc[4];
drwav_uint8 guid[16];
} id;
drwav_uint64 sizeInBytes;
unsigned int paddingSize;
} drwav_chunk_header;
typedef struct
{
drwav_uint16 formatTag;
drwav_uint16 channels;
drwav_uint32 sampleRate;
drwav_uint32 avgBytesPerSec;
drwav_uint16 blockAlign;
drwav_uint16 bitsPerSample;
drwav_uint16 extendedSize;
drwav_uint16 validBitsPerSample;
drwav_uint32 channelMask;
drwav_uint8 subFormat[16];
} drwav_fmt;
DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT);
typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
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);
typedef struct
{
void* pUserData;
void* (* onMalloc)(size_t sz, void* pUserData);
void* (* onRealloc)(void* p, size_t sz, void* pUserData);
void (* onFree)(void* p, void* pUserData);
} drwav_allocation_callbacks;
typedef struct
{
const drwav_uint8* data;
size_t dataSize;
size_t currentReadPos;
} drwav__memory_stream;
typedef struct
{
void** ppData;
size_t* pDataSize;
size_t dataSize;
size_t dataCapacity;
size_t currentWritePos;
} drwav__memory_stream_write;
typedef struct
{
drwav_container container;
drwav_uint32 format;
drwav_uint32 channels;
drwav_uint32 sampleRate;
drwav_uint32 bitsPerSample;
} drwav_data_format;
typedef enum
{
drwav_metadata_type_none = 0,
drwav_metadata_type_unknown = 1 << 0,
drwav_metadata_type_smpl = 1 << 1,
drwav_metadata_type_inst = 1 << 2,
drwav_metadata_type_cue = 1 << 3,
drwav_metadata_type_acid = 1 << 4,
drwav_metadata_type_bext = 1 << 5,
drwav_metadata_type_list_label = 1 << 6,
drwav_metadata_type_list_note = 1 << 7,
drwav_metadata_type_list_labelled_cue_region = 1 << 8,
drwav_metadata_type_list_info_software = 1 << 9,
drwav_metadata_type_list_info_copyright = 1 << 10,
drwav_metadata_type_list_info_title = 1 << 11,
drwav_metadata_type_list_info_artist = 1 << 12,
drwav_metadata_type_list_info_comment = 1 << 13,
drwav_metadata_type_list_info_date = 1 << 14,
drwav_metadata_type_list_info_genre = 1 << 15,
drwav_metadata_type_list_info_album = 1 << 16,
drwav_metadata_type_list_info_tracknumber = 1 << 17,
drwav_metadata_type_list_all_info_strings = drwav_metadata_type_list_info_software
| drwav_metadata_type_list_info_copyright
| drwav_metadata_type_list_info_title
| drwav_metadata_type_list_info_artist
| drwav_metadata_type_list_info_comment
| drwav_metadata_type_list_info_date
| drwav_metadata_type_list_info_genre
| drwav_metadata_type_list_info_album
| drwav_metadata_type_list_info_tracknumber,
drwav_metadata_type_list_all_adtl = drwav_metadata_type_list_label
| drwav_metadata_type_list_note
| drwav_metadata_type_list_labelled_cue_region,
drwav_metadata_type_all = -2,
drwav_metadata_type_all_including_unknown = -1
} drwav_metadata_type;
typedef enum
{
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
drwav_uint8* pUMID;
drwav_uint16 loudnessValue;
drwav_uint16 loudnessRange;
drwav_uint16 maxTruePeakLevel;
drwav_uint16 maxMomentaryLoudness;
drwav_uint16 maxShortTermLoudness;
} drwav_bext;
typedef struct
{
drwav_uint32 stringLength;
char* pString;
} drwav_list_info_text;
typedef struct
{
drwav_uint32 cuePointId;
drwav_uint32 sampleLength;
drwav_uint8 purposeId[4];
drwav_uint16 country;
drwav_uint16 language;
drwav_uint16 dialect;
drwav_uint16 codePage;
drwav_uint32 stringLength;
char* pString;
} drwav_list_labelled_cue_region;
typedef enum
{
drwav_metadata_location_invalid,
drwav_metadata_location_top_level,
drwav_metadata_location_inside_info_list,
drwav_metadata_location_inside_adtl_list
} drwav_metadata_location;
typedef struct
{
drwav_uint8 id[4];
drwav_metadata_location chunkLocation;
drwav_uint32 dataSizeInBytes;
drwav_uint8* pData;
} drwav_unknown_metadata;
typedef struct
{
drwav_metadata_type type;
union
{
drwav_cue cue;
drwav_smpl smpl;
drwav_acid acid;
drwav_inst inst;
drwav_bext bext;
drwav_list_label_or_note labelOrNote;
drwav_list_labelled_cue_region labelledCueRegion;
drwav_list_info_text infoText;
drwav_unknown_metadata unknown;
} data;
} drwav_metadata;
typedef struct
{
drwav_read_proc onRead;
drwav_write_proc onWrite;
drwav_seek_proc onSeek;
void* pUserData;
drwav_allocation_callbacks allocationCallbacks;
drwav_container container;
drwav_fmt fmt;
drwav_uint32 sampleRate;
drwav_uint16 channels;
drwav_uint16 bitsPerSample;
drwav_uint16 translatedFormatTag;
drwav_uint64 totalPCMFrameCount;
drwav_uint64 dataChunkDataSize;
drwav_uint64 dataChunkDataPos;
drwav_uint64 bytesRemaining;
drwav_uint64 readCursorInPCMFrames;
drwav_uint64 dataChunkDataSizeTargetWrite;
drwav_bool32 isSequentialWrite;
drwav_metadata_type allowedMetadataTypes;
drwav_metadata* pMetadata;
drwav_uint32 metadataCount;
drwav__memory_stream memoryStream;
drwav__memory_stream_write memoryStreamWrite;
struct
{
drwav_uint32 bytesRemainingInBlock;
drwav_uint16 predictor[2];
drwav_int32 delta[2];
drwav_int32 cachedFrames[4];
drwav_uint32 cachedFrameCount;
drwav_int32 prevFrames[2][2];
} msadpcm;
struct
{
drwav_uint32 bytesRemainingInBlock;
drwav_int32 predictor[2];
drwav_int32 stepIndex[2];
drwav_int32 cachedFrames[16];
drwav_uint32 cachedFrameCount;
} ima;
} drwav;
DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
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);
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);
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);
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);
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);
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_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
DRWAV_API drwav_metadata* drwav_take_ownership_of_metadata(drwav* pWav);
DRWAV_API drwav_result drwav_uninit(drwav* pWav);
DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex);
DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(drwav* pWav, drwav_uint64* pCursor);
DRWAV_API drwav_result drwav_get_length_in_pcm_frames(drwav* pWav, drwav_uint64* pLength);
DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
#ifndef DR_WAV_NO_CONVERSION_API
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
#endif
#ifndef DR_WAV_NO_STDIO
DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
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);
DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
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);
DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
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);
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);
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);
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);
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);
#endif
DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
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);
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);
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);
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);
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);
#ifndef DR_WAV_NO_CONVERSION_API
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* pAl...
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* pAllocati...
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* pAl...
#ifndef DR_WAV_NO_STDIO
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);
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);
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);
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);
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);
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);
#endif
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);
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);
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);
#endif
DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data);
DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data);
DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data);
DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data);
DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data);
DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data);
DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data);
DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16]);
DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
#ifdef __cplusplus
}
#endif
#endif
/* dr_wav_h end */
#endif /* MA_NO_WAV */
#if !defined(MA_NO_FLAC) && !defined(MA_NO_DECODING)
/* dr_flac_h begin */
#ifndef dr_flac_h
#define dr_flac_h
#ifdef __cplusplus
extern "C" {
#endif
#define DRFLAC_STRINGIFY(x) #x
#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
#define DRFLAC_VERSION_MAJOR 0
#define DRFLAC_VERSION_MINOR 12
#define DRFLAC_VERSION_REVISION 38
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
#include <stddef.h>
typedef signed char drflac_int8;
typedef unsigned char drflac_uint8;
typedef signed short drflac_int16;
typedef unsigned short drflac_uint16;
typedef signed int drflac_int32;
typedef unsigned int drflac_uint32;
#if defined(_MSC_VER) && !defined(__clang__)
typedef signed __int64 drflac_int64;
typedef unsigned __int64 drflac_uint64;
#else
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlong-long"
#if defined(__clang__)
#pragma GCC diagnostic ignored "-Wc++11-long-long"
#endif
#endif
typedef signed long long drflac_int64;
typedef unsigned long long drflac_uint64;
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
#pragma GCC diagnostic pop
#endif
#endif
#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__)
typedef drflac_uint64 drflac_uintptr;
#else
typedef drflac_uint32 drflac_uintptr;
#endif
typedef drflac_uint8 drflac_bool8;
typedef drflac_uint32 drflac_bool32;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
const void* pRawData;
drflac_uint32 rawDataSize;
union
{
drflac_streaminfo streaminfo;
struct
{
int unused;
} padding;
struct
{
drflac_uint32 id;
const void* pData;
drflac_uint32 dataSize;
} application;
struct
{
drflac_uint32 seekpointCount;
const drflac_seekpoint* pSeekpoints;
} seektable;
struct
{
drflac_uint32 vendorLength;
const char* vendor;
drflac_uint32 commentCount;
const void* pComments;
} vorbis_comment;
struct
{
char catalog[128];
drflac_uint64 leadInSampleCount;
drflac_bool32 isCD;
drflac_uint8 trackCount;
const void* pTrackData;
} cuesheet;
struct
{
drflac_uint32 type;
drflac_uint32 mimeLength;
const char* mime;
drflac_uint32 descriptionLength;
const char* description;
drflac_uint32 width;
drflac_uint32 height;
drflac_uint32 colorDepth;
drflac_uint32 indexColorCount;
drflac_uint32 pictureDataSize;
const drflac_uint8* pPictureData;
} picture;
} data;
} drflac_metadata;
typedef size_t (* drflac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
typedef void (* drflac_meta_proc)(void* pUserData, drflac_metadata* pMetadata);
typedef struct
{
void* pUserData;
void* (* onMalloc)(size_t sz, void* pUserData);
void* (* onRealloc)(void* p, size_t sz, void* pUserData);
void (* onFree)(void* p, void* pUserData);
} drflac_allocation_callbacks;
typedef struct
{
const drflac_uint8* data;
size_t dataSize;
size_t currentReadPos;
} drflac__memory_stream;
typedef struct
{
drflac_read_proc onRead;
drflac_seek_proc onSeek;
void* pUserData;
size_t unalignedByteCount;
drflac_cache_t unalignedCache;
drflac_uint32 nextL2Line;
drflac_uint32 consumedBits;
drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)];
drflac_cache_t cache;
drflac_uint16 crc16;
drflac_cache_t crc16Cache;
drflac_uint32 crc16CacheIgnoredBytes;
} drflac_bs;
typedef struct
{
drflac_uint8 subframeType;
drflac_uint8 wastedBitsPerSample;
drflac_uint8 lpcOrder;
drflac_int32* pSamplesS32;
} drflac_subframe;
typedef struct
{
drflac_uint64 pcmFrameNumber;
drflac_uint32 flacFrameNumber;
drflac_uint32 sampleRate;
drflac_uint16 blockSizeInPCMFrames;
drflac_uint8 channelAssignment;
drflac_uint8 bitsPerSample;
drflac_uint8 crc8;
} drflac_frame_header;
typedef struct
{
drflac_frame_header header;
drflac_uint32 pcmFramesRemaining;
drflac_subframe subframes[8];
} drflac_frame;
typedef struct
{
drflac_meta_proc onMeta;
void* pUserDataMD;
drflac_allocation_callbacks allocationCallbacks;
drflac_uint32 sampleRate;
drflac_uint8 channels;
drflac_uint8 bitsPerSample;
drflac_uint16 maxBlockSizeInPCMFrames;
drflac_uint64 totalPCMFrameCount;
drflac_container container;
drflac_uint32 seekpointCount;
drflac_frame currentFLACFrame;
drflac_uint64 currentPCMFrame;
drflac_uint64 firstFLACFramePosInBytes;
drflac__memory_stream memoryStream;
drflac_int32* pDecodedSamples;
drflac_seekpoint* pSeekpoints;
void* _oggbs;
drflac_bool32 _noSeekTableSeek : 1;
drflac_bool32 _noBinarySearchSeek : 1;
drflac_bool32 _noBruteForceSeek : 1;
drflac_bs bs;
drflac_uint8 pExtraData[1];
} drflac;
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
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);
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);
DRFLAC_API void drflac_close(drflac* pFlac);
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s32(drflac* pFlac, drflac_uint64 framesToRead, drflac_int32* pBufferOut);
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s16(drflac* pFlac, drflac_uint64 framesToRead, drflac_int16* pBufferOut);
DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac* pFlac, drflac_uint64 framesToRead, float* pBufferOut);
DRFLAC_API drflac_bool32 drflac_seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex);
#ifndef DR_FLAC_NO_STDIO
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
#endif
DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks);
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);
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* pA...
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* pA...
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* pAllocati...
#ifndef DR_FLAC_NO_STDIO
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);
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);
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);
#endif
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);
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);
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);
DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks);
typedef struct
{
drflac_uint32 countRemaining;
const char* pRunningData;
} drflac_vorbis_comment_iterator;
DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments);
DRFLAC_API const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut);
typedef struct
{
drflac_uint32 countRemaining;
const char* pRunningData;
} drflac_cuesheet_track_iterator;
#pragma pack(4)
typedef struct
{
drflac_uint64 offset;
drflac_uint8 index;
drflac_uint8 reserved[3];
} drflac_cuesheet_track_index;
#pragma pack()
typedef struct
{
drflac_uint64 offset;
drflac_uint8 trackNumber;
char ISRC[12];
drflac_bool8 isAudio;
drflac_bool8 preEmphasis;
drflac_uint8 indexCount;
const drflac_cuesheet_track_index* pIndexPoints;
} drflac_cuesheet_track;
DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData);
DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack);
#ifdef __cplusplus
}
#endif
#endif
/* dr_flac_h end */
#endif /* MA_NO_FLAC */
#if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING)
/* dr_mp3_h begin */
#ifndef dr_mp3_h
#define dr_mp3_h
#ifdef __cplusplus
extern "C" {
#endif
#define DRMP3_STRINGIFY(x) #x
#define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
#define DRMP3_VERSION_MAJOR 0
#define DRMP3_VERSION_MINOR 6
#define DRMP3_VERSION_REVISION 33
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
#include <stddef.h>
typedef signed char drmp3_int8;
typedef unsigned char drmp3_uint8;
typedef signed short drmp3_int16;
typedef unsigned short drmp3_uint16;
typedef signed int drmp3_int32;
typedef unsigned int drmp3_uint32;
#if defined(_MSC_VER) && !defined(__clang__)
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#define DRMP3_NO_HOST -49
#define DRMP3_IN_PROGRESS -50
#define DRMP3_CANCELLED -51
#define DRMP3_MEMORY_ALREADY_MAPPED -52
#define DRMP3_AT_END -53
#define DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
#define DRMP3_MAX_SAMPLES_PER_FRAME (DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2)
#ifdef _MSC_VER
#define DRMP3_INLINE __forceinline
#elif defined(__GNUC__)
#if defined(__STRICT_ANSI__)
#define DRMP3_GNUC_INLINE_HINT __inline__
#else
#define DRMP3_GNUC_INLINE_HINT inline
#endif
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
#define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT __attribute__((always_inline))
#else
#define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT
#endif
#elif defined(__WATCOMC__)
#define DRMP3_INLINE __inline
#else
#define DRMP3_INLINE
#endif
DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision);
DRMP3_API const char* drmp3_version_string(void);
typedef struct
{
int frame_bytes, channels, hz, layer, bitrate_kbps;
} drmp3dec_frame_info;
typedef struct
{
float mdct_overlap[2][9*32], qmf_state[15*2*32];
int reserv, free_format_bytes;
drmp3_uint8 header[4], reserv_buf[511];
} drmp3dec;
DRMP3_API void drmp3dec_init(drmp3dec *dec);
DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info);
DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples);
typedef enum
{
drmp3_seek_origin_start,
drmp3_seek_origin_current
} drmp3_seek_origin;
typedef struct
{
drmp3_uint64 seekPosInBytes;
drmp3_uint64 pcmFrameIndex;
drmp3_uint16 mp3FramesToDiscard;
drmp3_uint16 pcmFramesToDiscard;
} drmp3_seek_point;
typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin);
typedef struct
{
void* pUserData;
void* (* onMalloc)(size_t sz, void* pUserData);
void* (* onRealloc)(void* p, size_t sz, void* pUserData);
void (* onFree)(void* p, void* pUserData);
} drmp3_allocation_callbacks;
typedef struct
{
drmp3_uint32 channels;
drmp3_uint32 sampleRate;
} drmp3_config;
typedef struct
{
drmp3dec decoder;
drmp3dec_frame_info frameInfo;
drmp3_uint32 channels;
drmp3_uint32 sampleRate;
drmp3_read_proc onRead;
drmp3_seek_proc onSeek;
void* pUserData;
drmp3_allocation_callbacks allocationCallbacks;
drmp3_uint32 mp3FrameChannels;
drmp3_uint32 mp3FrameSampleRate;
drmp3_uint32 pcmFramesConsumedInMP3Frame;
drmp3_uint32 pcmFramesRemainingInMP3Frame;
drmp3_uint8 pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME];
drmp3_uint64 currentPCMFrame;
drmp3_uint64 streamCursor;
drmp3_seek_point* pSeekPoints;
drmp3_uint32 seekPointCount;
size_t dataSize;
size_t dataCapacity;
size_t dataConsumed;
drmp3_uint8* pData;
drmp3_bool32 atEnd : 1;
struct
{
const drmp3_uint8* pData;
size_t dataSize;
size_t currentReadPos;
} memory;
} drmp3;
DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks);
DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks);
#ifndef DR_MP3_NO_STDIO
DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
#endif
DRMP3_API void drmp3_uninit(drmp3* pMP3);
DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut);
DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3* pMP3, drmp3_uint64 framesToRead, drmp3_int16* pBufferOut);
DRMP3_API drmp3_bool32 drmp3_seek_to_pcm_frame(drmp3* pMP3, drmp3_uint64 frameIndex);
DRMP3_API drmp3_uint64 drmp3_get_pcm_frame_count(drmp3* pMP3);
DRMP3_API drmp3_uint64 drmp3_get_mp3_frame_count(drmp3* pMP3);
DRMP3_API drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3* pMP3, drmp3_uint64* pMP3FrameCount, drmp3_uint64* pPCMFrameCount);
DRMP3_API drmp3_bool32 drmp3_calculate_seek_points(drmp3* pMP3, drmp3_uint32* pSeekPointCount, drmp3_seek_point* pSeekPoints);
DRMP3_API drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints);
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);
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);
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);
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);
#ifndef DR_MP3_NO_STDIO
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);
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);
#endif
DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks);
DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks);
#ifdef __cplusplus
}
#endif
#endif
/* dr_mp3_h end */
#endif /* MA_NO_MP3 */
/**************************************************************************************************************************************************************
Decoding
**************************************************************************************************************************************************************/
#ifndef MA_NO_DECODING
static ma_result ma_decoder_read_bytes(ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead, size_t* pBytesRead)
{
MA_ASSERT(pDecoder != NULL);
return pDecoder->onRead(pDecoder, pBufferOut, bytesToRead, pBytesRead);
}
static ma_result ma_decoder_seek_bytes(ma_decoder* pDecoder, ma_int64 byteOffset, ma_seek_origin origin)
{
MA_ASSERT(pDecoder != NULL);
return pDecoder->onSeek(pDecoder, byteOffset, origin);
}
static ma_result ma_decoder_tell_bytes(ma_decoder* pDecoder, ma_int64* pCursor)
{
MA_ASSERT(pDecoder != NULL);
if (pDecoder->onTell == NULL) {
return MA_NOT_IMPLEMENTED;
}
return pDecoder->onTell(pDecoder, pCursor);
}
MA_API ma_decoding_backend_config ma_decoding_backend_config_init(ma_format preferredFormat, ma_uint32 seekPointCount)
{
ma_decoding_backend_config config;
MA_ZERO_OBJECT(&config);
config.preferredFormat = preferredFormat;
config.seekPointCount = seekPointCount;
return config;
}
MA_API ma_decoder_config ma_decoder_config_init(ma_format outputFormat, ma_uint32 outputChannels, ma_uint32 outputSampleRate)
{
ma_decoder_config config;
MA_ZERO_OBJECT(&config);
config.format = outputFormat;
config.channels = outputChannels;
config.sampleRate = outputSampleRate;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pDecoder->pBackendUserData = pConfig->pCustomBackendUserData;
return MA_SUCCESS;
}
static ma_result ma_decoder_init_custom__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{
ma_result result = MA_NO_BACKEND;
size_t ivtable;
MA_ASSERT(pConfig != NULL);
MA_ASSERT(pDecoder != NULL);
if (pConfig->ppCustomBackendVTables == NULL) {
return MA_NO_BACKEND;
}
/* The order each backend is listed is what defines the priority. */
for (ivtable = 0; ivtable < pConfig->customBackendCount; ivtable += 1) {
const ma_decoding_backend_vtable* pVTable = pConfig->ppCustomBackendVTables[ivtable];
if (pVTable != NULL && pVTable->onInit != NULL) {
result = ma_decoder_init_from_vtable(pVTable, pConfig->pCustomBackendUserData, pConfig, pDecoder);
if (result == MA_SUCCESS) {
return MA_SUCCESS;
} else {
/* 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. */
result = ma_decoder_seek_bytes(pDecoder, 0, ma_seek_origin_start);
if (result != MA_SUCCESS) {
return result; /* Failed to seek back to the start. */
}
}
} else {
/* No vtable. */
}
}
/* Getting here means we couldn't find a backend. */
return MA_NO_BACKEND;
}
/* WAV */
#ifdef dr_wav_h
#define MA_HAS_WAV
typedef struct
{
ma_data_source_base ds;
ma_read_proc onRead;
ma_seek_proc onSeek;
ma_tell_proc onTell;
void* pReadSeekTellUserData;
ma_format format; /* Can be f32, s16 or s32. */
#if !defined(MA_NO_WAV)
drwav dr;
#endif
} ma_wav;
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);
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);
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);
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);
MA_API void ma_wav_uninit(ma_wav* pWav, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_wav_read_pcm_frames(ma_wav* pWav, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_wav_seek_to_pcm_frame(ma_wav* pWav, ma_uint64 frameIndex);
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);
MA_API ma_result ma_wav_get_cursor_in_pcm_frames(ma_wav* pWav, ma_uint64* pCursor);
MA_API ma_result ma_wav_get_length_in_pcm_frames(ma_wav* pWav, ma_uint64* pLength);
static ma_result ma_wav_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
return ma_wav_read_pcm_frames((ma_wav*)pDataSource, pFramesOut, frameCount, pFramesRead);
}
static ma_result ma_wav_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
return ma_wav_seek_to_pcm_frame((ma_wav*)pDataSource, frameIndex);
}
static ma_result ma_wav_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
return ma_wav_get_data_format((ma_wav*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}
static ma_result ma_wav_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
return ma_wav_get_cursor_in_pcm_frames((ma_wav*)pDataSource, pCursor);
}
static ma_result ma_wav_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
return ma_wav_get_length_in_pcm_frames((ma_wav*)pDataSource, pLength);
}
static ma_data_source_vtable g_ma_wav_ds_vtable =
{
ma_wav_ds_read,
ma_wav_ds_seek,
ma_wav_ds_get_data_format,
ma_wav_ds_get_cursor,
ma_wav_ds_get_length,
NULL, /* onSetLooping */
0
};
#if !defined(MA_NO_WAV)
static drwav_allocation_callbacks drwav_allocation_callbacks_from_miniaudio(const ma_allocation_callbacks* pAllocationCallbacks)
{
drwav_allocation_callbacks callbacks;
if (pAllocationCallbacks != NULL) {
callbacks.onMalloc = pAllocationCallbacks->onMalloc;
callbacks.onRealloc = pAllocationCallbacks->onRealloc;
callbacks.onFree = pAllocationCallbacks->onFree;
callbacks.pUserData = pAllocationCallbacks->pUserData;
} else {
callbacks.onMalloc = ma__malloc_default;
callbacks.onRealloc = ma__realloc_default;
callbacks.onFree = ma__free_default;
callbacks.pUserData = NULL;
}
return callbacks;
}
static size_t ma_wav_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
ma_wav* pWav = (ma_wav*)pUserData;
ma_result result;
size_t bytesRead;
MA_ASSERT(pWav != NULL);
result = pWav->onRead(pWav->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
(void)result;
return bytesRead;
}
static drwav_bool32 ma_wav_dr_callback__seek(void* pUserData, int offset, drwav_seek_origin origin)
{
ma_wav* pWav = (ma_wav*)pUserData;
ma_result result;
ma_seek_origin maSeekOrigin;
MA_ASSERT(pWav != NULL);
maSeekOrigin = ma_seek_origin_start;
if (origin == drwav_seek_origin_current) {
maSeekOrigin = ma_seek_origin_current;
}
result = pWav->onSeek(pWav->pReadSeekTellUserData, offset, maSeekOrigin);
if (result != MA_SUCCESS) {
return MA_FALSE;
}
return MA_TRUE;
}
#endif
static ma_result ma_wav_init_internal(const ma_decoding_backend_config* pConfig, ma_wav* pWav)
{
ma_result result;
ma_data_source_config dataSourceConfig;
if (pWav == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pWav);
pWav->format = ma_format_unknown; /* Use closest match to source file by default. */
if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16 || pConfig->preferredFormat == ma_format_s32)) {
pWav->format = pConfig->preferredFormat;
} else {
/* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
}
dataSourceConfig = ma_data_source_config_init();
dataSourceConfig.vtable = &g_ma_wav_ds_vtable;
result = ma_data_source_init(&dataSourceConfig, &pWav->ds);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the base data source. */
}
return MA_SUCCESS;
}
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)
{
ma_result result;
result = ma_wav_init_internal(pConfig, pWav);
if (result != MA_SUCCESS) {
return result;
}
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
}
pWav->onRead = onRead;
pWav->onSeek = onSeek;
pWav->onTell = onTell;
pWav->pReadSeekTellUserData = pReadSeekTellUserData;
#if !defined(MA_NO_WAV)
{
drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drwav_bool32 wavResult;
wavResult = drwav_init(&pWav->dr, ma_wav_dr_callback__read, ma_wav_dr_callback__seek, pWav, &wavAllocationCallbacks);
if (wavResult != MA_TRUE) {
return MA_INVALID_FILE;
}
/*
If an explicit format was not specified, try picking the closest match based on the internal
format. The format needs to be supported by miniaudio.
*/
if (pWav->format == ma_format_unknown) {
switch (pWav->dr.translatedFormatTag)
{
case DR_WAVE_FORMAT_PCM:
{
if (pWav->dr.bitsPerSample == 8) {
pWav->format = ma_format_u8;
} else if (pWav->dr.bitsPerSample == 16) {
pWav->format = ma_format_s16;
} else if (pWav->dr.bitsPerSample == 24) {
pWav->format = ma_format_s24;
} else if (pWav->dr.bitsPerSample == 32) {
pWav->format = ma_format_s32;
}
} break;
case DR_WAVE_FORMAT_IEEE_FLOAT:
{
if (pWav->dr.bitsPerSample == 32) {
pWav->format = ma_format_f32;
}
} break;
default: break;
}
/* Fall back to f32 if we couldn't find anything. */
if (pWav->format == ma_format_unknown) {
pWav->format = ma_format_f32;
}
}
return MA_SUCCESS;
}
#else
{
/* wav is disabled. */
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_wav_init_internal(pConfig, pWav);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_WAV)
{
drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drwav_bool32 wavResult;
wavResult = drwav_init_file(&pWav->dr, pFilePath, &wavAllocationCallbacks);
if (wavResult != MA_TRUE) {
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* wav is disabled. */
(void)pFilePath;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_wav_init_internal(pConfig, pWav);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_WAV)
{
drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drwav_bool32 wavResult;
wavResult = drwav_init_file_w(&pWav->dr, pFilePath, &wavAllocationCallbacks);
if (wavResult != MA_TRUE) {
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* wav is disabled. */
(void)pFilePath;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_wav_init_internal(pConfig, pWav);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_WAV)
{
drwav_allocation_callbacks wavAllocationCallbacks = drwav_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drwav_bool32 wavResult;
wavResult = drwav_init_memory(&pWav->dr, pData, dataSize, &wavAllocationCallbacks);
if (wavResult != MA_TRUE) {
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* wav is disabled. */
(void)pData;
(void)dataSize;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API void ma_wav_uninit(ma_wav* pWav, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pWav == NULL) {
return;
}
(void)pAllocationCallbacks;
#if !defined(MA_NO_WAV)
{
drwav_uninit(&pWav->dr);
}
#else
{
/* wav is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
}
#endif
ma_data_source_uninit(&pWav->ds);
}
MA_API ma_result ma_wav_read_pcm_frames(ma_wav* pWav, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
if (frameCount == 0) {
return MA_INVALID_ARGS;
}
if (pWav == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_WAV)
{
/* We always use floating point format. */
ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
ma_uint64 totalFramesRead = 0;
ma_format format;
ma_wav_get_data_format(pWav, &format, NULL, NULL, NULL, 0);
switch (format)
{
case ma_format_f32:
{
totalFramesRead = drwav_read_pcm_frames_f32(&pWav->dr, frameCount, (float*)pFramesOut);
} break;
case ma_format_s16:
{
totalFramesRead = drwav_read_pcm_frames_s16(&pWav->dr, frameCount, (drwav_int16*)pFramesOut);
} break;
case ma_format_s32:
{
totalFramesRead = drwav_read_pcm_frames_s32(&pWav->dr, frameCount, (drwav_int32*)pFramesOut);
} break;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0; /* Safety. */
if (pWav == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_WAV)
{
drwav_result wavResult = drwav_get_cursor_in_pcm_frames(&pWav->dr, pCursor);
if (wavResult != DRWAV_SUCCESS) {
return (ma_result)wavResult; /* dr_wav result codes map to miniaudio's. */
}
return MA_SUCCESS;
}
#else
{
/* wav is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_wav_get_length_in_pcm_frames(ma_wav* pWav, ma_uint64* pLength)
{
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0; /* Safety. */
if (pWav == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_WAV)
{
drwav_result wavResult = drwav_get_length_in_pcm_frames(&pWav->dr, pLength);
if (wavResult != DRWAV_SUCCESS) {
return (ma_result)wavResult; /* dr_wav result codes map to miniaudio's. */
}
return MA_SUCCESS;
}
#else
{
/* wav is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
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_result result;
ma_wav* pWav;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
if (pWav == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_wav_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pWav);
if (result != MA_SUCCESS) {
ma_free(pWav, pAllocationCallbacks);
return result;
}
*ppBackend = pWav;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_wav* pWav;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
if (pWav == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_wav_init_file(pFilePath, pConfig, pAllocationCallbacks, pWav);
if (result != MA_SUCCESS) {
ma_free(pWav, pAllocationCallbacks);
return result;
}
*ppBackend = pWav;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_wav* pWav;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
if (pWav == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_wav_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pWav);
if (result != MA_SUCCESS) {
ma_free(pWav, pAllocationCallbacks);
return result;
}
*ppBackend = pWav;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_wav* pWav;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pWav = (ma_wav*)ma_malloc(sizeof(*pWav), pAllocationCallbacks);
if (pWav == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_wav_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pWav);
if (result != MA_SUCCESS) {
ma_free(pWav, pAllocationCallbacks);
return result;
}
*ppBackend = pWav;
return MA_SUCCESS;
}
static void ma_decoding_backend_uninit__wav(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_wav* pWav = (ma_wav*)pBackend;
(void)pUserData;
ma_wav_uninit(pWav, pAllocationCallbacks);
ma_free(pWav, pAllocationCallbacks);
}
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_wav =
{
ma_decoding_backend_init__wav,
ma_decoding_backend_init_file__wav,
ma_decoding_backend_init_file_w__wav,
ma_decoding_backend_init_memory__wav,
ma_decoding_backend_uninit__wav
};
static ma_result ma_decoder_init_wav__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{
return ma_decoder_init_from_vtable(&g_ma_decoding_backend_vtable_wav, NULL, pConfig, pDecoder);
}
#endif /* dr_wav_h */
/* FLAC */
#ifdef dr_flac_h
#define MA_HAS_FLAC
typedef struct
{
ma_data_source_base ds;
ma_read_proc onRead;
ma_seek_proc onSeek;
ma_tell_proc onTell;
void* pReadSeekTellUserData;
ma_format format; /* Can be f32, s16 or s32. */
#if !defined(MA_NO_FLAC)
drflac* dr;
#endif
} ma_flac;
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);
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);
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);
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);
MA_API void ma_flac_uninit(ma_flac* pFlac, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_flac_read_pcm_frames(ma_flac* pFlac, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_flac_seek_to_pcm_frame(ma_flac* pFlac, ma_uint64 frameIndex);
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);
MA_API ma_result ma_flac_get_cursor_in_pcm_frames(ma_flac* pFlac, ma_uint64* pCursor);
MA_API ma_result ma_flac_get_length_in_pcm_frames(ma_flac* pFlac, ma_uint64* pLength);
static ma_result ma_flac_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
return ma_flac_read_pcm_frames((ma_flac*)pDataSource, pFramesOut, frameCount, pFramesRead);
}
static ma_result ma_flac_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
return ma_flac_seek_to_pcm_frame((ma_flac*)pDataSource, frameIndex);
}
static ma_result ma_flac_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
return ma_flac_get_data_format((ma_flac*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}
static ma_result ma_flac_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
return ma_flac_get_cursor_in_pcm_frames((ma_flac*)pDataSource, pCursor);
}
static ma_result ma_flac_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
return ma_flac_get_length_in_pcm_frames((ma_flac*)pDataSource, pLength);
}
static ma_data_source_vtable g_ma_flac_ds_vtable =
{
ma_flac_ds_read,
ma_flac_ds_seek,
ma_flac_ds_get_data_format,
ma_flac_ds_get_cursor,
ma_flac_ds_get_length,
NULL, /* onSetLooping */
0
};
#if !defined(MA_NO_FLAC)
static drflac_allocation_callbacks drflac_allocation_callbacks_from_miniaudio(const ma_allocation_callbacks* pAllocationCallbacks)
{
drflac_allocation_callbacks callbacks;
if (pAllocationCallbacks != NULL) {
callbacks.onMalloc = pAllocationCallbacks->onMalloc;
callbacks.onRealloc = pAllocationCallbacks->onRealloc;
callbacks.onFree = pAllocationCallbacks->onFree;
callbacks.pUserData = pAllocationCallbacks->pUserData;
} else {
callbacks.onMalloc = ma__malloc_default;
callbacks.onRealloc = ma__realloc_default;
callbacks.onFree = ma__free_default;
callbacks.pUserData = NULL;
}
return callbacks;
}
static size_t ma_flac_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
ma_flac* pFlac = (ma_flac*)pUserData;
ma_result result;
size_t bytesRead;
MA_ASSERT(pFlac != NULL);
result = pFlac->onRead(pFlac->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
(void)result;
return bytesRead;
}
static drflac_bool32 ma_flac_dr_callback__seek(void* pUserData, int offset, drflac_seek_origin origin)
{
ma_flac* pFlac = (ma_flac*)pUserData;
ma_result result;
ma_seek_origin maSeekOrigin;
MA_ASSERT(pFlac != NULL);
maSeekOrigin = ma_seek_origin_start;
if (origin == drflac_seek_origin_current) {
maSeekOrigin = ma_seek_origin_current;
}
result = pFlac->onSeek(pFlac->pReadSeekTellUserData, offset, maSeekOrigin);
if (result != MA_SUCCESS) {
return MA_FALSE;
}
return MA_TRUE;
}
#endif
static ma_result ma_flac_init_internal(const ma_decoding_backend_config* pConfig, ma_flac* pFlac)
{
ma_result result;
ma_data_source_config dataSourceConfig;
if (pFlac == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pFlac);
pFlac->format = ma_format_f32; /* f32 by default. */
if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16 || pConfig->preferredFormat == ma_format_s32)) {
pFlac->format = pConfig->preferredFormat;
} else {
/* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
}
dataSourceConfig = ma_data_source_config_init();
dataSourceConfig.vtable = &g_ma_flac_ds_vtable;
result = ma_data_source_init(&dataSourceConfig, &pFlac->ds);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the base data source. */
}
return MA_SUCCESS;
}
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)
{
ma_result result;
result = ma_flac_init_internal(pConfig, pFlac);
if (result != MA_SUCCESS) {
return result;
}
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
}
pFlac->onRead = onRead;
pFlac->onSeek = onSeek;
pFlac->onTell = onTell;
pFlac->pReadSeekTellUserData = pReadSeekTellUserData;
#if !defined(MA_NO_FLAC)
{
drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
pFlac->dr = drflac_open(ma_flac_dr_callback__read, ma_flac_dr_callback__seek, pFlac, &flacAllocationCallbacks);
if (pFlac->dr == NULL) {
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* flac is disabled. */
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_flac_init_internal(pConfig, pFlac);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_FLAC)
{
drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
pFlac->dr = drflac_open_file(pFilePath, &flacAllocationCallbacks);
if (pFlac->dr == NULL) {
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* flac is disabled. */
(void)pFilePath;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_flac_init_internal(pConfig, pFlac);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_FLAC)
{
drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
pFlac->dr = drflac_open_file_w(pFilePath, &flacAllocationCallbacks);
if (pFlac->dr == NULL) {
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* flac is disabled. */
(void)pFilePath;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_flac_init_internal(pConfig, pFlac);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_FLAC)
{
drflac_allocation_callbacks flacAllocationCallbacks = drflac_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
pFlac->dr = drflac_open_memory(pData, dataSize, &flacAllocationCallbacks);
if (pFlac->dr == NULL) {
return MA_INVALID_FILE;
}
return MA_SUCCESS;
}
#else
{
/* flac is disabled. */
(void)pData;
(void)dataSize;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API void ma_flac_uninit(ma_flac* pFlac, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pFlac == NULL) {
return;
}
(void)pAllocationCallbacks;
#if !defined(MA_NO_FLAC)
{
drflac_close(pFlac->dr);
}
#else
{
/* flac is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
}
#endif
ma_data_source_uninit(&pFlac->ds);
}
MA_API ma_result ma_flac_read_pcm_frames(ma_flac* pFlac, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
if (frameCount == 0) {
return MA_INVALID_ARGS;
}
if (pFlac == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_FLAC)
{
/* We always use floating point format. */
ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
ma_uint64 totalFramesRead = 0;
ma_format format;
ma_flac_get_data_format(pFlac, &format, NULL, NULL, NULL, 0);
switch (format)
{
case ma_format_f32:
{
totalFramesRead = drflac_read_pcm_frames_f32(pFlac->dr, frameCount, (float*)pFramesOut);
} break;
case ma_format_s16:
{
totalFramesRead = drflac_read_pcm_frames_s16(pFlac->dr, frameCount, (drflac_int16*)pFramesOut);
} break;
case ma_format_s32:
{
totalFramesRead = drflac_read_pcm_frames_s32(pFlac->dr, frameCount, (drflac_int32*)pFramesOut);
} break;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_flac_get_cursor_in_pcm_frames(ma_flac* pFlac, ma_uint64* pCursor)
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0; /* Safety. */
if (pFlac == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_FLAC)
{
*pCursor = pFlac->dr->currentPCMFrame;
return MA_SUCCESS;
}
#else
{
/* flac is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_flac_get_length_in_pcm_frames(ma_flac* pFlac, ma_uint64* pLength)
{
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0; /* Safety. */
if (pFlac == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_FLAC)
{
*pLength = pFlac->dr->totalPCMFrameCount;
return MA_SUCCESS;
}
#else
{
/* flac is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
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* pAllocationCallback...
{
ma_result result;
ma_flac* pFlac;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
if (pFlac == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_flac_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pFlac);
if (result != MA_SUCCESS) {
ma_free(pFlac, pAllocationCallbacks);
return result;
}
*ppBackend = pFlac;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_flac* pFlac;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
if (pFlac == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_flac_init_file(pFilePath, pConfig, pAllocationCallbacks, pFlac);
if (result != MA_SUCCESS) {
ma_free(pFlac, pAllocationCallbacks);
return result;
}
*ppBackend = pFlac;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_flac* pFlac;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
if (pFlac == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_flac_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pFlac);
if (result != MA_SUCCESS) {
ma_free(pFlac, pAllocationCallbacks);
return result;
}
*ppBackend = pFlac;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_flac* pFlac;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pFlac = (ma_flac*)ma_malloc(sizeof(*pFlac), pAllocationCallbacks);
if (pFlac == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_flac_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pFlac);
if (result != MA_SUCCESS) {
ma_free(pFlac, pAllocationCallbacks);
return result;
}
*ppBackend = pFlac;
return MA_SUCCESS;
}
static void ma_decoding_backend_uninit__flac(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_flac* pFlac = (ma_flac*)pBackend;
(void)pUserData;
ma_flac_uninit(pFlac, pAllocationCallbacks);
ma_free(pFlac, pAllocationCallbacks);
}
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_flac =
{
ma_decoding_backend_init__flac,
ma_decoding_backend_init_file__flac,
ma_decoding_backend_init_file_w__flac,
ma_decoding_backend_init_memory__flac,
ma_decoding_backend_uninit__flac
};
static ma_result ma_decoder_init_flac__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{
return ma_decoder_init_from_vtable(&g_ma_decoding_backend_vtable_flac, NULL, pConfig, pDecoder);
}
#endif /* dr_flac_h */
/* MP3 */
#ifdef dr_mp3_h
#define MA_HAS_MP3
typedef struct
{
ma_data_source_base ds;
ma_read_proc onRead;
ma_seek_proc onSeek;
ma_tell_proc onTell;
void* pReadSeekTellUserData;
ma_format format; /* Can be f32 or s16. */
#if !defined(MA_NO_MP3)
drmp3 dr;
drmp3_uint32 seekPointCount;
drmp3_seek_point* pSeekPoints; /* Only used if seek table generation is used. */
#endif
} ma_mp3;
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);
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);
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);
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);
MA_API void ma_mp3_uninit(ma_mp3* pMP3, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_mp3_read_pcm_frames(ma_mp3* pMP3, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_mp3_seek_to_pcm_frame(ma_mp3* pMP3, ma_uint64 frameIndex);
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);
MA_API ma_result ma_mp3_get_cursor_in_pcm_frames(ma_mp3* pMP3, ma_uint64* pCursor);
MA_API ma_result ma_mp3_get_length_in_pcm_frames(ma_mp3* pMP3, ma_uint64* pLength);
static ma_result ma_mp3_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
return ma_mp3_read_pcm_frames((ma_mp3*)pDataSource, pFramesOut, frameCount, pFramesRead);
}
static ma_result ma_mp3_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
return ma_mp3_seek_to_pcm_frame((ma_mp3*)pDataSource, frameIndex);
}
static ma_result ma_mp3_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
return ma_mp3_get_data_format((ma_mp3*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}
static ma_result ma_mp3_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
return ma_mp3_get_cursor_in_pcm_frames((ma_mp3*)pDataSource, pCursor);
}
static ma_result ma_mp3_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
return ma_mp3_get_length_in_pcm_frames((ma_mp3*)pDataSource, pLength);
}
static ma_data_source_vtable g_ma_mp3_ds_vtable =
{
ma_mp3_ds_read,
ma_mp3_ds_seek,
ma_mp3_ds_get_data_format,
ma_mp3_ds_get_cursor,
ma_mp3_ds_get_length,
NULL, /* onSetLooping */
0
};
#if !defined(MA_NO_MP3)
static drmp3_allocation_callbacks drmp3_allocation_callbacks_from_miniaudio(const ma_allocation_callbacks* pAllocationCallbacks)
{
drmp3_allocation_callbacks callbacks;
if (pAllocationCallbacks != NULL) {
callbacks.onMalloc = pAllocationCallbacks->onMalloc;
callbacks.onRealloc = pAllocationCallbacks->onRealloc;
callbacks.onFree = pAllocationCallbacks->onFree;
callbacks.pUserData = pAllocationCallbacks->pUserData;
} else {
callbacks.onMalloc = ma__malloc_default;
callbacks.onRealloc = ma__realloc_default;
callbacks.onFree = ma__free_default;
callbacks.pUserData = NULL;
}
return callbacks;
}
static size_t ma_mp3_dr_callback__read(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
ma_mp3* pMP3 = (ma_mp3*)pUserData;
ma_result result;
size_t bytesRead;
MA_ASSERT(pMP3 != NULL);
result = pMP3->onRead(pMP3->pReadSeekTellUserData, pBufferOut, bytesToRead, &bytesRead);
(void)result;
return bytesRead;
}
static drmp3_bool32 ma_mp3_dr_callback__seek(void* pUserData, int offset, drmp3_seek_origin origin)
{
ma_mp3* pMP3 = (ma_mp3*)pUserData;
ma_result result;
ma_seek_origin maSeekOrigin;
MA_ASSERT(pMP3 != NULL);
maSeekOrigin = ma_seek_origin_start;
if (origin == drmp3_seek_origin_current) {
maSeekOrigin = ma_seek_origin_current;
}
result = pMP3->onSeek(pMP3->pReadSeekTellUserData, offset, maSeekOrigin);
if (result != MA_SUCCESS) {
return MA_FALSE;
}
return MA_TRUE;
}
#endif
static ma_result ma_mp3_init_internal(const ma_decoding_backend_config* pConfig, ma_mp3* pMP3)
{
ma_result result;
ma_data_source_config dataSourceConfig;
if (pMP3 == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pMP3);
pMP3->format = ma_format_f32; /* f32 by default. */
if (pConfig != NULL && (pConfig->preferredFormat == ma_format_f32 || pConfig->preferredFormat == ma_format_s16)) {
pMP3->format = pConfig->preferredFormat;
} else {
/* Getting here means something other than f32 and s16 was specified. Just leave this unset to use the default format. */
}
dataSourceConfig = ma_data_source_config_init();
dataSourceConfig.vtable = &g_ma_mp3_ds_vtable;
result = ma_data_source_init(&dataSourceConfig, &pMP3->ds);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the base data source. */
}
return MA_SUCCESS;
}
static ma_result ma_mp3_generate_seek_table(ma_mp3* pMP3, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks)
{
drmp3_bool32 mp3Result;
drmp3_uint32 seekPointCount = 0;
drmp3_seek_point* pSeekPoints = NULL;
MA_ASSERT(pMP3 != NULL);
MA_ASSERT(pConfig != NULL);
seekPointCount = pConfig->seekPointCount;
if (seekPointCount > 0) {
pSeekPoints = (drmp3_seek_point*)ma_malloc(sizeof(*pMP3->pSeekPoints) * seekPointCount, pAllocationCallbacks);
if (pSeekPoints == NULL) {
return MA_OUT_OF_MEMORY;
}
}
mp3Result = drmp3_calculate_seek_points(&pMP3->dr, &seekPointCount, pSeekPoints);
if (mp3Result != MA_TRUE) {
return MA_ERROR;
}
mp3Result = drmp3_bind_seek_table(&pMP3->dr, seekPointCount, pSeekPoints);
if (mp3Result != MA_TRUE) {
ma_free(pSeekPoints, pAllocationCallbacks);
return MA_ERROR;
}
pMP3->seekPointCount = seekPointCount;
pMP3->pSeekPoints = pSeekPoints;
return MA_SUCCESS;
}
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)
{
ma_result result;
result = ma_mp3_init_internal(pConfig, pMP3);
if (result != MA_SUCCESS) {
return result;
}
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
}
pMP3->onRead = onRead;
pMP3->onSeek = onSeek;
pMP3->onTell = onTell;
pMP3->pReadSeekTellUserData = pReadSeekTellUserData;
#if !defined(MA_NO_MP3)
{
drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drmp3_bool32 mp3Result;
mp3Result = drmp3_init(&pMP3->dr, ma_mp3_dr_callback__read, ma_mp3_dr_callback__seek, pMP3, &mp3AllocationCallbacks);
if (mp3Result != MA_TRUE) {
return MA_INVALID_FILE;
}
ma_mp3_generate_seek_table(pMP3, pConfig, pAllocationCallbacks);
return MA_SUCCESS;
}
#else
{
/* mp3 is disabled. */
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_mp3_init_internal(pConfig, pMP3);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_MP3)
{
drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drmp3_bool32 mp3Result;
mp3Result = drmp3_init_file(&pMP3->dr, pFilePath, &mp3AllocationCallbacks);
if (mp3Result != MA_TRUE) {
return MA_INVALID_FILE;
}
ma_mp3_generate_seek_table(pMP3, pConfig, pAllocationCallbacks);
return MA_SUCCESS;
}
#else
{
/* mp3 is disabled. */
(void)pFilePath;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_mp3_init_internal(pConfig, pMP3);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_MP3)
{
drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drmp3_bool32 mp3Result;
mp3Result = drmp3_init_file_w(&pMP3->dr, pFilePath, &mp3AllocationCallbacks);
if (mp3Result != MA_TRUE) {
return MA_INVALID_FILE;
}
ma_mp3_generate_seek_table(pMP3, pConfig, pAllocationCallbacks);
return MA_SUCCESS;
}
#else
{
/* mp3 is disabled. */
(void)pFilePath;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_mp3_init_internal(pConfig, pMP3);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_MP3)
{
drmp3_allocation_callbacks mp3AllocationCallbacks = drmp3_allocation_callbacks_from_miniaudio(pAllocationCallbacks);
drmp3_bool32 mp3Result;
mp3Result = drmp3_init_memory(&pMP3->dr, pData, dataSize, &mp3AllocationCallbacks);
if (mp3Result != MA_TRUE) {
return MA_INVALID_FILE;
}
ma_mp3_generate_seek_table(pMP3, pConfig, pAllocationCallbacks);
return MA_SUCCESS;
}
#else
{
/* mp3 is disabled. */
(void)pData;
(void)dataSize;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API void ma_mp3_uninit(ma_mp3* pMP3, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pMP3 == NULL) {
return;
}
#if !defined(MA_NO_MP3)
{
drmp3_uninit(&pMP3->dr);
}
#else
{
/* mp3 is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
}
#endif
/* Seek points need to be freed after the MP3 decoder has been uninitialized to ensure they're no longer being referenced. */
ma_free(pMP3->pSeekPoints, pAllocationCallbacks);
ma_data_source_uninit(&pMP3->ds);
}
MA_API ma_result ma_mp3_read_pcm_frames(ma_mp3* pMP3, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
if (frameCount == 0) {
return MA_INVALID_ARGS;
}
if (pMP3 == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_MP3)
{
/* We always use floating point format. */
ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
ma_uint64 totalFramesRead = 0;
ma_format format;
ma_mp3_get_data_format(pMP3, &format, NULL, NULL, NULL, 0);
switch (format)
{
case ma_format_f32:
{
totalFramesRead = drmp3_read_pcm_frames_f32(&pMP3->dr, frameCount, (float*)pFramesOut);
} break;
case ma_format_s16:
{
totalFramesRead = drmp3_read_pcm_frames_s16(&pMP3->dr, frameCount, (drmp3_int16*)pFramesOut);
} break;
case ma_format_u8:
case ma_format_s24:
case ma_format_s32:
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_mp3_get_cursor_in_pcm_frames(ma_mp3* pMP3, ma_uint64* pCursor)
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0; /* Safety. */
if (pMP3 == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_MP3)
{
*pCursor = pMP3->dr.currentPCMFrame;
return MA_SUCCESS;
}
#else
{
/* mp3 is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_mp3_get_length_in_pcm_frames(ma_mp3* pMP3, ma_uint64* pLength)
{
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0; /* Safety. */
if (pMP3 == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_MP3)
{
*pLength = drmp3_get_pcm_frame_count(&pMP3->dr);
return MA_SUCCESS;
}
#else
{
/* mp3 is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
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_result result;
ma_mp3* pMP3;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
if (pMP3 == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_mp3_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pMP3);
if (result != MA_SUCCESS) {
ma_free(pMP3, pAllocationCallbacks);
return result;
}
*ppBackend = pMP3;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_mp3* pMP3;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
if (pMP3 == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_mp3_init_file(pFilePath, pConfig, pAllocationCallbacks, pMP3);
if (result != MA_SUCCESS) {
ma_free(pMP3, pAllocationCallbacks);
return result;
}
*ppBackend = pMP3;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_mp3* pMP3;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
if (pMP3 == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_mp3_init_file_w(pFilePath, pConfig, pAllocationCallbacks, pMP3);
if (result != MA_SUCCESS) {
ma_free(pMP3, pAllocationCallbacks);
return result;
}
*ppBackend = pMP3;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_mp3* pMP3;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pMP3 = (ma_mp3*)ma_malloc(sizeof(*pMP3), pAllocationCallbacks);
if (pMP3 == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_mp3_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pMP3);
if (result != MA_SUCCESS) {
ma_free(pMP3, pAllocationCallbacks);
return result;
}
*ppBackend = pMP3;
return MA_SUCCESS;
}
static void ma_decoding_backend_uninit__mp3(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_mp3* pMP3 = (ma_mp3*)pBackend;
(void)pUserData;
ma_mp3_uninit(pMP3, pAllocationCallbacks);
ma_free(pMP3, pAllocationCallbacks);
}
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_mp3 =
{
ma_decoding_backend_init__mp3,
ma_decoding_backend_init_file__mp3,
ma_decoding_backend_init_file_w__mp3,
ma_decoding_backend_init_memory__mp3,
ma_decoding_backend_uninit__mp3
};
static ma_result ma_decoder_init_mp3__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{
return ma_decoder_init_from_vtable(&g_ma_decoding_backend_vtable_mp3, NULL, pConfig, pDecoder);
}
#endif /* dr_mp3_h */
/* Vorbis */
#ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
#define MA_HAS_VORBIS
/* The size in bytes of each chunk of data to read from the Vorbis stream. */
#define MA_VORBIS_DATA_CHUNK_SIZE 4096
typedef struct
{
ma_data_source_base ds;
ma_read_proc onRead;
ma_seek_proc onSeek;
ma_tell_proc onTell;
void* pReadSeekTellUserData;
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. */
ma_format format; /* Only f32 is allowed with stb_vorbis. */
ma_uint32 channels;
ma_uint32 sampleRate;
ma_uint64 cursor;
#if !defined(MA_NO_VORBIS)
stb_vorbis* stb;
ma_bool32 usingPushMode;
struct
{
ma_uint8* pData;
size_t dataSize;
size_t dataCapacity;
ma_uint32 framesConsumed; /* The number of frames consumed in ppPacketData. */
ma_uint32 framesRemaining; /* The number of frames remaining in ppPacketData. */
float** ppPacketData;
} push;
#endif
} ma_stbvorbis;
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);
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);
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);
MA_API void ma_stbvorbis_uninit(ma_stbvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_stbvorbis_seek_to_pcm_frame(ma_stbvorbis* pVorbis, ma_uint64 frameIndex);
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);
MA_API ma_result ma_stbvorbis_get_cursor_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pCursor);
MA_API ma_result ma_stbvorbis_get_length_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pLength);
static ma_result ma_stbvorbis_ds_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
return ma_stbvorbis_read_pcm_frames((ma_stbvorbis*)pDataSource, pFramesOut, frameCount, pFramesRead);
}
static ma_result ma_stbvorbis_ds_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
return ma_stbvorbis_seek_to_pcm_frame((ma_stbvorbis*)pDataSource, frameIndex);
}
static ma_result ma_stbvorbis_ds_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
return ma_stbvorbis_get_data_format((ma_stbvorbis*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}
static ma_result ma_stbvorbis_ds_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
return ma_stbvorbis_get_cursor_in_pcm_frames((ma_stbvorbis*)pDataSource, pCursor);
}
static ma_result ma_stbvorbis_ds_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
return ma_stbvorbis_get_length_in_pcm_frames((ma_stbvorbis*)pDataSource, pLength);
}
static ma_data_source_vtable g_ma_stbvorbis_ds_vtable =
{
ma_stbvorbis_ds_read,
ma_stbvorbis_ds_seek,
ma_stbvorbis_ds_get_data_format,
ma_stbvorbis_ds_get_cursor,
ma_stbvorbis_ds_get_length,
NULL, /* onSetLooping */
0
};
static ma_result ma_stbvorbis_init_internal(const ma_decoding_backend_config* pConfig, ma_stbvorbis* pVorbis)
{
ma_result result;
ma_data_source_config dataSourceConfig;
(void)pConfig;
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pVorbis);
pVorbis->format = ma_format_f32; /* Only supporting f32. */
dataSourceConfig = ma_data_source_config_init();
dataSourceConfig.vtable = &g_ma_stbvorbis_ds_vtable;
result = ma_data_source_init(&dataSourceConfig, &pVorbis->ds);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the base data source. */
}
return MA_SUCCESS;
}
#if !defined(MA_NO_VORBIS)
static ma_result ma_stbvorbis_post_init(ma_stbvorbis* pVorbis)
{
stb_vorbis_info info;
MA_ASSERT(pVorbis != NULL);
info = stb_vorbis_get_info(pVorbis->stb);
pVorbis->channels = info.channels;
pVorbis->sampleRate = info.sample_rate;
return MA_SUCCESS;
}
#endif
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)
{
ma_result result;
result = ma_stbvorbis_init_internal(pConfig, pVorbis);
if (result != MA_SUCCESS) {
return result;
}
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS; /* onRead and onSeek are mandatory. */
}
pVorbis->onRead = onRead;
pVorbis->onSeek = onSeek;
pVorbis->onTell = onTell;
pVorbis->pReadSeekTellUserData = pReadSeekTellUserData;
ma_allocation_callbacks_init_copy(&pVorbis->allocationCallbacks, pAllocationCallbacks);
#if !defined(MA_NO_VORBIS)
{
/*
stb_vorbis lacks a callback based API for it's pulling API which means we're stuck with the
pushing API. In order for us to be able to successfully initialize the decoder we need to
supply it with enough data. We need to keep loading data until we have enough.
*/
stb_vorbis* stb;
size_t dataSize = 0;
size_t dataCapacity = 0;
ma_uint8* pData = NULL; /* <-- Must be initialized to NULL. */
for (;;) {
int vorbisError;
int consumedDataSize; /* <-- Fill by stb_vorbis_open_pushdata(). */
size_t bytesRead;
ma_uint8* pNewData;
/* Allocate memory for the new chunk. */
dataCapacity += MA_VORBIS_DATA_CHUNK_SIZE;
pNewData = (ma_uint8*)ma_realloc(pData, dataCapacity, pAllocationCallbacks);
if (pNewData == NULL) {
ma_free(pData, pAllocationCallbacks);
return MA_OUT_OF_MEMORY;
}
pData = pNewData;
/* Read in the next chunk. */
result = pVorbis->onRead(pVorbis->pReadSeekTellUserData, ma_offset_ptr(pData, dataSize), (dataCapacity - dataSize), &bytesRead);
dataSize += bytesRead;
if (result != MA_SUCCESS) {
ma_free(pData, pAllocationCallbacks);
return result;
}
/* We have a maximum of 31 bits with stb_vorbis. */
if (dataSize > INT_MAX) {
ma_free(pData, pAllocationCallbacks);
return MA_TOO_BIG;
}
stb = stb_vorbis_open_pushdata(pData, (int)dataSize, &consumedDataSize, &vorbisError, NULL);
if (stb != NULL) {
/*
Successfully opened the Vorbis decoder. We might have some leftover unprocessed
data so we'll need to move that down to the front.
*/
dataSize -= (size_t)consumedDataSize; /* Consume the data. */
MA_MOVE_MEMORY(pData, ma_offset_ptr(pData, consumedDataSize), dataSize);
break;
} else {
/* Failed to open the decoder. */
if (vorbisError == VORBIS_need_more_data) {
continue;
} else {
ma_free(pData, pAllocationCallbacks);
return MA_ERROR; /* Failed to open the stb_vorbis decoder. */
}
}
}
MA_ASSERT(stb != NULL);
pVorbis->stb = stb;
pVorbis->push.pData = pData;
pVorbis->push.dataSize = dataSize;
pVorbis->push.dataCapacity = dataCapacity;
pVorbis->usingPushMode = MA_TRUE;
result = ma_stbvorbis_post_init(pVorbis);
if (result != MA_SUCCESS) {
stb_vorbis_close(pVorbis->stb);
ma_free(pData, pAllocationCallbacks);
return result;
}
return MA_SUCCESS;
}
#else
{
/* vorbis is disabled. */
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_stbvorbis_init_internal(pConfig, pVorbis);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_VORBIS)
{
(void)pAllocationCallbacks; /* Don't know how to make use of this with stb_vorbis. */
/* We can use stb_vorbis' pull mode for file based streams. */
pVorbis->stb = stb_vorbis_open_filename(pFilePath, NULL, NULL);
if (pVorbis->stb == NULL) {
return MA_INVALID_FILE;
}
pVorbis->usingPushMode = MA_FALSE;
result = ma_stbvorbis_post_init(pVorbis);
if (result != MA_SUCCESS) {
stb_vorbis_close(pVorbis->stb);
return result;
}
return MA_SUCCESS;
}
#else
{
/* vorbis is disabled. */
(void)pFilePath;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
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)
{
ma_result result;
result = ma_stbvorbis_init_internal(pConfig, pVorbis);
if (result != MA_SUCCESS) {
return result;
}
#if !defined(MA_NO_VORBIS)
{
(void)pAllocationCallbacks;
/* stb_vorbis uses an int as it's size specifier, restricting it to 32-bit even on 64-bit systems. *sigh*. */
if (dataSize > INT_MAX) {
return MA_TOO_BIG;
}
pVorbis->stb = stb_vorbis_open_memory((const unsigned char*)pData, (int)dataSize, NULL, NULL);
if (pVorbis->stb == NULL) {
return MA_INVALID_FILE;
}
pVorbis->usingPushMode = MA_FALSE;
result = ma_stbvorbis_post_init(pVorbis);
if (result != MA_SUCCESS) {
stb_vorbis_close(pVorbis->stb);
return result;
}
return MA_SUCCESS;
}
#else
{
/* vorbis is disabled. */
(void)pData;
(void)dataSize;
(void)pAllocationCallbacks;
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API void ma_stbvorbis_uninit(ma_stbvorbis* pVorbis, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pVorbis == NULL) {
return;
}
#if !defined(MA_NO_VORBIS)
{
stb_vorbis_close(pVorbis->stb);
/* We'll have to clear some memory if we're using push mode. */
if (pVorbis->usingPushMode) {
ma_free(pVorbis->push.pData, pAllocationCallbacks);
}
}
#else
{
/* vorbis is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
}
#endif
ma_data_source_uninit(&pVorbis->ds);
}
MA_API ma_result ma_stbvorbis_read_pcm_frames(ma_stbvorbis* pVorbis, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
if (frameCount == 0) {
return MA_INVALID_ARGS;
}
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_VORBIS)
{
/* We always use floating point format. */
ma_result result = MA_SUCCESS; /* Must be initialized to MA_SUCCESS. */
ma_uint64 totalFramesRead = 0;
ma_format format;
ma_uint32 channels;
ma_stbvorbis_get_data_format(pVorbis, &format, &channels, NULL, NULL, 0);
if (format == ma_format_f32) {
/* We read differently depending on whether or not we're using push mode. */
if (pVorbis->usingPushMode) {
/* Push mode. This is the complex case. */
float* pFramesOutF32 = (float*)pFramesOut;
while (totalFramesRead < frameCount) {
/* The first thing to do is read from any already-cached frames. */
ma_uint32 framesToReadFromCache = (ma_uint32)ma_min(pVorbis->push.framesRemaining, (frameCount - totalFramesRead)); /* Safe cast because pVorbis->framesRemaining is 32-bit. */
/* The output pointer can be null in which case we just treate it as a seek. */
if (pFramesOut != NULL) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
MA_API ma_result ma_stbvorbis_get_cursor_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pCursor)
{
if (pCursor == NULL) {
return MA_INVALID_ARGS;
}
*pCursor = 0; /* Safety. */
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_VORBIS)
{
*pCursor = pVorbis->cursor;
return MA_SUCCESS;
}
#else
{
/* vorbis is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
MA_API ma_result ma_stbvorbis_get_length_in_pcm_frames(ma_stbvorbis* pVorbis, ma_uint64* pLength)
{
if (pLength == NULL) {
return MA_INVALID_ARGS;
}
*pLength = 0; /* Safety. */
if (pVorbis == NULL) {
return MA_INVALID_ARGS;
}
#if !defined(MA_NO_VORBIS)
{
if (pVorbis->usingPushMode) {
*pLength = 0; /* I don't know of a good way to determine this reliably with stb_vorbis and push mode. */
} else {
*pLength = stb_vorbis_stream_length_in_samples(pVorbis->stb);
}
return MA_SUCCESS;
}
#else
{
/* vorbis is disabled. Should never hit this since initialization would have failed. */
MA_ASSERT(MA_FALSE);
return MA_NOT_IMPLEMENTED;
}
#endif
}
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* pAllocationCal...
{
ma_result result;
ma_stbvorbis* pVorbis;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
if (pVorbis == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_stbvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
return result;
}
*ppBackend = pVorbis;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_stbvorbis* pVorbis;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
if (pVorbis == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_stbvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
return result;
}
*ppBackend = pVorbis;
return MA_SUCCESS;
}
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)
{
ma_result result;
ma_stbvorbis* pVorbis;
(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. */
/* For now we're just allocating the decoder backend on the heap. */
pVorbis = (ma_stbvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
if (pVorbis == NULL) {
return MA_OUT_OF_MEMORY;
}
result = ma_stbvorbis_init_memory(pData, dataSize, pConfig, pAllocationCallbacks, pVorbis);
if (result != MA_SUCCESS) {
ma_free(pVorbis, pAllocationCallbacks);
return result;
}
*ppBackend = pVorbis;
return MA_SUCCESS;
}
static void ma_decoding_backend_uninit__stbvorbis(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_stbvorbis* pVorbis = (ma_stbvorbis*)pBackend;
(void)pUserData;
ma_stbvorbis_uninit(pVorbis, pAllocationCallbacks);
ma_free(pVorbis, pAllocationCallbacks);
}
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_stbvorbis =
{
ma_decoding_backend_init__stbvorbis,
ma_decoding_backend_init_file__stbvorbis,
NULL, /* onInitFileW() */
ma_decoding_backend_init_memory__stbvorbis,
ma_decoding_backend_uninit__stbvorbis
};
static ma_result ma_decoder_init_vorbis__internal(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{
return ma_decoder_init_from_vtable(&g_ma_decoding_backend_vtable_stbvorbis, NULL, pConfig, pDecoder);
}
#endif /* STB_VORBIS_INCLUDE_STB_VORBIS_H */
static ma_result ma_decoder__init_allocation_callbacks(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{
MA_ASSERT(pDecoder != NULL);
if (pConfig != NULL) {
return ma_allocation_callbacks_init_copy(&pDecoder->allocationCallbacks, &pConfig->allocationCallbacks);
} else {
pDecoder->allocationCallbacks = ma_allocation_callbacks_init_default();
return MA_SUCCESS;
}
}
static ma_result ma_decoder__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
return ma_decoder_read_pcm_frames((ma_decoder*)pDataSource, pFramesOut, frameCount, pFramesRead);
}
static ma_result ma_decoder__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
return ma_decoder_seek_to_pcm_frame((ma_decoder*)pDataSource, frameIndex);
}
static ma_result ma_decoder__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
return ma_decoder_get_data_format((ma_decoder*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}
static ma_result ma_decoder__data_source_on_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
return ma_decoder_get_cursor_in_pcm_frames((ma_decoder*)pDataSource, pCursor);
}
static ma_result ma_decoder__data_source_on_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
return ma_decoder_get_length_in_pcm_frames((ma_decoder*)pDataSource, pLength);
}
static ma_data_source_vtable g_ma_decoder_data_source_vtable =
{
ma_decoder__data_source_on_read,
ma_decoder__data_source_on_seek,
ma_decoder__data_source_on_get_data_format,
ma_decoder__data_source_on_get_cursor,
ma_decoder__data_source_on_get_length,
NULL, /* onSetLooping */
0
};
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)
{
ma_result result;
ma_data_source_config dataSourceConfig;
MA_ASSERT(pConfig != NULL);
if (pDecoder == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDecoder);
if (onRead == NULL || onSeek == NULL) {
return MA_INVALID_ARGS;
}
dataSourceConfig = ma_data_source_config_init();
dataSourceConfig.vtable = &g_ma_decoder_data_source_vtable;
result = ma_data_source_init(&dataSourceConfig, &pDecoder->ds);
if (result != MA_SUCCESS) {
return result;
}
pDecoder->onRead = onRead;
pDecoder->onSeek = onSeek;
pDecoder->onTell = onTell;
pDecoder->pUserData = pUserData;
result = ma_decoder__init_allocation_callbacks(pConfig, pDecoder);
if (result != MA_SUCCESS) {
ma_data_source_uninit(&pDecoder->ds);
return result;
}
return MA_SUCCESS;
}
static ma_result ma_decoder__postinit(const ma_decoder_config* pConfig, ma_decoder* pDecoder)
{
ma_result result;
result = ma_decoder__init_data_converter(pDecoder, pConfig);
/* If we failed post initialization we need to uninitialize the decoder before returning to prevent a memory leak. */
if (result != MA_SUCCESS) {
ma_decoder_uninit(pDecoder);
return result;
}
return result;
}
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)
{
ma_result result = MA_NO_BACKEND;
MA_ASSERT(pConfig != NULL);
MA_ASSERT(pDecoder != NULL);
/* Silence some warnings in the case that we don't have any decoder backends enabled. */
(void)onRead;
(void)onSeek;
(void)pUserData;
/* If we've specified a specific encoding type, try that first. */
if (pConfig->encodingFormat != ma_encoding_format_unknown) {
#ifdef MA_HAS_WAV
if (pConfig->encodingFormat == ma_encoding_format_wav) {
result = ma_decoder_init_wav__internal(pConfig, pDecoder);
}
#endif
#ifdef MA_HAS_FLAC
if (pConfig->encodingFormat == ma_encoding_format_flac) {
result = ma_decoder_init_flac__internal(pConfig, pDecoder);
}
#endif
#ifdef MA_HAS_MP3
if (pConfig->encodingFormat == ma_encoding_format_mp3) {
result = ma_decoder_init_mp3__internal(pConfig, pDecoder);
}
#endif
#ifdef MA_HAS_VORBIS
if (pConfig->encodingFormat == ma_encoding_format_vorbis) {
result = ma_decoder_init_vorbis__internal(pConfig, pDecoder);
}
#endif
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
{
ma_decoder_config config;
ma_decoder decoder;
ma_result result;
if (pFrameCountOut != NULL) {
*pFrameCountOut = 0;
}
if (ppPCMFramesOut != NULL) {
*ppPCMFramesOut = NULL;
}
if (pData == NULL || dataSize == 0) {
return MA_INVALID_ARGS;
}
config = ma_decoder_config_init_copy(pConfig);
result = ma_decoder_init_memory(pData, dataSize, &config, &decoder);
if (result != MA_SUCCESS) {
return result;
}
return ma_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
}
#endif /* MA_NO_DECODING */
#ifndef MA_NO_ENCODING
#if defined(MA_HAS_WAV)
static size_t ma_encoder__internal_on_write_wav(void* pUserData, const void* pData, size_t bytesToWrite)
{
ma_encoder* pEncoder = (ma_encoder*)pUserData;
size_t bytesWritten = 0;
MA_ASSERT(pEncoder != NULL);
pEncoder->onWrite(pEncoder, pData, bytesToWrite, &bytesWritten);
return bytesWritten;
}
static drwav_bool32 ma_encoder__internal_on_seek_wav(void* pUserData, int offset, drwav_seek_origin origin)
{
ma_encoder* pEncoder = (ma_encoder*)pUserData;
ma_result result;
MA_ASSERT(pEncoder != NULL);
result = pEncoder->onSeek(pEncoder, offset, (origin == drwav_seek_origin_start) ? ma_seek_origin_start : ma_seek_origin_current);
if (result != MA_SUCCESS) {
return DRWAV_FALSE;
} else {
return DRWAV_TRUE;
}
}
static ma_result ma_encoder__on_init_wav(ma_encoder* pEncoder)
{
drwav_data_format wavFormat;
drwav_allocation_callbacks allocationCallbacks;
drwav* pWav;
MA_ASSERT(pEncoder != NULL);
pWav = (drwav*)ma_malloc(sizeof(*pWav), &pEncoder->config.allocationCallbacks);
if (pWav == NULL) {
return MA_OUT_OF_MEMORY;
}
wavFormat.container = drwav_container_riff;
wavFormat.channels = pEncoder->config.channels;
wavFormat.sampleRate = pEncoder->config.sampleRate;
wavFormat.bitsPerSample = ma_get_bytes_per_sample(pEncoder->config.format) * 8;
if (pEncoder->config.format == ma_format_f32) {
wavFormat.format = DR_WAVE_FORMAT_IEEE_FLOAT;
} else {
wavFormat.format = DR_WAVE_FORMAT_PCM;
}
allocationCallbacks.pUserData = pEncoder->config.allocationCallbacks.pUserData;
allocationCallbacks.onMalloc = pEncoder->config.allocationCallbacks.onMalloc;
allocationCallbacks.onRealloc = pEncoder->config.allocationCallbacks.onRealloc;
allocationCallbacks.onFree = pEncoder->config.allocationCallbacks.onFree;
if (!drwav_init_write(pWav, &wavFormat, ma_encoder__internal_on_write_wav, ma_encoder__internal_on_seek_wav, pEncoder, &allocationCallbacks)) {
return MA_ERROR;
}
pEncoder->pInternalEncoder = pWav;
return MA_SUCCESS;
}
static void ma_encoder__on_uninit_wav(ma_encoder* pEncoder)
{
drwav* pWav;
MA_ASSERT(pEncoder != NULL);
pWav = (drwav*)pEncoder->pInternalEncoder;
MA_ASSERT(pWav != NULL);
drwav_uninit(pWav);
ma_free(pWav, &pEncoder->config.allocationCallbacks);
}
static ma_result ma_encoder__on_write_pcm_frames_wav(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount, ma_uint64* pFramesWritten)
{
drwav* pWav;
ma_uint64 framesWritten;
MA_ASSERT(pEncoder != NULL);
pWav = (drwav*)pEncoder->pInternalEncoder;
MA_ASSERT(pWav != NULL);
framesWritten = drwav_write_pcm_frames(pWav, frameCount, pFramesIn);
if (pFramesWritten != NULL) {
*pFramesWritten = framesWritten;
}
return MA_SUCCESS;
}
#endif
MA_API ma_encoder_config ma_encoder_config_init(ma_encoding_format encodingFormat, ma_format format, ma_uint32 channels, ma_uint32 sampleRate)
{
ma_encoder_config config;
MA_ZERO_OBJECT(&config);
config.encodingFormat = encodingFormat;
config.format = format;
config.channels = channels;
config.sampleRate = sampleRate;
return config;
}
MA_API ma_result ma_encoder_preinit(const ma_encoder_config* pConfig, ma_encoder* pEncoder)
{
ma_result result;
if (pEncoder == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pEncoder);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->format == ma_format_unknown || pConfig->channels == 0 || pConfig->sampleRate == 0) {
return MA_INVALID_ARGS;
}
pEncoder->config = *pConfig;
result = ma_allocation_callbacks_init_copy(&pEncoder->config.allocationCallbacks, &pConfig->allocationCallbacks);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_encoder_init__internal(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void* pUserData, ma_encoder* pEncoder)
{
ma_result result = MA_SUCCESS;
/* This assumes ma_encoder_preinit() has been called prior. */
MA_ASSERT(pEncoder != NULL);
if (onWrite == NULL || onSeek == NULL) {
return MA_INVALID_ARGS;
}
pEncoder->onWrite = onWrite;
pEncoder->onSeek = onSeek;
pEncoder->pUserData = pUserData;
switch (pEncoder->config.encodingFormat)
{
case ma_encoding_format_wav:
{
#if defined(MA_HAS_WAV)
pEncoder->onInit = ma_encoder__on_init_wav;
pEncoder->onUninit = ma_encoder__on_uninit_wav;
pEncoder->onWritePCMFrames = ma_encoder__on_write_pcm_frames_wav;
#else
result = MA_NO_BACKEND;
#endif
} break;
default:
{
result = MA_INVALID_ARGS;
} break;
}
/* Getting here means we should have our backend callbacks set up. */
if (result == MA_SUCCESS) {
result = pEncoder->onInit(pEncoder);
}
return result;
}
static ma_result ma_encoder__on_write_vfs(ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite, size_t* pBytesWritten)
{
return ma_vfs_or_default_write(pEncoder->data.vfs.pVFS, pEncoder->data.vfs.file, pBufferIn, bytesToWrite, pBytesWritten);
}
static ma_result ma_encoder__on_seek_vfs(ma_encoder* pEncoder, ma_int64 offset, ma_seek_origin origin)
{
return ma_vfs_or_default_seek(pEncoder->data.vfs.pVFS, pEncoder->data.vfs.file, offset, origin);
}
MA_API ma_result ma_encoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
{
ma_result result;
ma_vfs_file file;
result = ma_encoder_preinit(pConfig, pEncoder);
if (result != MA_SUCCESS) {
return result;
}
/* Now open the file. If this fails we don't need to uninitialize the encoder. */
result = ma_vfs_or_default_open(pVFS, pFilePath, MA_OPEN_MODE_WRITE, &file);
if (result != MA_SUCCESS) {
return result;
}
pEncoder->data.vfs.pVFS = pVFS;
pEncoder->data.vfs.file = file;
result = ma_encoder_init__internal(ma_encoder__on_write_vfs, ma_encoder__on_seek_vfs, NULL, pEncoder);
if (result != MA_SUCCESS) {
ma_vfs_or_default_close(pVFS, file);
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_encoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
{
ma_result result;
ma_vfs_file file;
result = ma_encoder_preinit(pConfig, pEncoder);
if (result != MA_SUCCESS) {
return result;
}
/* Now open the file. If this fails we don't need to uninitialize the encoder. */
result = ma_vfs_or_default_open_w(pVFS, pFilePath, MA_OPEN_MODE_WRITE, &file);
if (result != MA_SUCCESS) {
return result;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
*pHeapSizeInBytes = heapLayout.sizeInBytes;
return MA_SUCCESS;
}
MA_API ma_result ma_noise_init_preallocated(const ma_noise_config* pConfig, void* pHeap, ma_noise* pNoise)
{
ma_result result;
ma_noise_heap_layout heapLayout;
ma_data_source_config dataSourceConfig;
ma_uint32 iChannel;
if (pNoise == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNoise);
result = ma_noise_get_heap_layout(pConfig, &heapLayout);
if (result != MA_SUCCESS) {
return result;
}
pNoise->_pHeap = pHeap;
MA_ZERO_MEMORY(pNoise->_pHeap, heapLayout.sizeInBytes);
dataSourceConfig = ma_data_source_config_init();
dataSourceConfig.vtable = &g_ma_noise_data_source_vtable;
result = ma_data_source_init(&dataSourceConfig, &pNoise->ds);
if (result != MA_SUCCESS) {
return result;
}
pNoise->config = *pConfig;
ma_lcg_seed(&pNoise->lcg, pConfig->seed);
if (pNoise->config.type == ma_noise_type_pink) {
pNoise->state.pink.bin = (double** )ma_offset_ptr(pHeap, heapLayout.pink.binOffset);
pNoise->state.pink.accumulation = (double* )ma_offset_ptr(pHeap, heapLayout.pink.accumulationOffset);
pNoise->state.pink.counter = (ma_uint32*)ma_offset_ptr(pHeap, heapLayout.pink.counterOffset);
for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
pNoise->state.pink.bin[iChannel] = (double*)ma_offset_ptr(pHeap, heapLayout.pink.binOffset + (sizeof(double*) * pConfig->channels) + (sizeof(double) * MA_PINK_NOISE_BIN_SIZE * iChannel));
pNoise->state.pink.accumulation[iChannel] = 0;
pNoise->state.pink.counter[iChannel] = 1;
}
}
if (pNoise->config.type == ma_noise_type_brownian) {
pNoise->state.brownian.accumulation = (double*)ma_offset_ptr(pHeap, heapLayout.brownian.accumulationOffset);
for (iChannel = 0; iChannel < pConfig->channels; iChannel += 1) {
pNoise->state.brownian.accumulation[iChannel] = 0;
}
}
return MA_SUCCESS;
}
MA_API ma_result ma_noise_init(const ma_noise_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_noise* pNoise)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_noise_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_noise_init_preallocated(pConfig, pHeap, pNoise);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pNoise->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_noise_uninit(ma_noise* pNoise, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pNoise == NULL) {
return;
}
ma_data_source_uninit(&pNoise->ds);
if (pNoise->_ownsHeap) {
ma_free(pNoise->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_result ma_noise_set_amplitude(ma_noise* pNoise, double amplitude)
{
if (pNoise == NULL) {
return MA_INVALID_ARGS;
}
pNoise->config.amplitude = amplitude;
return MA_SUCCESS;
}
MA_API ma_result ma_noise_set_seed(ma_noise* pNoise, ma_int32 seed)
{
if (pNoise == NULL) {
return MA_INVALID_ARGS;
}
pNoise->lcg.state = seed;
return MA_SUCCESS;
}
MA_API ma_result ma_noise_set_type(ma_noise* pNoise, ma_noise_type type)
{
if (pNoise == NULL) {
return MA_INVALID_ARGS;
}
pNoise->config.type = type;
return MA_SUCCESS;
}
static MA_INLINE float ma_noise_f32_white(ma_noise* pNoise)
{
return (float)(ma_lcg_rand_f64(&pNoise->lcg) * pNoise->config.amplitude);
}
static MA_INLINE ma_int16 ma_noise_s16_white(ma_noise* pNoise)
{
return ma_pcm_sample_f32_to_s16(ma_noise_f32_white(pNoise));
}
static MA_INLINE ma_uint64 ma_noise_read_pcm_frames__white(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount)
{
ma_uint64 iFrame;
ma_uint32 iChannel;
const ma_uint32 channels = pNoise->config.channels;
MA_ASSUME(channels > 0);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (job.toc.breakup.code == MA_JOB_TYPE_QUIT) {
break;
}
ma_job_process(&job);
}
return (ma_thread_result)0;
}
#endif
MA_API ma_resource_manager_config ma_resource_manager_config_init(void)
{
ma_resource_manager_config config;
MA_ZERO_OBJECT(&config);
config.decodedFormat = ma_format_unknown;
config.decodedChannels = 0;
config.decodedSampleRate = 0;
config.jobThreadCount = 1; /* A single miniaudio-managed job thread by default. */
config.jobQueueCapacity = MA_JOB_TYPE_RESOURCE_MANAGER_QUEUE_CAPACITY;
/* Flags. */
config.flags = 0;
#ifdef MA_NO_THREADING
{
/* Threading is disabled at compile time so disable threading at runtime as well by default. */
config.flags |= MA_RESOURCE_MANAGER_FLAG_NO_THREADING;
config.jobThreadCount = 0;
}
#endif
return config;
}
MA_API ma_result ma_resource_manager_init(const ma_resource_manager_config* pConfig, ma_resource_manager* pResourceManager)
{
ma_result result;
ma_job_queue_config jobQueueConfig;
if (pResourceManager == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pResourceManager);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
#ifndef MA_NO_THREADING
{
if (pConfig->jobThreadCount > ma_countof(pResourceManager->jobThreads)) {
return MA_INVALID_ARGS; /* Requesting too many job threads. */
}
}
#endif
pResourceManager->config = *pConfig;
ma_allocation_callbacks_init_copy(&pResourceManager->config.allocationCallbacks, &pConfig->allocationCallbacks);
/* Get the log set up early so we can start using it as soon as possible. */
if (pResourceManager->config.pLog == NULL) {
result = ma_log_init(&pResourceManager->config.allocationCallbacks, &pResourceManager->log);
if (result == MA_SUCCESS) {
pResourceManager->config.pLog = &pResourceManager->log;
} else {
pResourceManager->config.pLog = NULL; /* Logging is unavailable. */
}
}
if (pResourceManager->config.pVFS == NULL) {
result = ma_default_vfs_init(&pResourceManager->defaultVFS, &pResourceManager->config.allocationCallbacks);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the default file system. */
}
pResourceManager->config.pVFS = &pResourceManager->defaultVFS;
}
/* If threading has been disabled at compile time, enfore it at run time as well. */
#ifdef MA_NO_THREADING
{
pResourceManager->config.flags |= MA_RESOURCE_MANAGER_FLAG_NO_THREADING;
}
#endif
/* We need to force MA_RESOURCE_MANAGER_FLAG_NON_BLOCKING if MA_RESOURCE_MANAGER_FLAG_NO_THREADING is set. */
if ((pResourceManager->config.flags & MA_RESOURCE_MANAGER_FLAG_NO_THREADING) != 0) {
pResourceManager->config.flags |= MA_RESOURCE_MANAGER_FLAG_NON_BLOCKING;
/* We cannot allow job threads when MA_RESOURCE_MANAGER_FLAG_NO_THREADING has been set. This is an invalid use case. */
if (pResourceManager->config.jobThreadCount > 0) {
return MA_INVALID_ARGS;
}
}
/* Job queue. */
jobQueueConfig.capacity = pResourceManager->config.jobQueueCapacity;
jobQueueConfig.flags = 0;
if ((pResourceManager->config.flags & MA_RESOURCE_MANAGER_FLAG_NON_BLOCKING) != 0) {
if (pResourceManager->config.jobThreadCount > 0) {
return MA_INVALID_ARGS; /* Non-blocking mode is only valid for self-managed job threads. */
}
jobQueueConfig.flags |= MA_JOB_QUEUE_FLAG_NON_BLOCKING;
}
result = ma_job_queue_init(&jobQueueConfig, &pResourceManager->config.allocationCallbacks, &pResourceManager->jobQueue);
if (result != MA_SUCCESS) {
return result;
}
/* Custom decoding backends. */
if (pConfig->ppCustomDecodingBackendVTables != NULL && pConfig->customDecodingBackendCount > 0) {
size_t sizeInBytes = sizeof(*pResourceManager->config.ppCustomDecodingBackendVTables) * pConfig->customDecodingBackendCount;
pResourceManager->config.ppCustomDecodingBackendVTables = (ma_decoding_backend_vtable**)ma_malloc(sizeInBytes, &pResourceManager->config.allocationCallbacks);
if (pResourceManager->config.ppCustomDecodingBackendVTables == NULL) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pDataStream = (ma_resource_manager_data_stream*)pJob->data.resourceManager.seekDataStream.pDataStream;
MA_ASSERT(pDataStream != NULL);
pResourceManager = pDataStream->pResourceManager;
if (pJob->order != c89atomic_load_32(&pDataStream->executionPointer)) {
return ma_resource_manager_post_job(pResourceManager, pJob); /* Out of order. */
}
/* For streams the status should be MA_SUCCESS for this to do anything. */
if (ma_resource_manager_data_stream_result(pDataStream) != MA_SUCCESS || pDataStream->isDecoderInitialized == MA_FALSE) {
result = MA_INVALID_OPERATION;
goto done;
}
/*
With seeking we just assume both pages are invalid and the relative frame cursor at position 0. This is basically exactly the same as loading, except
instead of initializing the decoder, we seek to a frame.
*/
ma_decoder_seek_to_pcm_frame(&pDataStream->decoder, pJob->data.resourceManager.seekDataStream.frameIndex);
/* After seeking we'll need to reload the pages. */
ma_resource_manager_data_stream_fill_pages(pDataStream);
/* We need to let the public API know that we're done seeking. */
c89atomic_fetch_sub_32(&pDataStream->seekCounter, 1);
done:
c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);
return result;
}
MA_API ma_result ma_resource_manager_process_job(ma_resource_manager* pResourceManager, ma_job* pJob)
{
if (pResourceManager == NULL || pJob == NULL) {
return MA_INVALID_ARGS;
}
return ma_job_process(pJob);
}
MA_API ma_result ma_resource_manager_process_next_job(ma_resource_manager* pResourceManager)
{
ma_result result;
ma_job job;
if (pResourceManager == NULL) {
return MA_INVALID_ARGS;
}
/* This will return MA_CANCELLED if the next job is a quit job. */
result = ma_resource_manager_next_job(pResourceManager, &job);
if (result != MA_SUCCESS) {
return result;
}
return ma_job_process(&job);
}
#else
/* We'll get here if the resource manager is being excluded from the build. We need to define the job processing callbacks as no-ops. */
static ma_result ma_job_process__resource_manager__load_data_buffer_node(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__free_data_buffer_node(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__page_data_buffer_node(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__load_data_buffer(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__free_data_buffer(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__load_data_stream(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__free_data_stream(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__page_data_stream(ma_job* pJob) { return ma_job_process__noop(pJob); }
static ma_result ma_job_process__resource_manager__seek_data_stream(ma_job* pJob) { return ma_job_process__noop(pJob); }
#endif /* MA_NO_RESOURCE_MANAGER */
#ifndef MA_NO_NODE_GRAPH
/* 10ms @ 48K = 480. Must never exceed 65535. */
#ifndef MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS
#define MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS 480
#endif
static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusIndex, float* pFramesOut, ma_uint32 frameCount, ma_uint32* pFramesRead, ma_uint64 globalTime);
MA_API void ma_debug_fill_pcm_frames_with_sine_wave(float* pFramesOut, ma_uint32 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate)
{
#ifndef MA_NO_GENERATION
{
ma_waveform_config waveformConfig;
ma_waveform waveform;
waveformConfig = ma_waveform_config_init(format, channels, sampleRate, ma_waveform_type_sine, 1.0, 400);
ma_waveform_init(&waveformConfig, &waveform);
ma_waveform_read_pcm_frames(&waveform, pFramesOut, frameCount, NULL);
}
#else
{
(void)pFramesOut;
(void)frameCount;
(void)format;
(void)channels;
(void)sampleRate;
#if defined(MA_DEBUG_OUTPUT)
{
#if _MSC_VER
#pragma message ("ma_debug_fill_pcm_frames_with_sine_wave() will do nothing because MA_NO_GENERATION is enabled.")
#endif
}
#endif
}
#endif
}
static ma_result ma_mix_pcm_frames_f32(float* pDst, const float* pSrc, ma_uint64 frameCount, ma_uint32 channels, float volume)
{
ma_uint64 iSample;
ma_uint64 sampleCount;
if (pDst == NULL || pSrc == NULL || channels == 0) {
return MA_INVALID_ARGS;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
return c89atomic_load_32(&pNodeGraph->isReading);
}
#endif
static void ma_node_graph_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_node_graph* pNodeGraph = (ma_node_graph*)pNode;
ma_uint64 framesRead;
ma_node_graph_read_pcm_frames(pNodeGraph, ppFramesOut[0], *pFrameCountOut, &framesRead);
*pFrameCountOut = (ma_uint32)framesRead; /* Safe cast. */
(void)ppFramesIn;
(void)pFrameCountIn;
}
static ma_node_vtable g_node_graph_node_vtable =
{
ma_node_graph_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
0, /* 0 input buses. */
1, /* 1 output bus. */
0 /* Flags. */
};
static void ma_node_graph_endpoint_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
MA_ASSERT(pNode != NULL);
MA_ASSERT(ma_node_get_input_bus_count(pNode) == 1);
MA_ASSERT(ma_node_get_output_bus_count(pNode) == 1);
/* Input channel count needs to be the same as the output channel count. */
MA_ASSERT(ma_node_get_input_channels(pNode, 0) == ma_node_get_output_channels(pNode, 0));
/* We don't need to do anything here because it's a passthrough. */
(void)pNode;
(void)ppFramesIn;
(void)pFrameCountIn;
(void)ppFramesOut;
(void)pFrameCountOut;
#if 0
/* The data has already been mixed. We just need to move it to the output buffer. */
if (ppFramesIn != NULL) {
ma_copy_pcm_frames(ppFramesOut[0], ppFramesIn[0], *pFrameCountOut, ma_format_f32, ma_node_get_output_channels(pNode, 0));
}
#endif
}
static ma_node_vtable g_node_graph_endpoint_vtable =
{
ma_node_graph_endpoint_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* 1 input bus. */
1, /* 1 output bus. */
MA_NODE_FLAG_PASSTHROUGH /* Flags. The endpoint is a passthrough. */
};
MA_API ma_result ma_node_graph_init(const ma_node_graph_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_node_graph* pNodeGraph)
{
ma_result result;
ma_node_config baseConfig;
ma_node_config endpointConfig;
if (pNodeGraph == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNodeGraph);
pNodeGraph->nodeCacheCapInFrames = pConfig->nodeCacheCapInFrames;
if (pNodeGraph->nodeCacheCapInFrames == 0) {
pNodeGraph->nodeCacheCapInFrames = MA_DEFAULT_NODE_CACHE_CAP_IN_FRAMES_PER_BUS;
}
/* Base node so we can use the node graph as a node into another graph. */
baseConfig = ma_node_config_init();
baseConfig.vtable = &g_node_graph_node_vtable;
baseConfig.pOutputChannels = &pConfig->channels;
result = ma_node_init(pNodeGraph, &baseConfig, pAllocationCallbacks, &pNodeGraph->base);
if (result != MA_SUCCESS) {
return result;
}
/* Endpoint. */
endpointConfig = ma_node_config_init();
endpointConfig.vtable = &g_node_graph_endpoint_vtable;
endpointConfig.pInputChannels = &pConfig->channels;
endpointConfig.pOutputChannels = &pConfig->channels;
result = ma_node_init(pNodeGraph, &endpointConfig, pAllocationCallbacks, &pNodeGraph->endpoint);
if (result != MA_SUCCESS) {
ma_node_uninit(&pNodeGraph->base, pAllocationCallbacks);
return result;
}
return MA_SUCCESS;
}
MA_API void ma_node_graph_uninit(ma_node_graph* pNodeGraph, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pNodeGraph == NULL) {
return;
}
ma_node_uninit(&pNodeGraph->endpoint, pAllocationCallbacks);
}
MA_API ma_node* ma_node_graph_get_endpoint(ma_node_graph* pNodeGraph)
{
if (pNodeGraph == NULL) {
return NULL;
}
return &pNodeGraph->endpoint;
}
MA_API ma_result ma_node_graph_read_pcm_frames(ma_node_graph* pNodeGraph, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
ma_result result = MA_SUCCESS;
ma_uint64 totalFramesRead;
ma_uint32 channels;
if (pFramesRead != NULL) {
*pFramesRead = 0; /* Safety. */
}
if (pNodeGraph == NULL) {
return MA_INVALID_ARGS;
}
channels = ma_node_get_output_channels(&pNodeGraph->endpoint, 0);
/* We'll be nice and try to do a full read of all frameCount frames. */
totalFramesRead = 0;
while (totalFramesRead < frameCount) {
ma_uint32 framesJustRead;
ma_uint64 framesToRead = frameCount - totalFramesRead;
if (framesToRead > 0xFFFFFFFF) {
framesToRead = 0xFFFFFFFF;
}
ma_node_graph_set_is_reading(pNodeGraph, MA_TRUE);
{
result = ma_node_read_pcm_frames(&pNodeGraph->endpoint, 0, (float*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, ma_format_f32, channels), (ma_uint32)framesToRead, &framesJustRead, ma_node_get_time(&pNodeGraph->endpoint));
}
ma_node_graph_set_is_reading(pNodeGraph, MA_FALSE);
totalFramesRead += framesJustRead;
if (result != MA_SUCCESS) {
break;
}
/* Abort if we weren't able to read any frames or else we risk getting stuck in a loop. */
if (framesJustRead == 0) {
break;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pNodeBase->pInputBuses = pNodeBase->_inputBuses;
}
if (heapLayout.outputBusOffset != MA_SIZE_MAX) {
pNodeBase->pOutputBuses = (ma_node_output_bus*)ma_offset_ptr(pHeap, heapLayout.inputBusOffset);
} else {
pNodeBase->pOutputBuses = pNodeBase->_outputBuses;
}
if (heapLayout.cachedDataOffset != MA_SIZE_MAX) {
pNodeBase->pCachedData = (float*)ma_offset_ptr(pHeap, heapLayout.cachedDataOffset);
pNodeBase->cachedDataCapInFramesPerBus = pNodeGraph->nodeCacheCapInFrames;
} else {
pNodeBase->pCachedData = NULL;
}
/* We need to run an initialization step for each input and output bus. */
for (iInputBus = 0; iInputBus < ma_node_get_input_bus_count(pNodeBase); iInputBus += 1) {
result = ma_node_input_bus_init(pConfig->pInputChannels[iInputBus], &pNodeBase->pInputBuses[iInputBus]);
if (result != MA_SUCCESS) {
return result;
}
}
for (iOutputBus = 0; iOutputBus < ma_node_get_output_bus_count(pNodeBase); iOutputBus += 1) {
result = ma_node_output_bus_init(pNodeBase, iOutputBus, pConfig->pOutputChannels[iOutputBus], &pNodeBase->pOutputBuses[iOutputBus]);
if (result != MA_SUCCESS) {
return result;
}
}
/* The cached data needs to be initialized to silence (or a sine wave tone if we're debugging). */
if (pNodeBase->pCachedData != NULL) {
ma_uint32 iBus;
#if 1 /* Toggle this between 0 and 1 to turn debugging on or off. 1 = fill with a sine wave for debugging; 0 = fill with silence. */
/* For safety we'll go ahead and default the buffer to silence. */
for (iBus = 0; iBus < ma_node_get_input_bus_count(pNodeBase); iBus += 1) {
ma_silence_pcm_frames(ma_node_get_cached_input_ptr(pNode, iBus), pNodeBase->cachedDataCapInFramesPerBus, ma_format_f32, ma_node_input_bus_get_channels(&pNodeBase->pInputBuses[iBus]));
}
for (iBus = 0; iBus < ma_node_get_output_bus_count(pNodeBase); iBus += 1) {
ma_silence_pcm_frames(ma_node_get_cached_output_ptr(pNode, iBus), pNodeBase->cachedDataCapInFramesPerBus, ma_format_f32, ma_node_output_bus_get_channels(&pNodeBase->pOutputBuses[iBus]));
}
#else
/* For debugging. Default to a sine wave. */
for (iBus = 0; iBus < ma_node_get_input_bus_count(pNodeBase); iBus += 1) {
ma_debug_fill_pcm_frames_with_sine_wave(ma_node_get_cached_input_ptr(pNode, iBus), pNodeBase->cachedDataCapInFramesPerBus, ma_format_f32, ma_node_input_bus_get_channels(&pNodeBase->pInputBuses[iBus]), 48000);
}
for (iBus = 0; iBus < ma_node_get_output_bus_count(pNodeBase); iBus += 1) {
ma_debug_fill_pcm_frames_with_sine_wave(ma_node_get_cached_output_ptr(pNode, iBus), pNodeBase->cachedDataCapInFramesPerBus, ma_format_f32, ma_node_output_bus_get_channels(&pNodeBase->pOutputBuses[iBus]), 48000);
}
#endif
}
return MA_SUCCESS;
}
MA_API ma_result ma_node_init(ma_node_graph* pNodeGraph, const ma_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_node* pNode)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_node_get_heap_size(pNodeGraph, pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_node_init_preallocated(pNodeGraph, pConfig, pHeap, pNode);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
((ma_node_base*)pNode)->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_node_uninit(ma_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_node_base* pNodeBase = (ma_node_base*)pNode;
if (pNodeBase == NULL) {
return;
}
/*
The first thing we need to do is fully detach the node. This will detach all inputs and
outputs. We need to do this first because it will sever the connection with the node graph and
allow us to complete uninitialization without needing to worry about thread-safety with the
audio thread. The detachment process will wait for any local processing of the node to finish.
*/
ma_node_detach_full(pNode);
/*
At this point the node should be completely unreferenced by the node graph and we can finish up
the uninitialization process without needing to worry about thread-safety.
*/
if (pNodeBase->_ownsHeap) {
ma_free(pNodeBase->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_node_graph* ma_node_get_node_graph(const ma_node* pNode)
{
if (pNode == NULL) {
return NULL;
}
return ((const ma_node_base*)pNode)->pNodeGraph;
}
MA_API ma_uint32 ma_node_get_input_bus_count(const ma_node* pNode)
{
if (pNode == NULL) {
return 0;
}
return ((ma_node_base*)pNode)->inputBusCount;
}
MA_API ma_uint32 ma_node_get_output_bus_count(const ma_node* pNode)
{
if (pNode == NULL) {
return 0;
}
return ((ma_node_base*)pNode)->outputBusCount;
}
MA_API ma_uint32 ma_node_get_input_channels(const ma_node* pNode, ma_uint32 inputBusIndex)
{
const ma_node_base* pNodeBase = (const ma_node_base*)pNode;
if (pNode == NULL) {
return 0;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}
/* Data source node. */
MA_API ma_data_source_node_config ma_data_source_node_config_init(ma_data_source* pDataSource)
{
ma_data_source_node_config config;
MA_ZERO_OBJECT(&config);
config.nodeConfig = ma_node_config_init();
config.pDataSource = pDataSource;
return config;
}
static void ma_data_source_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_data_source_node* pDataSourceNode = (ma_data_source_node*)pNode;
ma_format format;
ma_uint32 channels;
ma_uint32 frameCount;
ma_uint64 framesRead = 0;
MA_ASSERT(pDataSourceNode != NULL);
MA_ASSERT(pDataSourceNode->pDataSource != NULL);
MA_ASSERT(ma_node_get_input_bus_count(pDataSourceNode) == 0);
MA_ASSERT(ma_node_get_output_bus_count(pDataSourceNode) == 1);
/* We don't want to read from ppFramesIn at all. Instead we read from the data source. */
(void)ppFramesIn;
(void)pFrameCountIn;
frameCount = *pFrameCountOut;
/* miniaudio should never be calling this with a frame count of zero. */
MA_ASSERT(frameCount > 0);
if (ma_data_source_get_data_format(pDataSourceNode->pDataSource, &format, &channels, NULL, NULL, 0) == MA_SUCCESS) { /* <-- Don't care about sample rate here. */
/* The node graph system requires samples be in floating point format. This is checked in ma_data_source_node_init(). */
MA_ASSERT(format == ma_format_f32);
(void)format; /* Just to silence some static analysis tools. */
ma_data_source_read_pcm_frames(pDataSourceNode->pDataSource, ppFramesOut[0], frameCount, &framesRead);
}
*pFrameCountOut = (ma_uint32)framesRead;
}
static ma_node_vtable g_ma_data_source_node_vtable =
{
ma_data_source_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
0, /* 0 input buses. */
1, /* 1 output bus. */
0
};
MA_API ma_result ma_data_source_node_init(ma_node_graph* pNodeGraph, const ma_data_source_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source_node* pDataSourceNode)
{
ma_result result;
ma_format format; /* For validating the format, which must be ma_format_f32. */
ma_uint32 channels; /* For specifying the channel count of the output bus. */
ma_node_config baseConfig;
if (pDataSourceNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDataSourceNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
result = ma_data_source_get_data_format(pConfig->pDataSource, &format, &channels, NULL, NULL, 0); /* Don't care about sample rate. This will check pDataSource for NULL. */
if (result != MA_SUCCESS) {
return result;
}
MA_ASSERT(format == ma_format_f32); /* <-- If you've triggered this it means your data source is not outputting floating-point samples. You must configure your data source to use ma_format_f32. */
if (format != ma_format_f32) {
return MA_INVALID_ARGS; /* Invalid format. */
}
/* The channel count is defined by the data source. If the caller has manually changed the channels we just ignore it. */
baseConfig = pConfig->nodeConfig;
baseConfig.vtable = &g_ma_data_source_node_vtable; /* Explicitly set the vtable here to prevent callers from setting it incorrectly. */
/*
The channel count is defined by the data source. It is invalid for the caller to manually set
the channel counts in the config. `ma_data_source_node_config_init()` will have defaulted the
channel count pointer to NULL which is how it must remain. If you trigger any of these asserts
it means you're explicitly setting the channel count. Instead, configure the output channel
count of your data source to be the necessary channel count.
*/
if (baseConfig.pOutputChannels != NULL) {
return MA_INVALID_ARGS;
}
baseConfig.pOutputChannels = &channels;
result = ma_node_init(pNodeGraph, &baseConfig, pAllocationCallbacks, &pDataSourceNode->base);
if (result != MA_SUCCESS) {
return result;
}
pDataSourceNode->pDataSource = pConfig->pDataSource;
return MA_SUCCESS;
}
MA_API void ma_data_source_node_uninit(ma_data_source_node* pDataSourceNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_node_uninit(&pDataSourceNode->base, pAllocationCallbacks);
}
MA_API ma_result ma_data_source_node_set_looping(ma_data_source_node* pDataSourceNode, ma_bool32 isLooping)
{
if (pDataSourceNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_data_source_set_looping(pDataSourceNode->pDataSource, isLooping);
}
MA_API ma_bool32 ma_data_source_node_is_looping(ma_data_source_node* pDataSourceNode)
{
if (pDataSourceNode == NULL) {
return MA_FALSE;
}
return ma_data_source_is_looping(pDataSourceNode->pDataSource);
}
/* Splitter Node. */
MA_API ma_splitter_node_config ma_splitter_node_config_init(ma_uint32 channels)
{
ma_splitter_node_config config;
MA_ZERO_OBJECT(&config);
config.nodeConfig = ma_node_config_init();
config.channels = channels;
return config;
}
static void ma_splitter_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_node_base* pNodeBase = (ma_node_base*)pNode;
ma_uint32 iOutputBus;
ma_uint32 channels;
MA_ASSERT(pNodeBase != NULL);
MA_ASSERT(ma_node_get_input_bus_count(pNodeBase) == 1);
MA_ASSERT(ma_node_get_output_bus_count(pNodeBase) >= 2);
/* We don't need to consider the input frame count - it'll be the same as the output frame count and we process everything. */
(void)pFrameCountIn;
/* NOTE: This assumes the same number of channels for all inputs and outputs. This was checked in ma_splitter_node_init(). */
channels = ma_node_get_input_channels(pNodeBase, 0);
/* Splitting is just copying the first input bus and copying it over to each output bus. */
for (iOutputBus = 0; iOutputBus < ma_node_get_output_bus_count(pNodeBase); iOutputBus += 1) {
ma_copy_pcm_frames(ppFramesOut[iOutputBus], ppFramesIn[0], *pFrameCountOut, ma_format_f32, channels);
}
}
static ma_node_vtable g_ma_splitter_node_vtable =
{
ma_splitter_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* 1 input bus. */
2, /* 2 output buses. */
0
};
MA_API ma_result ma_splitter_node_init(ma_node_graph* pNodeGraph, const ma_splitter_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_splitter_node* pSplitterNode)
{
ma_result result;
ma_node_config baseConfig;
ma_uint32 pInputChannels[1];
ma_uint32 pOutputChannels[2];
if (pSplitterNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pSplitterNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
/* Splitters require the same number of channels between inputs and outputs. */
pInputChannels[0] = pConfig->channels;
pOutputChannels[0] = pConfig->channels;
pOutputChannels[1] = pConfig->channels;
baseConfig = pConfig->nodeConfig;
baseConfig.vtable = &g_ma_splitter_node_vtable;
baseConfig.pInputChannels = pInputChannels;
baseConfig.pOutputChannels = pOutputChannels;
result = ma_node_init(pNodeGraph, &baseConfig, pAllocationCallbacks, &pSplitterNode->base);
if (result != MA_SUCCESS) {
return result; /* Failed to initialize the base node. */
}
return MA_SUCCESS;
}
MA_API void ma_splitter_node_uninit(ma_splitter_node* pSplitterNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_node_uninit(pSplitterNode, pAllocationCallbacks);
}
/*
Biquad Node
*/
MA_API ma_biquad_node_config ma_biquad_node_config_init(ma_uint32 channels, float b0, float b1, float b2, float a0, float a1, float a2)
{
ma_biquad_node_config config;
config.nodeConfig = ma_node_config_init();
config.biquad = ma_biquad_config_init(ma_format_f32, channels, b0, b1, b2, a0, a1, a2);
return config;
}
static void ma_biquad_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_biquad_node* pLPFNode = (ma_biquad_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_biquad_process_pcm_frames(&pLPFNode->biquad, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_biquad_node_vtable =
{
ma_biquad_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_biquad_node_init(ma_node_graph* pNodeGraph, const ma_biquad_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_biquad_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->biquad.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_biquad_init(&pConfig->biquad, pAllocationCallbacks, &pNode->biquad);
if (result != MA_SUCCESS) {
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_biquad_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->biquad.channels;
baseNodeConfig.pOutputChannels = &pConfig->biquad.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_biquad_node_reinit(const ma_biquad_config* pConfig, ma_biquad_node* pNode)
{
ma_biquad_node* pLPFNode = (ma_biquad_node*)pNode;
MA_ASSERT(pNode != NULL);
return ma_biquad_reinit(pConfig, &pLPFNode->biquad);
}
MA_API void ma_biquad_node_uninit(ma_biquad_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_biquad_node* pLPFNode = (ma_biquad_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_biquad_uninit(&pLPFNode->biquad, pAllocationCallbacks);
}
/*
Low Pass Filter Node
*/
MA_API ma_lpf_node_config ma_lpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_lpf_node_config config;
config.nodeConfig = ma_node_config_init();
config.lpf = ma_lpf_config_init(ma_format_f32, channels, sampleRate, cutoffFrequency, order);
return config;
}
static void ma_lpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_lpf_node* pLPFNode = (ma_lpf_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_lpf_process_pcm_frames(&pLPFNode->lpf, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_lpf_node_vtable =
{
ma_lpf_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_lpf_node_init(ma_node_graph* pNodeGraph, const ma_lpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_lpf_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->lpf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_lpf_init(&pConfig->lpf, pAllocationCallbacks, &pNode->lpf);
if (result != MA_SUCCESS) {
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_lpf_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->lpf.channels;
baseNodeConfig.pOutputChannels = &pConfig->lpf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_lpf_node_reinit(const ma_lpf_config* pConfig, ma_lpf_node* pNode)
{
ma_lpf_node* pLPFNode = (ma_lpf_node*)pNode;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_lpf_reinit(pConfig, &pLPFNode->lpf);
}
MA_API void ma_lpf_node_uninit(ma_lpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_lpf_node* pLPFNode = (ma_lpf_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_lpf_uninit(&pLPFNode->lpf, pAllocationCallbacks);
}
/*
High Pass Filter Node
*/
MA_API ma_hpf_node_config ma_hpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_hpf_node_config config;
config.nodeConfig = ma_node_config_init();
config.hpf = ma_hpf_config_init(ma_format_f32, channels, sampleRate, cutoffFrequency, order);
return config;
}
static void ma_hpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_hpf_node* pHPFNode = (ma_hpf_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_hpf_process_pcm_frames(&pHPFNode->hpf, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_hpf_node_vtable =
{
ma_hpf_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_hpf_node_init(ma_node_graph* pNodeGraph, const ma_hpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hpf_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->hpf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_hpf_init(&pConfig->hpf, pAllocationCallbacks, &pNode->hpf);
if (result != MA_SUCCESS) {
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_hpf_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->hpf.channels;
baseNodeConfig.pOutputChannels = &pConfig->hpf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_hpf_node_reinit(const ma_hpf_config* pConfig, ma_hpf_node* pNode)
{
ma_hpf_node* pHPFNode = (ma_hpf_node*)pNode;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_hpf_reinit(pConfig, &pHPFNode->hpf);
}
MA_API void ma_hpf_node_uninit(ma_hpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_hpf_node* pHPFNode = (ma_hpf_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_hpf_uninit(&pHPFNode->hpf, pAllocationCallbacks);
}
/*
Band Pass Filter Node
*/
MA_API ma_bpf_node_config ma_bpf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double cutoffFrequency, ma_uint32 order)
{
ma_bpf_node_config config;
config.nodeConfig = ma_node_config_init();
config.bpf = ma_bpf_config_init(ma_format_f32, channels, sampleRate, cutoffFrequency, order);
return config;
}
static void ma_bpf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_bpf_node* pBPFNode = (ma_bpf_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_bpf_process_pcm_frames(&pBPFNode->bpf, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_bpf_node_vtable =
{
ma_bpf_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_bpf_node_init(ma_node_graph* pNodeGraph, const ma_bpf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_bpf_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->bpf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_bpf_init(&pConfig->bpf, pAllocationCallbacks, &pNode->bpf);
if (result != MA_SUCCESS) {
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_bpf_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->bpf.channels;
baseNodeConfig.pOutputChannels = &pConfig->bpf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_bpf_node_reinit(const ma_bpf_config* pConfig, ma_bpf_node* pNode)
{
ma_bpf_node* pBPFNode = (ma_bpf_node*)pNode;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_bpf_reinit(pConfig, &pBPFNode->bpf);
}
MA_API void ma_bpf_node_uninit(ma_bpf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_bpf_node* pBPFNode = (ma_bpf_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_bpf_uninit(&pBPFNode->bpf, pAllocationCallbacks);
}
/*
Notching Filter Node
*/
MA_API ma_notch_node_config ma_notch_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double q, double frequency)
{
ma_notch_node_config config;
config.nodeConfig = ma_node_config_init();
config.notch = ma_notch2_config_init(ma_format_f32, channels, sampleRate, q, frequency);
return config;
}
static void ma_notch_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_notch_node* pBPFNode = (ma_notch_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_notch2_process_pcm_frames(&pBPFNode->notch, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_notch_node_vtable =
{
ma_notch_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_notch_node_init(ma_node_graph* pNodeGraph, const ma_notch_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_notch_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->notch.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_notch2_init(&pConfig->notch, pAllocationCallbacks, &pNode->notch);
if (result != MA_SUCCESS) {
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_notch_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->notch.channels;
baseNodeConfig.pOutputChannels = &pConfig->notch.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_notch_node_reinit(const ma_notch_config* pConfig, ma_notch_node* pNode)
{
ma_notch_node* pNotchNode = (ma_notch_node*)pNode;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_notch2_reinit(pConfig, &pNotchNode->notch);
}
MA_API void ma_notch_node_uninit(ma_notch_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_notch_node* pNotchNode = (ma_notch_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_notch2_uninit(&pNotchNode->notch, pAllocationCallbacks);
}
/*
Peaking Filter Node
*/
MA_API ma_peak_node_config ma_peak_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
{
ma_peak_node_config config;
config.nodeConfig = ma_node_config_init();
config.peak = ma_peak2_config_init(ma_format_f32, channels, sampleRate, gainDB, q, frequency);
return config;
}
static void ma_peak_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_peak_node* pBPFNode = (ma_peak_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_peak2_process_pcm_frames(&pBPFNode->peak, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_peak_node_vtable =
{
ma_peak_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_peak_node_init(ma_node_graph* pNodeGraph, const ma_peak_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_peak_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->peak.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_peak2_init(&pConfig->peak, pAllocationCallbacks, &pNode->peak);
if (result != MA_SUCCESS) {
ma_node_uninit(pNode, pAllocationCallbacks);
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_peak_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->peak.channels;
baseNodeConfig.pOutputChannels = &pConfig->peak.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_peak_node_reinit(const ma_peak_config* pConfig, ma_peak_node* pNode)
{
ma_peak_node* pPeakNode = (ma_peak_node*)pNode;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_peak2_reinit(pConfig, &pPeakNode->peak);
}
MA_API void ma_peak_node_uninit(ma_peak_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_peak_node* pPeakNode = (ma_peak_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_peak2_uninit(&pPeakNode->peak, pAllocationCallbacks);
}
/*
Low Shelf Filter Node
*/
MA_API ma_loshelf_node_config ma_loshelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
{
ma_loshelf_node_config config;
config.nodeConfig = ma_node_config_init();
config.loshelf = ma_loshelf2_config_init(ma_format_f32, channels, sampleRate, gainDB, q, frequency);
return config;
}
static void ma_loshelf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_loshelf_node* pBPFNode = (ma_loshelf_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_loshelf2_process_pcm_frames(&pBPFNode->loshelf, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_loshelf_node_vtable =
{
ma_loshelf_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_loshelf_node_init(ma_node_graph* pNodeGraph, const ma_loshelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_loshelf_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->loshelf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_loshelf2_init(&pConfig->loshelf, pAllocationCallbacks, &pNode->loshelf);
if (result != MA_SUCCESS) {
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_loshelf_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->loshelf.channels;
baseNodeConfig.pOutputChannels = &pConfig->loshelf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_loshelf_node_reinit(const ma_loshelf_config* pConfig, ma_loshelf_node* pNode)
{
ma_loshelf_node* pLoshelfNode = (ma_loshelf_node*)pNode;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_loshelf2_reinit(pConfig, &pLoshelfNode->loshelf);
}
MA_API void ma_loshelf_node_uninit(ma_loshelf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_loshelf_node* pLoshelfNode = (ma_loshelf_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_loshelf2_uninit(&pLoshelfNode->loshelf, pAllocationCallbacks);
}
/*
High Shelf Filter Node
*/
MA_API ma_hishelf_node_config ma_hishelf_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, double gainDB, double q, double frequency)
{
ma_hishelf_node_config config;
config.nodeConfig = ma_node_config_init();
config.hishelf = ma_hishelf2_config_init(ma_format_f32, channels, sampleRate, gainDB, q, frequency);
return config;
}
static void ma_hishelf_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_hishelf_node* pBPFNode = (ma_hishelf_node*)pNode;
MA_ASSERT(pNode != NULL);
(void)pFrameCountIn;
ma_hishelf2_process_pcm_frames(&pBPFNode->hishelf, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_hishelf_node_vtable =
{
ma_hishelf_node_process_pcm_frames,
NULL, /* onGetRequiredInputFrameCount */
1, /* One input. */
1, /* One output. */
0 /* Default flags. */
};
MA_API ma_result ma_hishelf_node_init(ma_node_graph* pNodeGraph, const ma_hishelf_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_hishelf_node* pNode)
{
ma_result result;
ma_node_config baseNodeConfig;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pNode);
if (pConfig == NULL) {
return MA_INVALID_ARGS;
}
if (pConfig->hishelf.format != ma_format_f32) {
return MA_INVALID_ARGS; /* The format must be f32. */
}
result = ma_hishelf2_init(&pConfig->hishelf, pAllocationCallbacks, &pNode->hishelf);
if (result != MA_SUCCESS) {
return result;
}
baseNodeConfig = ma_node_config_init();
baseNodeConfig.vtable = &g_ma_hishelf_node_vtable;
baseNodeConfig.pInputChannels = &pConfig->hishelf.channels;
baseNodeConfig.pOutputChannels = &pConfig->hishelf.channels;
result = ma_node_init(pNodeGraph, &baseNodeConfig, pAllocationCallbacks, pNode);
if (result != MA_SUCCESS) {
return result;
}
return result;
}
MA_API ma_result ma_hishelf_node_reinit(const ma_hishelf_config* pConfig, ma_hishelf_node* pNode)
{
ma_hishelf_node* pHishelfNode = (ma_hishelf_node*)pNode;
if (pNode == NULL) {
return MA_INVALID_ARGS;
}
return ma_hishelf2_reinit(pConfig, &pHishelfNode->hishelf);
}
MA_API void ma_hishelf_node_uninit(ma_hishelf_node* pNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_hishelf_node* pHishelfNode = (ma_hishelf_node*)pNode;
if (pNode == NULL) {
return;
}
ma_node_uninit(pNode, pAllocationCallbacks);
ma_hishelf2_uninit(&pHishelfNode->hishelf, pAllocationCallbacks);
}
MA_API ma_delay_node_config ma_delay_node_config_init(ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 delayInFrames, float decay)
{
ma_delay_node_config config;
config.nodeConfig = ma_node_config_init();
config.delay = ma_delay_config_init(channels, sampleRate, delayInFrames, decay);
return config;
}
static void ma_delay_node_process_pcm_frames(ma_node* pNode, const float** ppFramesIn, ma_uint32* pFrameCountIn, float** ppFramesOut, ma_uint32* pFrameCountOut)
{
ma_delay_node* pDelayNode = (ma_delay_node*)pNode;
(void)pFrameCountIn;
ma_delay_process_pcm_frames(&pDelayNode->delay, ppFramesOut[0], ppFramesIn[0], *pFrameCountOut);
}
static ma_node_vtable g_ma_delay_node_vtable =
{
ma_delay_node_process_pcm_frames,
NULL,
1, /* 1 input channels. */
1, /* 1 output channel. */
MA_NODE_FLAG_CONTINUOUS_PROCESSING /* Delay requires continuous processing to ensure the tail get's processed. */
};
MA_API ma_result ma_delay_node_init(ma_node_graph* pNodeGraph, const ma_delay_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_delay_node* pDelayNode)
{
ma_result result;
ma_node_config baseConfig;
if (pDelayNode == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pDelayNode);
result = ma_delay_init(&pConfig->delay, pAllocationCallbacks, &pDelayNode->delay);
if (result != MA_SUCCESS) {
return result;
}
baseConfig = pConfig->nodeConfig;
baseConfig.vtable = &g_ma_delay_node_vtable;
baseConfig.pInputChannels = &pConfig->delay.channels;
baseConfig.pOutputChannels = &pConfig->delay.channels;
result = ma_node_init(pNodeGraph, &baseConfig, pAllocationCallbacks, &pDelayNode->baseNode);
if (result != MA_SUCCESS) {
ma_delay_uninit(&pDelayNode->delay, pAllocationCallbacks);
return result;
}
return result;
}
MA_API void ma_delay_node_uninit(ma_delay_node* pDelayNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pDelayNode == NULL) {
return;
}
/* The base node is always uninitialized first. */
ma_node_uninit(pDelayNode, pAllocationCallbacks);
ma_delay_uninit(&pDelayNode->delay, pAllocationCallbacks);
}
MA_API void ma_delay_node_set_wet(ma_delay_node* pDelayNode, float value)
{
if (pDelayNode == NULL) {
return;
}
ma_delay_set_wet(&pDelayNode->delay, value);
}
MA_API float ma_delay_node_get_wet(const ma_delay_node* pDelayNode)
{
if (pDelayNode == NULL) {
return 0;
}
return ma_delay_get_wet(&pDelayNode->delay);
}
MA_API void ma_delay_node_set_dry(ma_delay_node* pDelayNode, float value)
{
if (pDelayNode == NULL) {
return;
}
ma_delay_set_dry(&pDelayNode->delay, value);
}
MA_API float ma_delay_node_get_dry(const ma_delay_node* pDelayNode)
{
if (pDelayNode == NULL) {
return 0;
}
return ma_delay_get_dry(&pDelayNode->delay);
}
MA_API void ma_delay_node_set_decay(ma_delay_node* pDelayNode, float value)
{
if (pDelayNode == NULL) {
return;
}
ma_delay_set_decay(&pDelayNode->delay, value);
}
MA_API float ma_delay_node_get_decay(const ma_delay_node* pDelayNode)
{
if (pDelayNode == NULL) {
return 0;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
result = ma_node_init_preallocated(&pConfig->pEngine->nodeGraph, &baseNodeConfig, ma_offset_ptr(pHeap, heapLayout.baseNodeOffset), &pEngineNode->baseNode);
if (result != MA_SUCCESS) {
goto error0;
}
/*
We can now initialize the effects we need in order to implement the engine node. There's a
defined order of operations here, mainly centered around when we convert our channels from the
data source's native channel count to the engine's channel count. As a rule, we want to do as
much computation as possible before spatialization because there's a chance that will increase
the channel count, thereby increasing the amount of work needing to be done to process.
*/
/* We'll always do resampling first. */
resamplerConfig = ma_linear_resampler_config_init(ma_format_f32, baseNodeConfig.pInputChannels[0], pEngineNode->sampleRate, ma_engine_get_sample_rate(pEngineNode->pEngine));
resamplerConfig.lpfOrder = 0; /* <-- Need to disable low-pass filtering for pitch shifting for now because there's cases where the biquads are becoming unstable. Need to figure out a better fix for this. */
result = ma_linear_resampler_init_preallocated(&resamplerConfig, ma_offset_ptr(pHeap, heapLayout.resamplerOffset), &pEngineNode->resampler);
if (result != MA_SUCCESS) {
goto error1;
}
/* After resampling will come the fader. */
faderConfig = ma_fader_config_init(ma_format_f32, baseNodeConfig.pInputChannels[0], ma_engine_get_sample_rate(pEngineNode->pEngine));
result = ma_fader_init(&faderConfig, &pEngineNode->fader);
if (result != MA_SUCCESS) {
goto error2;
}
/*
Spatialization comes next. We spatialize based ont he node's output channel count. It's up the caller to
ensure channels counts link up correctly in the node graph.
*/
spatializerConfig = ma_engine_node_spatializer_config_init(&baseNodeConfig);
spatializerConfig.gainSmoothTimeInFrames = pEngineNode->pEngine->gainSmoothTimeInFrames;
result = ma_spatializer_init_preallocated(&spatializerConfig, ma_offset_ptr(pHeap, heapLayout.spatializerOffset), &pEngineNode->spatializer);
if (result != MA_SUCCESS) {
goto error2;
}
/*
After spatialization comes panning. We need to do this after spatialization because otherwise we wouldn't
be able to pan mono sounds.
*/
pannerConfig = ma_panner_config_init(ma_format_f32, baseNodeConfig.pOutputChannels[0]);
result = ma_panner_init(&pannerConfig, &pEngineNode->panner);
if (result != MA_SUCCESS) {
goto error3;
}
return MA_SUCCESS;
/* No need for allocation callbacks here because we use a preallocated heap. */
error3: ma_spatializer_uninit(&pEngineNode->spatializer, NULL);
error2: ma_linear_resampler_uninit(&pEngineNode->resampler, NULL);
error1: ma_node_uninit(&pEngineNode->baseNode, NULL);
error0: return result;
}
MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_engine_node* pEngineNode)
{
ma_result result;
size_t heapSizeInBytes;
void* pHeap;
result = ma_engine_node_get_heap_size(pConfig, &heapSizeInBytes);
if (result != MA_SUCCESS) {
return result;
}
if (heapSizeInBytes > 0) {
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
if (pHeap == NULL) {
return MA_OUT_OF_MEMORY;
}
} else {
pHeap = NULL;
}
result = ma_engine_node_init_preallocated(pConfig, pHeap, pEngineNode);
if (result != MA_SUCCESS) {
ma_free(pHeap, pAllocationCallbacks);
return result;
}
pEngineNode->_ownsHeap = MA_TRUE;
return MA_SUCCESS;
}
MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocation_callbacks* pAllocationCallbacks)
{
/*
The base node always needs to be uninitialized first to ensure it's detached from the graph completely before we
destroy anything that might be in the middle of being used by the processing function.
*/
ma_node_uninit(&pEngineNode->baseNode, pAllocationCallbacks);
/* Now that the node has been uninitialized we can safely uninitialize the rest. */
ma_spatializer_uninit(&pEngineNode->spatializer, pAllocationCallbacks);
ma_linear_resampler_uninit(&pEngineNode->resampler, pAllocationCallbacks);
/* Free the heap last. */
if (pEngineNode->_ownsHeap) {
ma_free(pEngineNode->_pHeap, pAllocationCallbacks);
}
}
MA_API ma_sound_config ma_sound_config_init(void)
{
ma_sound_config config;
MA_ZERO_OBJECT(&config);
config.rangeEndInPCMFrames = ~((ma_uint64)0);
config.loopPointEndInPCMFrames = ~((ma_uint64)0);
return config;
}
MA_API ma_sound_group_config ma_sound_group_config_init(void)
{
ma_sound_group_config config;
MA_ZERO_OBJECT(&config);
return config;
}
MA_API ma_engine_config ma_engine_config_init(void)
{
ma_engine_config config;
MA_ZERO_OBJECT(&config);
config.listenerCount = 1; /* Always want at least one listener. */
config.monoExpansionMode = ma_mono_expansion_mode_default;
return config;
}
#if !defined(MA_NO_DEVICE_IO)
static void ma_engine_data_callback_internal(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount)
{
ma_engine* pEngine = (ma_engine*)pDevice->pUserData;
(void)pFramesIn;
/*
Experiment: Try processing a resource manager job if we're on the Emscripten build.
This serves two purposes:
1) It ensures jobs are actually processed at some point since we cannot guarantee that the
caller is doing the right thing and calling ma_resource_manager_process_next_job(); and
2) It's an attempt at working around an issue where processing jobs on the Emscripten main
loop doesn't work as well as it should. When trying to load sounds without the `DECODE`
flag or with the `ASYNC` flag, the sound data is just not able to be loaded in time
before the callback is processed. I think it's got something to do with the single-
threaded nature of Web, but I'm not entirely sure.
*/
#if !defined(MA_NO_RESOURCE_MANAGER) && defined(MA_EMSCRIPTEN)
{
if (pEngine->pResourceManager != NULL) {
if ((pEngine->pResourceManager->config.flags & MA_RESOURCE_MANAGER_FLAG_NO_THREADING) != 0) {
ma_resource_manager_process_next_job(pEngine->pResourceManager);
}
}
}
#endif
ma_engine_read_pcm_frames(pEngine, pFramesOut, frameCount, NULL);
}
#endif
MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEngine)
{
ma_result result;
ma_node_graph_config nodeGraphConfig;
ma_engine_config engineConfig;
ma_spatializer_listener_config listenerConfig;
ma_uint32 iListener;
if (pEngine == NULL) {
return MA_INVALID_ARGS;
}
MA_ZERO_OBJECT(pEngine);
/* The config is allowed to be NULL in which case we use defaults for everything. */
if (pConfig != NULL) {
engineConfig = *pConfig;
} else {
engineConfig = ma_engine_config_init();
}
pEngine->monoExpansionMode = engineConfig.monoExpansionMode;
ma_allocation_callbacks_init_copy(&pEngine->allocationCallbacks, &engineConfig.allocationCallbacks);
#if !defined(MA_NO_RESOURCE_MANAGER)
{
pEngine->pResourceManager = engineConfig.pResourceManager;
}
#endif
#if !defined(MA_NO_DEVICE_IO)
{
pEngine->pDevice = engineConfig.pDevice;
/* If we don't have a device, we need one. */
if (pEngine->pDevice == NULL && engineConfig.noDevice == MA_FALSE) {
ma_device_config deviceConfig;
pEngine->pDevice = (ma_device*)ma_malloc(sizeof(*pEngine->pDevice), &pEngine->allocationCallbacks);
if (pEngine->pDevice == NULL) {
return MA_OUT_OF_MEMORY;
}
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.pDeviceID = engineConfig.pPlaybackDeviceID;
deviceConfig.playback.format = ma_format_f32;
deviceConfig.playback.channels = engineConfig.channels;
deviceConfig.sampleRate = engineConfig.sampleRate;
deviceConfig.dataCallback = ma_engine_data_callback_internal;
deviceConfig.pUserData = pEngine;
deviceConfig.periodSizeInFrames = engineConfig.periodSizeInFrames;
deviceConfig.periodSizeInMilliseconds = engineConfig.periodSizeInMilliseconds;
deviceConfig.noPreSilencedOutputBuffer = MA_TRUE; /* We'll always be outputting to every frame in the callback so there's no need for a pre-silenced buffer. */
deviceConfig.noClip = MA_TRUE; /* The engine will do clipping itself. */
if (engineConfig.pContext == NULL) {
ma_context_config contextConfig = ma_context_config_init();
contextConfig.allocationCallbacks = pEngine->allocationCallbacks;
contextConfig.pLog = engineConfig.pLog;
/* If the engine config does not specify a log, use the resource manager's if we have one. */
#ifndef MA_NO_RESOURCE_MANAGER
{
if (contextConfig.pLog == NULL && engineConfig.pResourceManager != NULL) {
contextConfig.pLog = ma_resource_manager_get_log(engineConfig.pResourceManager);
}
}
#endif
result = ma_device_init_ex(NULL, 0, &contextConfig, &deviceConfig, pEngine->pDevice);
} else {
result = ma_device_init(engineConfig.pContext, &deviceConfig, pEngine->pDevice);
}
if (result != MA_SUCCESS) {
ma_free(pEngine->pDevice, &pEngine->allocationCallbacks);
pEngine->pDevice = NULL;
return result;
}
pEngine->ownsDevice = MA_TRUE;
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
for (iListener = 0; iListener < engineConfig.listenerCount; iListener += 1) {
listenerConfig = ma_spatializer_listener_config_init(ma_node_graph_get_channels(&pEngine->nodeGraph));
/*
If we're using a device, use the device's channel map for the listener. Otherwise just use
miniaudio's default channel map.
*/
#if !defined(MA_NO_DEVICE_IO)
{
if (pEngine->pDevice != NULL) {
/*
Temporarily disabled. There is a subtle bug here where front-left and front-right
will be used by the device's channel map, but this is not what we want to use for
spatialization. Instead we want to use side-left and side-right. I need to figure
out a better solution for this. For now, disabling the user of device channel maps.
*/
/*listenerConfig.pChannelMapOut = pEngine->pDevice->playback.channelMap;*/
}
}
#endif
result = ma_spatializer_listener_init(&listenerConfig, &pEngine->allocationCallbacks, &pEngine->listeners[iListener]); /* TODO: Change this to a pre-allocated heap. */
if (result != MA_SUCCESS) {
goto on_error_2;
}
pEngine->listenerCount += 1;
}
/* Gain smoothing for spatialized sounds. */
pEngine->gainSmoothTimeInFrames = engineConfig.gainSmoothTimeInFrames;
if (pEngine->gainSmoothTimeInFrames == 0) {
ma_uint32 gainSmoothTimeInMilliseconds = engineConfig.gainSmoothTimeInMilliseconds;
if (gainSmoothTimeInMilliseconds == 0) {
gainSmoothTimeInMilliseconds = 8;
}
pEngine->gainSmoothTimeInFrames = (gainSmoothTimeInMilliseconds * ma_engine_get_sample_rate(pEngine)) / 1000; /* 8ms by default. */
}
/* We need a resource manager. */
#ifndef MA_NO_RESOURCE_MANAGER
{
if (pEngine->pResourceManager == NULL) {
ma_resource_manager_config resourceManagerConfig;
pEngine->pResourceManager = (ma_resource_manager*)ma_malloc(sizeof(*pEngine->pResourceManager), &pEngine->allocationCallbacks);
if (pEngine->pResourceManager == NULL) {
result = MA_OUT_OF_MEMORY;
goto on_error_2;
}
resourceManagerConfig = ma_resource_manager_config_init();
resourceManagerConfig.pLog = pEngine->pLog; /* Always use the engine's log for internally-managed resource managers. */
resourceManagerConfig.decodedFormat = ma_format_f32;
resourceManagerConfig.decodedChannels = 0; /* Leave the decoded channel count as 0 so we can get good spatialization. */
resourceManagerConfig.decodedSampleRate = ma_engine_get_sample_rate(pEngine);
ma_allocation_callbacks_init_copy(&resourceManagerConfig.allocationCallbacks, &pEngine->allocationCallbacks);
resourceManagerConfig.pVFS = engineConfig.pResourceManagerVFS;
/* The Emscripten build cannot use threads. */
#if defined(MA_EMSCRIPTEN)
{
resourceManagerConfig.jobThreadCount = 0;
resourceManagerConfig.flags |= MA_RESOURCE_MANAGER_FLAG_NO_THREADING;
}
#endif
result = ma_resource_manager_init(&resourceManagerConfig, pEngine->pResourceManager);
if (result != MA_SUCCESS) {
goto on_error_3;
}
pEngine->ownsResourceManager = MA_TRUE;
}
}
#endif
/* Setup some stuff for inlined sounds. That is sounds played with ma_engine_play_sound(). */
pEngine->inlinedSoundLock = 0;
pEngine->pInlinedSoundHead = NULL;
/* Start the engine if required. This should always be the last step. */
#if !defined(MA_NO_DEVICE_IO)
{
if (engineConfig.noAutoStart == MA_FALSE && pEngine->pDevice != NULL) {
result = ma_engine_start(pEngine);
if (result != MA_SUCCESS) {
goto on_error_4; /* Failed to start the engine. */
}
}
}
#endif
return MA_SUCCESS;
#if !defined(MA_NO_DEVICE_IO)
on_error_4:
#endif
#if !defined(MA_NO_RESOURCE_MANAGER)
on_error_3:
if (pEngine->ownsResourceManager) {
ma_free(pEngine->pResourceManager, &pEngine->allocationCallbacks);
}
#endif /* MA_NO_RESOURCE_MANAGER */
on_error_2:
for (iListener = 0; iListener < pEngine->listenerCount; iListener += 1) {
ma_spatializer_listener_uninit(&pEngine->listeners[iListener], &pEngine->allocationCallbacks);
}
ma_node_graph_uninit(&pEngine->nodeGraph, &pEngine->allocationCallbacks);
on_error_1:
#if !defined(MA_NO_DEVICE_IO)
{
if (pEngine->ownsDevice) {
ma_device_uninit(pEngine->pDevice);
ma_free(pEngine->pDevice, &pEngine->allocationCallbacks);
}
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#if 0
case 2:
{
drwav__bswap_samples_f16((drwav_float16*)pSamples, sampleCount);
} break;
#endif
case 4:
{
drwav__bswap_samples_f32((float*)pSamples, sampleCount);
} break;
case 8:
{
drwav__bswap_samples_f64((double*)pSamples, sampleCount);
} break;
default:
{
DRWAV_ASSERT(DRWAV_FALSE);
} break;
}
}
static DRWAV_INLINE void drwav__bswap_samples(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample, drwav_uint16 format)
{
switch (format)
{
case DR_WAVE_FORMAT_PCM:
{
drwav__bswap_samples_pcm(pSamples, sampleCount, bytesPerSample);
} break;
case DR_WAVE_FORMAT_IEEE_FLOAT:
{
drwav__bswap_samples_ieee(pSamples, sampleCount, bytesPerSample);
} break;
case DR_WAVE_FORMAT_ALAW:
case DR_WAVE_FORMAT_MULAW:
{
drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
} break;
case DR_WAVE_FORMAT_ADPCM:
case DR_WAVE_FORMAT_DVI_ADPCM:
default:
{
DRWAV_ASSERT(DRWAV_FALSE);
} break;
}
}
DRWAV_PRIVATE void* drwav__malloc_default(size_t sz, void* pUserData)
{
(void)pUserData;
return DRWAV_MALLOC(sz);
}
DRWAV_PRIVATE void* drwav__realloc_default(void* p, size_t sz, void* pUserData)
{
(void)pUserData;
return DRWAV_REALLOC(p, sz);
}
DRWAV_PRIVATE void drwav__free_default(void* p, void* pUserData)
{
(void)pUserData;
DRWAV_FREE(p);
}
DRWAV_PRIVATE void* drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onMalloc != NULL) {
return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
}
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
}
return NULL;
}
DRWAV_PRIVATE void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drwav_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
}
if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
void* p2;
p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
if (p2 == NULL) {
return NULL;
}
if (p != NULL) {
DRWAV_COPY_MEMORY(p2, p, szOld);
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
return p2;
}
return NULL;
}
DRWAV_PRIVATE void drwav__free_from_callbacks(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
{
if (p == NULL || pAllocationCallbacks == NULL) {
return;
}
if (pAllocationCallbacks->onFree != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
}
DRWAV_PRIVATE drwav_allocation_callbacks drwav_copy_allocation_callbacks_or_defaults(const drwav_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
return *pAllocationCallbacks;
} else {
drwav_allocation_callbacks allocationCallbacks;
allocationCallbacks.pUserData = NULL;
allocationCallbacks.onMalloc = drwav__malloc_default;
allocationCallbacks.onRealloc = drwav__realloc_default;
allocationCallbacks.onFree = drwav__free_default;
return allocationCallbacks;
}
}
static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 formatTag)
{
return
formatTag == DR_WAVE_FORMAT_ADPCM ||
formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
}
DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_riff(drwav_uint64 chunkSize)
{
return (unsigned int)(chunkSize % 2);
}
DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_w64(drwav_uint64 chunkSize)
{
return (unsigned int)(chunkSize % 8);
}
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
{
if (container == drwav_container_riff || container == drwav_container_rf64) {
drwav_uint8 sizeInBytes[4];
if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
return DRWAV_AT_END;
}
if (onRead(pUserData, sizeInBytes, 4) != 4) {
return DRWAV_INVALID_FILE;
}
pHeaderOut->sizeInBytes = drwav_bytes_to_u32(sizeInBytes);
pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
*pRunningBytesReadOut += 8;
} else {
drwav_uint8 sizeInBytes[8];
if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
return DRWAV_AT_END;
}
if (onRead(pUserData, sizeInBytes, 8) != 8) {
return DRWAV_INVALID_FILE;
}
pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24;
pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
*pRunningBytesReadOut += 24;
}
return DRWAV_SUCCESS;
}
DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
{
drwav_uint64 bytesRemainingToSeek = offset;
while (bytesRemainingToSeek > 0) {
if (bytesRemainingToSeek > 0x7FFFFFFF) {
if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
return DRWAV_FALSE;
}
bytesRemainingToSeek -= 0x7FFFFFFF;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#define DRWAV_SMPL_BYTES 36
#define DRWAV_SMPL_LOOP_BYTES 24
#define DRWAV_INST_BYTES 7
#define DRWAV_ACID_BYTES 24
#define DRWAV_CUE_BYTES 4
#define DRWAV_BEXT_BYTES 602
#define DRWAV_BEXT_DESCRIPTION_BYTES 256
#define DRWAV_BEXT_ORIGINATOR_NAME_BYTES 32
#define DRWAV_BEXT_ORIGINATOR_REF_BYTES 32
#define DRWAV_BEXT_RESERVED_BYTES 180
#define DRWAV_BEXT_UMID_BYTES 64
#define DRWAV_CUE_POINT_BYTES 24
#define DRWAV_LIST_LABEL_OR_NOTE_BYTES 4
#define DRWAV_LIST_LABELLED_TEXT_BYTES 20
#define DRWAV_METADATA_ALIGNMENT 8
typedef enum
{
drwav__metadata_parser_stage_count,
drwav__metadata_parser_stage_read
} drwav__metadata_parser_stage;
typedef struct
{
drwav_read_proc onRead;
drwav_seek_proc onSeek;
void *pReadSeekUserData;
drwav__metadata_parser_stage stage;
drwav_metadata *pMetadata;
drwav_uint32 metadataCount;
drwav_uint8 *pData;
drwav_uint8 *pDataCursor;
drwav_uint64 metadataCursor;
drwav_uint64 extraCapacity;
} drwav__metadata_parser;
DRWAV_PRIVATE size_t drwav__metadata_memory_capacity(drwav__metadata_parser* pParser)
{
drwav_uint64 cap = sizeof(drwav_metadata) * (drwav_uint64)pParser->metadataCount + pParser->extraCapacity;
if (cap > DRWAV_SIZE_MAX) {
return 0;
}
return (size_t)cap;
}
DRWAV_PRIVATE drwav_uint8* drwav__metadata_get_memory(drwav__metadata_parser* pParser, size_t size, size_t align)
{
drwav_uint8* pResult;
if (align) {
drwav_uintptr modulo = (drwav_uintptr)pParser->pDataCursor % align;
if (modulo != 0) {
pParser->pDataCursor += align - modulo;
}
}
pResult = pParser->pDataCursor;
DRWAV_ASSERT((pResult + size) <= (pParser->pData + drwav__metadata_memory_capacity(pParser)));
pParser->pDataCursor += size;
return pResult;
}
DRWAV_PRIVATE void drwav__metadata_request_extra_memory_for_stage_2(drwav__metadata_parser* pParser, size_t bytes, size_t align)
{
size_t extra = bytes + (align ? (align - 1) : 0);
pParser->extraCapacity += extra;
}
DRWAV_PRIVATE drwav_result drwav__metadata_alloc(drwav__metadata_parser* pParser, drwav_allocation_callbacks* pAllocationCallbacks)
{
if (pParser->extraCapacity != 0 || pParser->metadataCount != 0) {
pAllocationCallbacks->onFree(pParser->pData, pAllocationCallbacks->pUserData);
pParser->pData = (drwav_uint8*)pAllocationCallbacks->onMalloc(drwav__metadata_memory_capacity(pParser), pAllocationCallbacks->pUserData);
pParser->pDataCursor = pParser->pData;
if (pParser->pData == NULL) {
return DRWAV_OUT_OF_MEMORY;
}
pParser->pMetadata = (drwav_metadata*)drwav__metadata_get_memory(pParser, sizeof(drwav_metadata) * pParser->metadataCount, 1);
pParser->metadataCursor = 0;
}
return DRWAV_SUCCESS;
}
DRWAV_PRIVATE size_t drwav__metadata_parser_read(drwav__metadata_parser* pParser, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
{
if (pCursor != NULL) {
return drwav__on_read(pParser->onRead, pParser->pReadSeekUserData, pBufferOut, bytesToRead, pCursor);
} else {
return pParser->onRead(pParser->pReadSeekUserData, pBufferOut, bytesToRead);
}
}
DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata* pMetadata)
{
drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
drwav_uint64 totalBytesRead = 0;
size_t bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
DRWAV_ASSERT(pChunkHeader != NULL);
if (bytesJustRead == sizeof(smplHeaderData)) {
drwav_uint32 iSampleLoop;
pMetadata->type = drwav_metadata_type_smpl;
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
pMetadata->data.smpl.productId = drwav_bytes_to_u32(smplHeaderData + 4);
pMetadata->data.smpl.samplePeriodNanoseconds = drwav_bytes_to_u32(smplHeaderData + 8);
pMetadata->data.smpl.midiUnityNote = drwav_bytes_to_u32(smplHeaderData + 12);
pMetadata->data.smpl.midiPitchFraction = drwav_bytes_to_u32(smplHeaderData + 16);
pMetadata->data.smpl.smpteFormat = drwav_bytes_to_u32(smplHeaderData + 20);
pMetadata->data.smpl.smpteOffset = drwav_bytes_to_u32(smplHeaderData + 24);
pMetadata->data.smpl.sampleLoopCount = drwav_bytes_to_u32(smplHeaderData + 28);
pMetadata->data.smpl.samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(smplHeaderData + 32);
if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
if (bytesJustRead == sizeof(smplLoopData)) {
pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
} else {
break;
}
}
if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
pMetadata->data.smpl.pSamplerSpecificData = drwav__metadata_get_memory(pParser, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, 1);
DRWAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL);
drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_comment, "ICMT")) {
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_comment);
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_date, "ICRD")) {
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_date);
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_genre, "IGNR")) {
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_genre);
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_album, "IPRD")) {
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_album);
} else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber, "ITRK")) {
subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_tracknumber);
} else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
}
bytesRead += subchunkBytesRead;
DRWAV_ASSERT(subchunkBytesRead <= subchunkDataSize);
if (subchunkBytesRead < subchunkDataSize) {
drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, drwav_seek_origin_current)) {
break;
}
bytesRead += bytesToSeek;
}
if ((subchunkDataSize % 2) == 1) {
if (!pParser->onSeek(pParser->pReadSeekUserData, 1, drwav_seek_origin_current)) {
break;
}
bytesRead += 1;
}
}
} else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
bytesRead = drwav__metadata_process_unknown_chunk(pParser, pChunkID, pChunkHeader->sizeInBytes, drwav_metadata_location_top_level);
}
return bytesRead;
}
DRWAV_PRIVATE drwav_uint32 drwav_get_bytes_per_pcm_frame(drwav* pWav)
{
drwav_uint32 bytesPerFrame;
if ((pWav->bitsPerSample & 0x7) == 0) {
bytesPerFrame = (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
} else {
bytesPerFrame = pWav->fmt.blockAlign;
}
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW || pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
if (bytesPerFrame != pWav->fmt.channels) {
return 0;
}
}
return bytesPerFrame;
}
DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT)
{
if (pFMT == NULL) {
return 0;
}
if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
return pFMT->formatTag;
} else {
return drwav_bytes_to_u16(pFMT->subFormat);
}
}
DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
{
if (pWav == NULL || onRead == NULL || onSeek == NULL) {
return DRWAV_FALSE;
}
DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
pWav->onRead = onRead;
pWav->onSeek = onSeek;
pWav->pUserData = pReadSeekUserData;
pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
return DRWAV_FALSE;
}
return DRWAV_TRUE;
}
DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags)
{
drwav_uint64 cursor;
drwav_bool32 sequential;
drwav_uint8 riff[4];
drwav_fmt fmt;
unsigned short translatedFormatTag;
drwav_bool32 foundDataChunk;
drwav_uint64 dataChunkSize = 0;
drwav_uint64 sampleCountFromFactChunk = 0;
drwav_uint64 chunkSize;
drwav__metadata_parser metadataParser;
cursor = 0;
sequential = (flags & DRWAV_SEQUENTIAL) != 0;
if (drwav__on_read(pWav->onRead, pWav->pUserData, riff, sizeof(riff), &cursor) != sizeof(riff)) {
return DRWAV_FALSE;
}
if (drwav_fourcc_equal(riff, "RIFF")) {
pWav->container = drwav_container_riff;
} else if (drwav_fourcc_equal(riff, "riff")) {
int i;
drwav_uint8 riff2[12];
pWav->container = drwav_container_w64;
if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2, sizeof(riff2), &cursor) != sizeof(riff2)) {
return DRWAV_FALSE;
}
for (i = 0; i < 12; ++i) {
if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
return DRWAV_FALSE;
}
}
} else if (drwav_fourcc_equal(riff, "RF64")) {
pWav->container = drwav_container_rf64;
} else {
return DRWAV_FALSE;
}
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
drwav_uint8 chunkSizeBytes[4];
drwav_uint8 wave[4];
if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
return DRWAV_FALSE;
}
if (pWav->container == drwav_container_riff) {
if (drwav_bytes_to_u32(chunkSizeBytes) < 36) {
return DRWAV_FALSE;
}
} else {
if (drwav_bytes_to_u32(chunkSizeBytes) != 0xFFFFFFFF) {
return DRWAV_FALSE;
}
}
if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
return DRWAV_FALSE;
}
if (!drwav_fourcc_equal(wave, "WAVE")) {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
return DRWAV_FALSE;
}
cursor = pWav->dataChunkDataPos;
}
pWav->fmt = fmt;
pWav->sampleRate = fmt.sampleRate;
pWav->channels = fmt.channels;
pWav->bitsPerSample = fmt.bitsPerSample;
pWav->bytesRemaining = dataChunkSize;
pWav->translatedFormatTag = translatedFormatTag;
pWav->dataChunkDataSize = dataChunkSize;
if (sampleCountFromFactChunk != 0) {
pWav->totalPCMFrameCount = sampleCountFromFactChunk;
} else {
drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
if (bytesPerFrame == 0) {
return DRWAV_FALSE;
}
pWav->totalPCMFrameCount = dataChunkSize / bytesPerFrame;
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
drwav_uint64 totalBlockHeaderSizeInBytes;
drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
if ((blockCount * fmt.blockAlign) < dataChunkSize) {
blockCount += 1;
}
totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
}
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
drwav_uint64 totalBlockHeaderSizeInBytes;
drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
if ((blockCount * fmt.blockAlign) < dataChunkSize) {
blockCount += 1;
}
totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
pWav->totalPCMFrameCount += blockCount;
}
}
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
if (pWav->channels > 2) {
return DRWAV_FALSE;
}
}
if (drwav_get_bytes_per_pcm_frame(pWav) == 0) {
return DRWAV_FALSE;
}
#ifdef DR_WAV_LIBSNDFILE_COMPAT
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels;
}
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
}
#endif
return DRWAV_TRUE;
}
DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
{
return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
}
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)
{
if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
}
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)
{
if (!drwav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
pWav->allowedMetadataTypes = drwav_metadata_type_all_including_unknown;
return drwav_init__internal(pWav, NULL, NULL, flags);
}
DRWAV_API drwav_metadata* drwav_take_ownership_of_metadata(drwav* pWav)
{
drwav_metadata *result = pWav->pMetadata;
pWav->pMetadata = NULL;
pWav->metadataCount = 0;
return result;
}
DRWAV_PRIVATE size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
{
DRWAV_ASSERT(pWav != NULL);
DRWAV_ASSERT(pWav->onWrite != NULL);
return pWav->onWrite(pWav->pUserData, pData, dataSize);
}
DRWAV_PRIVATE size_t drwav__write_byte(drwav* pWav, drwav_uint8 byte)
{
DRWAV_ASSERT(pWav != NULL);
DRWAV_ASSERT(pWav->onWrite != NULL);
return pWav->onWrite(pWav->pUserData, &byte, 1);
}
DRWAV_PRIVATE size_t drwav__write_u16ne_to_le(drwav* pWav, drwav_uint16 value)
{
DRWAV_ASSERT(pWav != NULL);
DRWAV_ASSERT(pWav->onWrite != NULL);
if (!drwav__is_little_endian()) {
value = drwav__bswap16(value);
}
return drwav__write(pWav, &value, 2);
}
DRWAV_PRIVATE size_t drwav__write_u32ne_to_le(drwav* pWav, drwav_uint32 value)
{
DRWAV_ASSERT(pWav != NULL);
DRWAV_ASSERT(pWav->onWrite != NULL);
if (!drwav__is_little_endian()) {
value = drwav__bswap32(value);
}
return drwav__write(pWav, &value, 4);
}
DRWAV_PRIVATE size_t drwav__write_u64ne_to_le(drwav* pWav, drwav_uint64 value)
{
DRWAV_ASSERT(pWav != NULL);
DRWAV_ASSERT(pWav->onWrite != NULL);
if (!drwav__is_little_endian()) {
value = drwav__bswap64(value);
}
return drwav__write(pWav, &value, 8);
}
DRWAV_PRIVATE size_t drwav__write_f32ne_to_le(drwav* pWav, float value)
{
union {
drwav_uint32 u32;
float f32;
} u;
DRWAV_ASSERT(pWav != NULL);
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
bytesWritten += drwav__write_or_count_byte(pWav, '\0');
}
} break;
case drwav_metadata_type_unknown:
{
if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list) {
subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
}
} break;
default: break;
}
if ((subchunkSize % 2) != 0) {
bytesWritten += drwav__write_or_count_byte(pWav, 0);
}
}
}
DRWAV_ASSERT((bytesWritten % 2) == 0);
return bytesWritten;
}
DRWAV_PRIVATE drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
{
drwav_uint64 chunkSize = 4 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, pMetadata, metadataCount) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
if (chunkSize > 0xFFFFFFFFUL) {
chunkSize = 0xFFFFFFFFUL;
}
return (drwav_uint32)chunkSize;
}
DRWAV_PRIVATE drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
{
if (dataChunkSize <= 0xFFFFFFFFUL) {
return (drwav_uint32)dataChunkSize;
} else {
return 0xFFFFFFFFUL;
}
}
DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_w64(drwav_uint64 dataChunkSize)
{
drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize;
}
DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
{
return 24 + dataChunkSize;
}
DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize, drwav_metadata *metadata, drwav_uint32 numMetadata)
{
drwav_uint64 chunkSize = 4 + 36 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, metadata, numMetadata) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize);
if (chunkSize > 0xFFFFFFFFUL) {
chunkSize = 0xFFFFFFFFUL;
}
return chunkSize;
}
DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
{
return dataChunkSize;
}
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)
{
if (pWav == NULL || onWrite == NULL) {
return DRWAV_FALSE;
}
if (!isSequential && onSeek == NULL) {
return DRWAV_FALSE;
}
if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
return DRWAV_FALSE;
}
if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
return DRWAV_FALSE;
}
DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
pWav->onWrite = onWrite;
pWav->onSeek = onSeek;
pWav->pUserData = pUserData;
pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
return DRWAV_FALSE;
}
pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
pWav->fmt.channels = (drwav_uint16)pFormat->channels;
pWav->fmt.sampleRate = pFormat->sampleRate;
pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
pWav->fmt.extendedSize = 0;
pWav->isSequentialWrite = isSequential;
return DRWAV_TRUE;
}
DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
{
size_t runningPos = 0;
drwav_uint64 initialDataChunkSize = 0;
drwav_uint64 chunkSizeFMT;
if (pWav->isSequentialWrite) {
initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
if (pFormat->container == drwav_container_riff) {
if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
return DRWAV_FALSE;
}
}
}
pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
if (pFormat->container == drwav_container_riff) {
drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize;
runningPos += drwav__write(pWav, "RIFF", 4);
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
runningPos += drwav__write(pWav, "WAVE", 4);
} else if (pFormat->container == drwav_container_w64) {
drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize;
runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
} else if (pFormat->container == drwav_container_rf64) {
runningPos += drwav__write(pWav, "RF64", 4);
runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
runningPos += drwav__write(pWav, "WAVE", 4);
}
if (pFormat->container == drwav_container_rf64) {
drwav_uint32 initialds64ChunkSize = 28;
drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize;
runningPos += drwav__write(pWav, "ds64", 4);
runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize);
runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize);
runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize);
runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount);
runningPos += drwav__write_u32ne_to_le(pWav, 0);
}
if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
chunkSizeFMT = 16;
runningPos += drwav__write(pWav, "fmt ", 4);
runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
} else if (pFormat->container == drwav_container_w64) {
chunkSizeFMT = 40;
runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
}
runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.formatTag);
runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.channels);
runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.sampleRate);
runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.avgBytesPerSec);
runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.blockAlign);
runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.bitsPerSample);
if (!pWav->isSequentialWrite && pWav->pMetadata != NULL && pWav->metadataCount > 0 && (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64)) {
runningPos += drwav__write_or_count_metadata(pWav, pWav->pMetadata, pWav->metadataCount);
}
pWav->dataChunkDataPos = runningPos;
if (pFormat->container == drwav_container_riff) {
drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
runningPos += drwav__write(pWav, "data", 4);
runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
} else if (pFormat->container == drwav_container_w64) {
drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize;
runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
} else if (pFormat->container == drwav_container_rf64) {
runningPos += drwav__write(pWav, "data", 4);
runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF);
}
pWav->container = pFormat->container;
pWav->channels = (drwav_uint16)pFormat->channels;
pWav->sampleRate = pFormat->sampleRate;
pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
pWav->dataChunkDataPos = runningPos;
return DRWAV_TRUE;
}
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)
{
if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
return drwav_init_write__internal(pWav, pFormat, 0);
}
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)
{
if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
}
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)
{
if (pFormat == NULL) {
return DRWAV_FALSE;
}
return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
}
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,...
{
if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
pWav->pMetadata = pMetadata;
pWav->metadataCount = metadataCount;
return drwav_init_write__internal(pWav, pFormat, 0);
}
DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
{
drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalFrameCount * pFormat->channels * pFormat->bitsPerSample/8.0);
drwav_uint64 riffChunkSizeBytes;
drwav_uint64 fileSizeBytes = 0;
if (pFormat->container == drwav_container_riff) {
riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes, pMetadata, metadataCount);
fileSizeBytes = (8 + riffChunkSizeBytes);
} else if (pFormat->container == drwav_container_w64) {
riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
fileSizeBytes = riffChunkSizeBytes;
} else if (pFormat->container == drwav_container_rf64) {
riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes, pMetadata, metadataCount);
fileSizeBytes = (8 + riffChunkSizeBytes);
}
return fileSizeBytes;
}
#ifndef DR_WAV_NO_STDIO
#include <errno.h>
DRWAV_PRIVATE drwav_result drwav_result_from_errno(int e)
{
switch (e)
{
case 0: return DRWAV_SUCCESS;
#ifdef EPERM
case EPERM: return DRWAV_INVALID_OPERATION;
#endif
#ifdef ENOENT
case ENOENT: return DRWAV_DOES_NOT_EXIST;
#endif
#ifdef ESRCH
case ESRCH: return DRWAV_DOES_NOT_EXIST;
#endif
#ifdef EINTR
case EINTR: return DRWAV_INTERRUPT;
#endif
#ifdef EIO
case EIO: return DRWAV_IO_ERROR;
#endif
#ifdef ENXIO
case ENXIO: return DRWAV_DOES_NOT_EXIST;
#endif
#ifdef E2BIG
case E2BIG: return DRWAV_INVALID_ARGS;
#endif
#ifdef ENOEXEC
case ENOEXEC: return DRWAV_INVALID_FILE;
#endif
#ifdef EBADF
case EBADF: return DRWAV_INVALID_FILE;
#endif
#ifdef ECHILD
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#endif
#ifdef EKEYREJECTED
case EKEYREJECTED: return DRWAV_ERROR;
#endif
#ifdef EOWNERDEAD
case EOWNERDEAD: return DRWAV_ERROR;
#endif
#ifdef ENOTRECOVERABLE
case ENOTRECOVERABLE: return DRWAV_ERROR;
#endif
#ifdef ERFKILL
case ERFKILL: return DRWAV_ERROR;
#endif
#ifdef EHWPOISON
case EHWPOISON: return DRWAV_ERROR;
#endif
default: return DRWAV_ERROR;
}
}
DRWAV_PRIVATE drwav_result drwav_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err;
#endif
if (ppFile != NULL) {
*ppFile = NULL;
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRWAV_INVALID_ARGS;
}
#if defined(_MSC_VER) && _MSC_VER >= 1400
err = fopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drwav_result_from_errno(err);
}
#else
#if defined(_WIN32) || defined(__APPLE__)
*ppFile = fopen(pFilePath, pOpenMode);
#else
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
*ppFile = fopen64(pFilePath, pOpenMode);
#else
*ppFile = fopen(pFilePath, pOpenMode);
#endif
#endif
if (*ppFile == NULL) {
drwav_result result = drwav_result_from_errno(errno);
if (result == DRWAV_SUCCESS) {
result = DRWAV_ERROR;
}
return result;
}
#endif
return DRWAV_SUCCESS;
}
#if defined(_WIN32)
#if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
#define DRWAV_HAS_WFOPEN
#endif
#endif
DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
{
if (ppFile != NULL) {
*ppFile = NULL;
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRWAV_INVALID_ARGS;
}
#if defined(DRWAV_HAS_WFOPEN)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drwav_result_from_errno(err);
}
#else
*ppFile = _wfopen(pFilePath, pOpenMode);
if (*ppFile == NULL) {
return drwav_result_from_errno(errno);
}
#endif
(void)pAllocationCallbacks;
}
#else
{
mbstate_t mbs;
size_t lenMB;
const wchar_t* pFilePathTemp = pFilePath;
char* pFilePathMB = NULL;
char pOpenModeMB[32] = {0};
DRWAV_ZERO_OBJECT(&mbs);
lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
if (lenMB == (size_t)-1) {
return drwav_result_from_errno(errno);
}
pFilePathMB = (char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
if (pFilePathMB == NULL) {
return DRWAV_OUT_OF_MEMORY;
}
pFilePathTemp = pFilePath;
DRWAV_ZERO_OBJECT(&mbs);
wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
{
size_t i = 0;
for (;;) {
if (pOpenMode[i] == 0) {
pOpenModeMB[i] = '\0';
break;
}
pOpenModeMB[i] = (char)pOpenMode[i];
i += 1;
}
}
*ppFile = fopen(pFilePathMB, pOpenModeMB);
drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
}
if (*ppFile == NULL) {
return DRWAV_ERROR;
}
#endif
return DRWAV_SUCCESS;
}
DRWAV_PRIVATE size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
}
DRWAV_PRIVATE size_t drwav__on_write_stdio(void* pUserData, const void* pData, size_t bytesToWrite)
{
return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
}
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
{
return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
}
DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
{
return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
}
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)
{
drwav_bool32 result;
result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (result != DRWAV_TRUE) {
fclose(pFile);
return result;
}
pWav->allowedMetadataTypes = allowedMetadataTypes;
result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
if (result != DRWAV_TRUE) {
fclose(pFile);
return result;
}
return DRWAV_TRUE;
}
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)
{
FILE* pFile;
if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
return DRWAV_FALSE;
}
return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
}
DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
{
return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
}
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)
{
FILE* pFile;
if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
return DRWAV_FALSE;
}
return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, drwav_metadata_type_none, pAllocationCallbacks);
}
DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
{
FILE* pFile;
if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
return DRWAV_FALSE;
}
return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
}
DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
{
FILE* pFile;
if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
return DRWAV_FALSE;
}
return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags, drwav_metadata_type_all_including_unknown, pAllocationCallbacks);
}
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)
{
drwav_bool32 result;
result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (result != DRWAV_TRUE) {
fclose(pFile);
return result;
}
result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
if (result != DRWAV_TRUE) {
fclose(pFile);
return result;
}
return DRWAV_TRUE;
}
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)
{
FILE* pFile;
if (drwav_fopen(&pFile, filename, "wb") != DRWAV_SUCCESS) {
return DRWAV_FALSE;
}
return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
}
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)
{
FILE* pFile;
if (drwav_wfopen(&pFile, filename, L"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
return DRWAV_FALSE;
}
return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
}
DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
{
return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
}
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)
{
return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
}
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)
{
if (pFormat == NULL) {
return DRWAV_FALSE;
}
return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
}
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)
{
return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
}
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)
{
return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
}
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)
{
if (pFormat == NULL) {
return DRWAV_FALSE;
}
return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
}
#endif
DRWAV_PRIVATE size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
drwav* pWav = (drwav*)pUserData;
size_t bytesRemaining;
DRWAV_ASSERT(pWav != NULL);
DRWAV_ASSERT(pWav->memoryStream.dataSize >= pWav->memoryStream.currentReadPos);
bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
if (bytesToRead > bytesRemaining) {
bytesToRead = bytesRemaining;
}
if (bytesToRead > 0) {
DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
pWav->memoryStream.currentReadPos += bytesToRead;
}
return bytesToRead;
}
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
{
drwav* pWav = (drwav*)pUserData;
DRWAV_ASSERT(pWav != NULL);
if (origin == drwav_seek_origin_current) {
if (offset > 0) {
if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
return DRWAV_FALSE;
}
} else {
if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
return DRWAV_FALSE;
}
}
pWav->memoryStream.currentReadPos += offset;
} else {
if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
pWav->memoryStream.currentReadPos = offset;
} else {
return DRWAV_FALSE;
}
}
return DRWAV_TRUE;
}
DRWAV_PRIVATE size_t drwav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
{
drwav* pWav = (drwav*)pUserData;
size_t bytesRemaining;
DRWAV_ASSERT(pWav != NULL);
DRWAV_ASSERT(pWav->memoryStreamWrite.dataCapacity >= pWav->memoryStreamWrite.currentWritePos);
bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
if (bytesRemaining < bytesToWrite) {
void* pNewData;
size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
}
pNewData = drwav__realloc_from_callbacks(*pWav->memoryStreamWrite.ppData, newDataCapacity, pWav->memoryStreamWrite.dataCapacity, &pWav->allocationCallbacks);
if (pNewData == NULL) {
return 0;
}
*pWav->memoryStreamWrite.ppData = pNewData;
pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
}
DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
if (pWav->memoryStreamWrite.dataSize < pWav->memoryStreamWrite.currentWritePos) {
pWav->memoryStreamWrite.dataSize = pWav->memoryStreamWrite.currentWritePos;
}
*pWav->memoryStreamWrite.pDataSize = pWav->memoryStreamWrite.dataSize;
return bytesToWrite;
}
DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
{
drwav* pWav = (drwav*)pUserData;
DRWAV_ASSERT(pWav != NULL);
if (origin == drwav_seek_origin_current) {
if (offset > 0) {
if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);
}
} else {
if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
offset = -(int)pWav->memoryStreamWrite.currentWritePos;
}
}
pWav->memoryStreamWrite.currentWritePos += offset;
} else {
if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
pWav->memoryStreamWrite.currentWritePos = offset;
} else {
pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize;
}
}
return DRWAV_TRUE;
}
DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks)
{
return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
}
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)
{
if (data == NULL || dataSize == 0) {
return DRWAV_FALSE;
}
if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
pWav->memoryStream.data = (const drwav_uint8*)data;
pWav->memoryStream.dataSize = dataSize;
pWav->memoryStream.currentReadPos = 0;
return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
}
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)
{
if (data == NULL || dataSize == 0) {
return DRWAV_FALSE;
}
if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
pWav->memoryStream.data = (const drwav_uint8*)data;
pWav->memoryStream.dataSize = dataSize;
pWav->memoryStream.currentReadPos = 0;
pWav->allowedMetadataTypes = drwav_metadata_type_all_including_unknown;
return drwav_init__internal(pWav, NULL, NULL, flags);
}
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* pAllocationCallb...
{
if (ppData == NULL || pDataSize == NULL) {
return DRWAV_FALSE;
}
*ppData = NULL;
*pDataSize = 0;
if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
return DRWAV_FALSE;
}
pWav->memoryStreamWrite.ppData = ppData;
pWav->memoryStreamWrite.pDataSize = pDataSize;
pWav->memoryStreamWrite.dataSize = 0;
pWav->memoryStreamWrite.dataCapacity = 0;
pWav->memoryStreamWrite.currentWritePos = 0;
return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
}
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)
{
return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
}
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)
{
return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
}
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)
{
if (pFormat == NULL) {
return DRWAV_FALSE;
}
return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
}
DRWAV_API drwav_result drwav_uninit(drwav* pWav)
{
drwav_result result = DRWAV_SUCCESS;
if (pWav == NULL) {
return DRWAV_INVALID_ARGS;
}
if (pWav->onWrite != NULL) {
drwav_uint32 paddingSize = 0;
if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
} else {
paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
}
if (paddingSize > 0) {
drwav_uint64 paddingData = 0;
drwav__write(pWav, &paddingData, paddingSize);
}
if (pWav->onSeek && !pWav->isSequentialWrite) {
if (pWav->container == drwav_container_riff) {
if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
drwav__write_u32ne_to_le(pWav, riffChunkSize);
}
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
drwav__write_u32ne_to_le(pWav, dataChunkSize);
}
} else if (pWav->container == drwav_container_w64) {
if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
drwav__write_u64ne_to_le(pWav, riffChunkSize);
}
if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
drwav__write_u64ne_to_le(pWav, dataChunkSize);
}
} else if (pWav->container == drwav_container_rf64) {
int ds64BodyPos = 12 + 8;
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
drwav__write_u64ne_to_le(pWav, riffChunkSize);
}
if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
drwav__write_u64ne_to_le(pWav, dataChunkSize);
}
}
}
if (pWav->isSequentialWrite) {
if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
result = DRWAV_INVALID_FILE;
}
}
} else {
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
}
for (i = 0; i < sampleCount; ++i) {
unsigned int s0 = pIn[i*3 + 0];
unsigned int s1 = pIn[i*3 + 1];
unsigned int s2 = pIn[i*3 + 2];
drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
*pOut++ = sample32;
}
}
DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount)
{
size_t i;
if (pOut == NULL || pIn == NULL) {
return;
}
for (i = 0; i < sampleCount; ++i) {
*pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
}
}
DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount)
{
size_t i;
if (pOut == NULL || pIn == NULL) {
return;
}
for (i = 0; i < sampleCount; ++i) {
*pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
}
}
DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
{
size_t i;
if (pOut == NULL || pIn == NULL) {
return;
}
for (i = 0; i < sampleCount; ++i) {
*pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
}
}
DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
{
size_t i;
if (pOut == NULL || pIn == NULL) {
return;
}
for (i= 0; i < sampleCount; ++i) {
*pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
}
}
DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
{
drwav_uint64 sampleDataSize;
drwav_int16* pSampleData;
drwav_uint64 framesRead;
DRWAV_ASSERT(pWav != NULL);
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
if (sampleDataSize > DRWAV_SIZE_MAX) {
drwav_uninit(pWav);
return NULL;
}
pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
if (pSampleData == NULL) {
drwav_uninit(pWav);
return NULL;
}
framesRead = drwav_read_pcm_frames_s16(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
if (framesRead != pWav->totalPCMFrameCount) {
drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
drwav_uninit(pWav);
return NULL;
}
drwav_uninit(pWav);
if (sampleRate) {
*sampleRate = pWav->sampleRate;
}
if (channels) {
*channels = pWav->channels;
}
if (totalFrameCount) {
*totalFrameCount = pWav->totalPCMFrameCount;
}
return pSampleData;
}
DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
{
drwav_uint64 sampleDataSize;
float* pSampleData;
drwav_uint64 framesRead;
DRWAV_ASSERT(pWav != NULL);
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
if (sampleDataSize > DRWAV_SIZE_MAX) {
drwav_uninit(pWav);
return NULL;
}
pSampleData = (float*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
if (pSampleData == NULL) {
drwav_uninit(pWav);
return NULL;
}
framesRead = drwav_read_pcm_frames_f32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
if (framesRead != pWav->totalPCMFrameCount) {
drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
drwav_uninit(pWav);
return NULL;
}
drwav_uninit(pWav);
if (sampleRate) {
*sampleRate = pWav->sampleRate;
}
if (channels) {
*channels = pWav->channels;
}
if (totalFrameCount) {
*totalFrameCount = pWav->totalPCMFrameCount;
}
return pSampleData;
}
DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
{
drwav_uint64 sampleDataSize;
drwav_int32* pSampleData;
drwav_uint64 framesRead;
DRWAV_ASSERT(pWav != NULL);
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
if (sampleDataSize > DRWAV_SIZE_MAX) {
drwav_uninit(pWav);
return NULL;
}
pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks);
if (pSampleData == NULL) {
drwav_uninit(pWav);
return NULL;
}
framesRead = drwav_read_pcm_frames_s32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
if (framesRead != pWav->totalPCMFrameCount) {
drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
drwav_uninit(pWav);
return NULL;
}
drwav_uninit(pWav);
if (sampleRate) {
*sampleRate = pWav->sampleRate;
}
if (channels) {
*channels = pWav->channels;
}
if (totalFrameCount) {
*totalFrameCount = pWav->totalPCMFrameCount;
}
return pSampleData;
}
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* pAl...
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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* pAllocati...
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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* pAl...
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
#ifndef DR_WAV_NO_STDIO
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)
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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)
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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)
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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)
{
drwav wav;
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (channelsOut) {
*channelsOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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)
{
drwav wav;
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (channelsOut) {
*channelsOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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)
{
drwav wav;
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (channelsOut) {
*channelsOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
#endif
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)
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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)
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
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)
{
drwav wav;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
return NULL;
}
return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
#endif
DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
drwav__free_from_callbacks(p, pAllocationCallbacks);
} else {
drwav__free_default(p, NULL);
}
}
DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data)
{
return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
}
DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data)
{
return (drwav_int16)drwav_bytes_to_u16(data);
}
DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data)
{
return ((drwav_uint32)data[0] << 0) | ((drwav_uint32)data[1] << 8) | ((drwav_uint32)data[2] << 16) | ((drwav_uint32)data[3] << 24);
}
DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data)
{
union {
drwav_uint32 u32;
float f32;
} value;
value.u32 = drwav_bytes_to_u32(data);
return value.f32;
}
DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data)
{
return (drwav_int32)drwav_bytes_to_u32(data);
}
DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data)
{
return
((drwav_uint64)data[0] << 0) | ((drwav_uint64)data[1] << 8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
}
DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data)
{
return (drwav_int64)drwav_bytes_to_u64(data);
}
DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16])
{
int i;
for (i = 0; i < 16; i += 1) {
if (a[i] != b[i]) {
return DRWAV_FALSE;
}
}
return DRWAV_TRUE;
}
DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
{
return
a[0] == b[0] &&
a[1] == b[1] &&
a[2] == b[2] &&
a[3] == b[3];
}
#endif
/* dr_wav_c end */
#endif /* DRWAV_IMPLEMENTATION */
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
*blockType = (drflac_uint8)((blockHeader & 0x7F000000UL) >> 24);
*blockSize = (blockHeader & 0x00FFFFFFUL);
}
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)
{
drflac_uint32 blockHeader;
*blockSize = 0;
if (onRead(pUserData, &blockHeader, 4) != 4) {
return DRFLAC_FALSE;
}
drflac__decode_block_header(blockHeader, isLastBlock, blockType, blockSize);
return DRFLAC_TRUE;
}
static drflac_bool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drflac_streaminfo* pStreamInfo)
{
drflac_uint32 blockSizes;
drflac_uint64 frameSizes = 0;
drflac_uint64 importantProps;
drflac_uint8 md5[16];
if (onRead(pUserData, &blockSizes, 4) != 4) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, &frameSizes, 6) != 6) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, &importantProps, 8) != 8) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, md5, sizeof(md5)) != sizeof(md5)) {
return DRFLAC_FALSE;
}
blockSizes = drflac__be2host_32(blockSizes);
frameSizes = drflac__be2host_64(frameSizes);
importantProps = drflac__be2host_64(importantProps);
pStreamInfo->minBlockSizeInPCMFrames = (drflac_uint16)((blockSizes & 0xFFFF0000) >> 16);
pStreamInfo->maxBlockSizeInPCMFrames = (drflac_uint16) (blockSizes & 0x0000FFFF);
pStreamInfo->minFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 24)) >> 40);
pStreamInfo->maxFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 0)) >> 16);
pStreamInfo->sampleRate = (drflac_uint32)((importantProps & (((drflac_uint64)0x000FFFFF << 16) << 28)) >> 44);
pStreamInfo->channels = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000000E << 16) << 24)) >> 41) + 1;
pStreamInfo->bitsPerSample = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000001F << 16) << 20)) >> 36) + 1;
pStreamInfo->totalPCMFrameCount = ((importantProps & ((((drflac_uint64)0x0000000F << 16) << 16) | 0xFFFFFFFF)));
DRFLAC_COPY_MEMORY(pStreamInfo->md5, md5, sizeof(md5));
return DRFLAC_TRUE;
}
static void* drflac__malloc_default(size_t sz, void* pUserData)
{
(void)pUserData;
return DRFLAC_MALLOC(sz);
}
static void* drflac__realloc_default(void* p, size_t sz, void* pUserData)
{
(void)pUserData;
return DRFLAC_REALLOC(p, sz);
}
static void drflac__free_default(void* p, void* pUserData)
{
(void)pUserData;
DRFLAC_FREE(p);
}
static void* drflac__malloc_from_callbacks(size_t sz, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onMalloc != NULL) {
return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
}
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
}
return NULL;
}
static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
}
if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
void* p2;
p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
if (p2 == NULL) {
return NULL;
}
if (p != NULL) {
DRFLAC_COPY_MEMORY(p2, p, szOld);
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
return p2;
}
return NULL;
}
static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (p == NULL || pAllocationCallbacks == NULL) {
return;
}
if (pAllocationCallbacks->onFree != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
}
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* pSeektabl...
{
drflac_uint64 runningFilePos = 42;
drflac_uint64 seektablePos = 0;
drflac_uint32 seektableSize = 0;
for (;;) {
drflac_metadata metadata;
drflac_uint8 isLastBlock = 0;
drflac_uint8 blockType;
drflac_uint32 blockSize;
if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
return DRFLAC_FALSE;
}
runningFilePos += 4;
metadata.type = blockType;
metadata.pRawData = NULL;
metadata.rawDataSize = 0;
switch (blockType)
{
case DRFLAC_METADATA_BLOCK_TYPE_APPLICATION:
{
if (blockSize < 4) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
metadata.data.application.id = drflac__be2host_32(*(drflac_uint32*)pRawData);
metadata.data.application.pData = (const void*)((drflac_uint8*)pRawData + sizeof(drflac_uint32));
metadata.data.application.dataSize = blockSize - sizeof(drflac_uint32);
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE:
{
seektablePos = runningFilePos;
seektableSize = blockSize;
if (onMeta) {
drflac_uint32 iSeekpoint;
void* pRawData;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
metadata.data.seektable.seekpointCount = blockSize/sizeof(drflac_seekpoint);
metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
for (iSeekpoint = 0; iSeekpoint < metadata.data.seektable.seekpointCount; ++iSeekpoint) {
drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
pSeekpoint->firstPCMFrame = drflac__be2host_64(pSeekpoint->firstPCMFrame);
pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
pSeekpoint->pcmFrameCount = drflac__be2host_16(pSeekpoint->pcmFrameCount);
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT:
{
if (blockSize < 8) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
drflac_uint32 i;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
pRunningData = (const char*)pRawData;
pRunningDataEnd = (const char*)pRawData + blockSize;
metadata.data.vorbis_comment.vendorLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
if ((pRunningDataEnd - pRunningData) - 4 < (drflac_int64)metadata.data.vorbis_comment.vendorLength) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
metadata.data.vorbis_comment.commentCount = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
if ((pRunningDataEnd - pRunningData) / sizeof(drflac_uint32) < metadata.data.vorbis_comment.commentCount) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.vorbis_comment.pComments = pRunningData;
for (i = 0; i < metadata.data.vorbis_comment.commentCount; ++i) {
drflac_uint32 commentLength;
if (pRunningDataEnd - pRunningData < 4) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
commentLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
if (pRunningDataEnd - pRunningData < (drflac_int64)commentLength) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
pRunningData += commentLength;
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET:
{
if (blockSize < 396) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
drflac_uint8 iTrack;
drflac_uint8 iIndex;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
pRunningData = (const char*)pRawData;
pRunningDataEnd = (const char*)pRawData + blockSize;
DRFLAC_COPY_MEMORY(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128;
metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
metadata.data.cuesheet.isCD = (pRunningData[0] & 0x80) != 0; pRunningData += 259;
metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
metadata.data.cuesheet.pTrackData = pRunningData;
for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
drflac_uint8 indexCount;
drflac_uint32 indexPointSize;
if (pRunningDataEnd - pRunningData < 36) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
pRunningData += 35;
indexCount = pRunningData[0]; pRunningData += 1;
indexPointSize = indexCount * sizeof(drflac_cuesheet_track_index);
if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
for (iIndex = 0; iIndex < indexCount; ++iIndex) {
drflac_cuesheet_track_index* pTrack = (drflac_cuesheet_track_index*)pRunningData;
pRunningData += sizeof(drflac_cuesheet_track_index);
pTrack->offset = drflac__be2host_64(pTrack->offset);
}
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_PICTURE:
{
if (blockSize < 32) {
return DRFLAC_FALSE;
}
if (onMeta) {
void* pRawData;
const char* pRunningData;
const char* pRunningDataEnd;
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
pRunningData = (const char*)pRawData;
pRunningDataEnd = (const char*)pRawData + blockSize;
metadata.data.picture.type = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_PADDING:
{
if (onMeta) {
metadata.data.padding.unused = 0;
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
isLastBlock = DRFLAC_TRUE;
} else {
onMeta(pUserDataMD, &metadata);
}
}
} break;
case DRFLAC_METADATA_BLOCK_TYPE_INVALID:
{
if (onMeta) {
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
isLastBlock = DRFLAC_TRUE;
}
}
} break;
default:
{
if (onMeta) {
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
if (pRawData == NULL) {
return DRFLAC_FALSE;
}
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE;
}
metadata.pRawData = pRawData;
metadata.rawDataSize = blockSize;
onMeta(pUserDataMD, &metadata);
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
}
} break;
}
if (onMeta == NULL && blockSize > 0) {
if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
isLastBlock = DRFLAC_TRUE;
}
}
runningFilePos += blockSize;
if (isLastBlock) {
break;
}
}
*pSeektablePos = seektablePos;
*pSeektableSize = seektableSize;
*pFirstFramePos = runningFilePos;
return DRFLAC_TRUE;
}
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)
{
drflac_uint8 isLastBlock;
drflac_uint8 blockType;
drflac_uint32 blockSize;
(void)onSeek;
pInit->container = drflac_container_native;
if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
return DRFLAC_FALSE;
}
if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
if (!relaxed) {
return DRFLAC_FALSE;
} else {
pInit->hasStreamInfoBlock = DRFLAC_FALSE;
pInit->hasMetadataBlocks = DRFLAC_FALSE;
if (!drflac__read_next_flac_frame_header(&pInit->bs, 0, &pInit->firstFrameHeader)) {
return DRFLAC_FALSE;
}
if (pInit->firstFrameHeader.bitsPerSample == 0) {
return DRFLAC_FALSE;
}
pInit->sampleRate = pInit->firstFrameHeader.sampleRate;
pInit->channels = drflac__get_channel_count_from_channel_assignment(pInit->firstFrameHeader.channelAssignment);
pInit->bitsPerSample = pInit->firstFrameHeader.bitsPerSample;
pInit->maxBlockSizeInPCMFrames = 65535;
return DRFLAC_TRUE;
}
} else {
drflac_streaminfo streaminfo;
if (!drflac__read_streaminfo(onRead, pUserData, &streaminfo)) {
return DRFLAC_FALSE;
}
pInit->hasStreamInfoBlock = DRFLAC_TRUE;
pInit->sampleRate = streaminfo.sampleRate;
pInit->channels = streaminfo.channels;
pInit->bitsPerSample = streaminfo.bitsPerSample;
pInit->totalPCMFrameCount = streaminfo.totalPCMFrameCount;
pInit->maxBlockSizeInPCMFrames = streaminfo.maxBlockSizeInPCMFrames;
pInit->hasMetadataBlocks = !isLastBlock;
if (onMeta) {
drflac_metadata metadata;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
return DRFLAC_FALSE;
}
pInit->runningFilePos += 4;
if (id[0] == 'I' && id[1] == 'D' && id[2] == '3') {
drflac_uint8 header[6];
drflac_uint8 flags;
drflac_uint32 headerSize;
if (onRead(pUserData, header, 6) != 6) {
return DRFLAC_FALSE;
}
pInit->runningFilePos += 6;
flags = header[1];
DRFLAC_COPY_MEMORY(&headerSize, header+2, 4);
headerSize = drflac__unsynchsafe_32(drflac__be2host_32(headerSize));
if (flags & 0x10) {
headerSize += 10;
}
if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
return DRFLAC_FALSE;
}
pInit->runningFilePos += headerSize;
} else {
break;
}
}
if (id[0] == 'f' && id[1] == 'L' && id[2] == 'a' && id[3] == 'C') {
return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#ifndef DR_FLAC_NO_OGG
if (id[0] == 'O' && id[1] == 'g' && id[2] == 'g' && id[3] == 'S') {
return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#endif
if (relaxed) {
if (container == drflac_container_native) {
return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#ifndef DR_FLAC_NO_OGG
if (container == drflac_container_ogg) {
return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
}
#endif
}
return DRFLAC_FALSE;
}
static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
{
DRFLAC_ASSERT(pFlac != NULL);
DRFLAC_ASSERT(pInit != NULL);
DRFLAC_ZERO_MEMORY(pFlac, sizeof(*pFlac));
pFlac->bs = pInit->bs;
pFlac->onMeta = pInit->onMeta;
pFlac->pUserDataMD = pInit->pUserDataMD;
pFlac->maxBlockSizeInPCMFrames = pInit->maxBlockSizeInPCMFrames;
pFlac->sampleRate = pInit->sampleRate;
pFlac->channels = (drflac_uint8)pInit->channels;
pFlac->bitsPerSample = (drflac_uint8)pInit->bitsPerSample;
pFlac->totalPCMFrameCount = pInit->totalPCMFrameCount;
pFlac->container = pInit->container;
}
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)
{
drflac_init_info init;
drflac_uint32 allocationSize;
drflac_uint32 wholeSIMDVectorCountPerChannel;
drflac_uint32 decodedSamplesAllocationSize;
#ifndef DR_FLAC_NO_OGG
drflac_oggbs oggbs;
#endif
drflac_uint64 firstFramePos;
drflac_uint64 seektablePos;
drflac_uint32 seektableSize;
drflac_allocation_callbacks allocationCallbacks;
drflac* pFlac;
drflac__init_cpu_caps();
if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
return NULL;
}
if (pAllocationCallbacks != NULL) {
allocationCallbacks = *pAllocationCallbacks;
if (allocationCallbacks.onFree == NULL || (allocationCallbacks.onMalloc == NULL && allocationCallbacks.onRealloc == NULL)) {
return NULL;
}
} else {
allocationCallbacks.pUserData = NULL;
allocationCallbacks.onMalloc = drflac__malloc_default;
allocationCallbacks.onRealloc = drflac__realloc_default;
allocationCallbacks.onFree = drflac__free_default;
}
allocationSize = sizeof(drflac);
if ((init.maxBlockSizeInPCMFrames % (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) == 0) {
wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32)));
} else {
wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) + 1;
}
decodedSamplesAllocationSize = wholeSIMDVectorCountPerChannel * DRFLAC_MAX_SIMD_VECTOR_SIZE * init.channels;
allocationSize += decodedSamplesAllocationSize;
allocationSize += DRFLAC_MAX_SIMD_VECTOR_SIZE;
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg) {
allocationSize += sizeof(drflac_oggbs);
}
DRFLAC_ZERO_MEMORY(&oggbs, sizeof(oggbs));
if (init.container == drflac_container_ogg) {
oggbs.onRead = onRead;
oggbs.onSeek = onSeek;
oggbs.pUserData = pUserData;
oggbs.currentBytePos = init.oggFirstBytePos;
oggbs.firstBytePos = init.oggFirstBytePos;
oggbs.serialNumber = init.oggSerial;
oggbs.bosPageHeader = init.oggBosHeader;
oggbs.bytesRemainingInPage = 0;
}
#endif
firstFramePos = 42;
seektablePos = 0;
seektableSize = 0;
if (init.hasMetadataBlocks) {
drflac_read_proc onReadOverride = onRead;
drflac_seek_proc onSeekOverride = onSeek;
void* pUserDataOverride = pUserData;
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg) {
onReadOverride = drflac__on_read_ogg;
onSeekOverride = drflac__on_seek_ogg;
pUserDataOverride = (void*)&oggbs;
}
#endif
if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seektableSize, &allocationCallbacks)) {
return NULL;
}
allocationSize += seektableSize;
}
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
drflac__init_from_info(pFlac, &init);
pFlac->allocationCallbacks = allocationCallbacks;
pFlac->pDecodedSamples = (drflac_int32*)drflac_align((size_t)pFlac->pExtraData, DRFLAC_MAX_SIMD_VECTOR_SIZE);
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg) {
drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + seektableSize);
DRFLAC_COPY_MEMORY(pInternalOggbs, &oggbs, sizeof(oggbs));
pFlac->bs.onRead = drflac__on_read_ogg;
pFlac->bs.onSeek = drflac__on_seek_ogg;
pFlac->bs.pUserData = (void*)pInternalOggbs;
pFlac->_oggbs = (void*)pInternalOggbs;
}
#endif
pFlac->firstFLACFramePosInBytes = firstFramePos;
#ifndef DR_FLAC_NO_OGG
if (init.container == drflac_container_ogg)
{
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
}
else
#endif
{
if (seektablePos != 0) {
pFlac->seekpointCount = seektableSize / sizeof(*pFlac->pSeekpoints);
pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints, seektableSize) == seektableSize) {
drflac_uint32 iSeekpoint;
for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
pFlac->pSeekpoints[iSeekpoint].firstPCMFrame = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].firstPCMFrame);
pFlac->pSeekpoints[iSeekpoint].flacFrameOffset = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].flacFrameOffset);
pFlac->pSeekpoints[iSeekpoint].pcmFrameCount = drflac__be2host_16(pFlac->pSeekpoints[iSeekpoint].pcmFrameCount);
}
} else {
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
}
if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, drflac_seek_origin_start)) {
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
return NULL;
}
} else {
pFlac->pSeekpoints = NULL;
pFlac->seekpointCount = 0;
}
}
}
if (!init.hasStreamInfoBlock) {
pFlac->currentFLACFrame.header = init.firstFrameHeader;
for (;;) {
drflac_result result = drflac__decode_flac_frame(pFlac);
if (result == DRFLAC_SUCCESS) {
break;
} else {
if (result == DRFLAC_CRC_MISMATCH) {
if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
return NULL;
}
continue;
} else {
drflac__free_from_callbacks(pFlac, &allocationCallbacks);
return NULL;
}
}
}
}
return pFlac;
}
#ifndef DR_FLAC_NO_STDIO
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
static drflac_result drflac_result_from_errno(int e)
{
switch (e)
{
case 0: return DRFLAC_SUCCESS;
#ifdef EPERM
case EPERM: return DRFLAC_INVALID_OPERATION;
#endif
#ifdef ENOENT
case ENOENT: return DRFLAC_DOES_NOT_EXIST;
#endif
#ifdef ESRCH
case ESRCH: return DRFLAC_DOES_NOT_EXIST;
#endif
#ifdef EINTR
case EINTR: return DRFLAC_INTERRUPT;
#endif
#ifdef EIO
case EIO: return DRFLAC_IO_ERROR;
#endif
#ifdef ENXIO
case ENXIO: return DRFLAC_DOES_NOT_EXIST;
#endif
#ifdef E2BIG
case E2BIG: return DRFLAC_INVALID_ARGS;
#endif
#ifdef ENOEXEC
case ENOEXEC: return DRFLAC_INVALID_FILE;
#endif
#ifdef EBADF
case EBADF: return DRFLAC_INVALID_FILE;
#endif
#ifdef ECHILD
case ECHILD: return DRFLAC_ERROR;
#endif
#ifdef EAGAIN
case EAGAIN: return DRFLAC_UNAVAILABLE;
#endif
#ifdef ENOMEM
case ENOMEM: return DRFLAC_OUT_OF_MEMORY;
#endif
#ifdef EACCES
case EACCES: return DRFLAC_ACCESS_DENIED;
#endif
#ifdef EFAULT
case EFAULT: return DRFLAC_BAD_ADDRESS;
#endif
#ifdef ENOTBLK
case ENOTBLK: return DRFLAC_ERROR;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#endif
#ifdef EKEYREJECTED
case EKEYREJECTED: return DRFLAC_ERROR;
#endif
#ifdef EOWNERDEAD
case EOWNERDEAD: return DRFLAC_ERROR;
#endif
#ifdef ENOTRECOVERABLE
case ENOTRECOVERABLE: return DRFLAC_ERROR;
#endif
#ifdef ERFKILL
case ERFKILL: return DRFLAC_ERROR;
#endif
#ifdef EHWPOISON
case EHWPOISON: return DRFLAC_ERROR;
#endif
default: return DRFLAC_ERROR;
}
}
static drflac_result drflac_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err;
#endif
if (ppFile != NULL) {
*ppFile = NULL;
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRFLAC_INVALID_ARGS;
}
#if defined(_MSC_VER) && _MSC_VER >= 1400
err = fopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drflac_result_from_errno(err);
}
#else
#if defined(_WIN32) || defined(__APPLE__)
*ppFile = fopen(pFilePath, pOpenMode);
#else
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
*ppFile = fopen64(pFilePath, pOpenMode);
#else
*ppFile = fopen(pFilePath, pOpenMode);
#endif
#endif
if (*ppFile == NULL) {
drflac_result result = drflac_result_from_errno(errno);
if (result == DRFLAC_SUCCESS) {
result = DRFLAC_ERROR;
}
return result;
}
#endif
return DRFLAC_SUCCESS;
}
#if defined(_WIN32)
#if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
#define DRFLAC_HAS_WFOPEN
#endif
#endif
static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (ppFile != NULL) {
*ppFile = NULL;
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRFLAC_INVALID_ARGS;
}
#if defined(DRFLAC_HAS_WFOPEN)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drflac_result_from_errno(err);
}
#else
*ppFile = _wfopen(pFilePath, pOpenMode);
if (*ppFile == NULL) {
return drflac_result_from_errno(errno);
}
#endif
(void)pAllocationCallbacks;
}
#else
{
mbstate_t mbs;
size_t lenMB;
const wchar_t* pFilePathTemp = pFilePath;
char* pFilePathMB = NULL;
char pOpenModeMB[32] = {0};
DRFLAC_ZERO_OBJECT(&mbs);
lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
if (lenMB == (size_t)-1) {
return drflac_result_from_errno(errno);
}
pFilePathMB = (char*)drflac__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
if (pFilePathMB == NULL) {
return DRFLAC_OUT_OF_MEMORY;
}
pFilePathTemp = pFilePath;
DRFLAC_ZERO_OBJECT(&mbs);
wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
{
size_t i = 0;
for (;;) {
if (pOpenMode[i] == 0) {
pOpenModeMB[i] = '\0';
break;
}
pOpenModeMB[i] = (char)pOpenMode[i];
i += 1;
}
}
*ppFile = fopen(pFilePathMB, pOpenModeMB);
drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
}
if (*ppFile == NULL) {
return DRFLAC_ERROR;
}
#endif
return DRFLAC_SUCCESS;
}
static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
{
return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData);
}
static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
{
DRFLAC_ASSERT(offset >= 0);
return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
}
DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return NULL;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return NULL;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return pFlac;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac* pFlac;
FILE* pFile;
if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
return NULL;
}
pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return pFlac;
}
return pFlac;
}
#endif
static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead)
{
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
size_t bytesRemaining;
DRFLAC_ASSERT(memoryStream != NULL);
DRFLAC_ASSERT(memoryStream->dataSize >= memoryStream->currentReadPos);
bytesRemaining = memoryStream->dataSize - memoryStream->currentReadPos;
if (bytesToRead > bytesRemaining) {
bytesToRead = bytesRemaining;
}
if (bytesToRead > 0) {
DRFLAC_COPY_MEMORY(bufferOut, memoryStream->data + memoryStream->currentReadPos, bytesToRead);
memoryStream->currentReadPos += bytesToRead;
}
return bytesToRead;
}
static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
{
drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
DRFLAC_ASSERT(memoryStream != NULL);
DRFLAC_ASSERT(offset >= 0);
if (offset > (drflac_int64)memoryStream->dataSize) {
return DRFLAC_FALSE;
}
if (origin == drflac_seek_origin_current) {
if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
memoryStream->currentReadPos += offset;
} else {
return DRFLAC_FALSE;
}
} else {
if ((drflac_uint32)offset <= memoryStream->dataSize) {
memoryStream->currentReadPos = offset;
} else {
return DRFLAC_FALSE;
}
}
return DRFLAC_TRUE;
}
DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks)
{
drflac__memory_stream memoryStream;
drflac* pFlac;
memoryStream.data = (const drflac_uint8*)pData;
memoryStream.dataSize = dataSize;
memoryStream.currentReadPos = 0;
pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
pFlac->memoryStream = memoryStream;
#ifndef DR_FLAC_NO_OGG
if (pFlac->container == drflac_container_ogg)
{
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
oggbs->pUserData = &pFlac->memoryStream;
}
else
#endif
{
pFlac->bs.pUserData = &pFlac->memoryStream;
}
return pFlac;
}
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)
{
drflac__memory_stream memoryStream;
drflac* pFlac;
memoryStream.data = (const drflac_uint8*)pData;
memoryStream.dataSize = dataSize;
memoryStream.currentReadPos = 0;
pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
pFlac->memoryStream = memoryStream;
#ifndef DR_FLAC_NO_OGG
if (pFlac->container == drflac_container_ogg)
{
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
oggbs->pUserData = &pFlac->memoryStream;
}
else
#endif
{
pFlac->bs.pUserData = &pFlac->memoryStream;
}
return pFlac;
}
DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
}
DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
{
return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
}
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)
{
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
}
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)
{
return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
}
DRFLAC_API void drflac_close(drflac* pFlac)
{
if (pFlac == NULL) {
return;
}
#ifndef DR_FLAC_NO_STDIO
if (pFlac->bs.onRead == drflac__on_read_stdio) {
fclose((FILE*)pFlac->bs.pUserData);
}
#ifndef DR_FLAC_NO_OGG
if (pFlac->container == drflac_container_ogg) {
drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
DRFLAC_ASSERT(pFlac->bs.onRead == drflac__on_read_ogg);
if (oggbs->onRead == drflac__on_read_stdio) {
fclose((FILE*)oggbs->pUserData);
}
}
#endif
#endif
drflac__free_from_callbacks(pFlac, &pFlac->allocationCallbacks);
}
#if 0
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* pOutpu...
{
drflac_uint64 i;
for (i = 0; i < frameCount; ++i) {
drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
drflac_uint32 right = left - side;
pOutputSamples[i*2+0] = (drflac_int32)left;
pOutputSamples[i*2+1] = (drflac_int32)right;
}
}
#endif
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* pOutputSa...
{
drflac_uint64 i;
drflac_uint64 frameCount4 = frameCount >> 2;
const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
for (i = 0; i < frameCount4; ++i) {
drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
drflac_uint32 right0 = left0 - side0;
drflac_uint32 right1 = left1 - side1;
drflac_uint32 right2 = left2 - side2;
drflac_uint32 right3 = left3 - side3;
pOutputSamples[i*8+0] = (drflac_int32)left0;
pOutputSamples[i*8+1] = (drflac_int32)right0;
pOutputSamples[i*8+2] = (drflac_int32)left1;
pOutputSamples[i*8+3] = (drflac_int32)right1;
pOutputSamples[i*8+4] = (drflac_int32)left2;
pOutputSamples[i*8+5] = (drflac_int32)right2;
pOutputSamples[i*8+6] = (drflac_int32)left3;
pOutputSamples[i*8+7] = (drflac_int32)right3;
}
for (i = (frameCount4 << 2); i < frameCount; ++i) {
drflac_uint32 left = pInputSamples0U32[i] << shift0;
drflac_uint32 side = pInputSamples1U32[i] << shift1;
drflac_uint32 right = left - side;
pOutputSamples[i*2+0] = (drflac_int32)left;
pOutputSamples[i*2+1] = (drflac_int32)right;
}
}
#if defined(DRFLAC_SUPPORT_SSE2)
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* pOutputSamp...
{
drflac_uint64 i;
drflac_uint64 frameCount4 = frameCount >> 2;
const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
if (currentFLACFramePCMFramesConsumed > offsetAbs) {
pFlac->currentFLACFrame.pcmFramesRemaining += offsetAbs;
pFlac->currentPCMFrame = pcmFrameIndex;
return DRFLAC_TRUE;
}
}
#ifndef DR_FLAC_NO_OGG
if (pFlac->container == drflac_container_ogg)
{
wasSuccessful = drflac_ogg__seek_to_pcm_frame(pFlac, pcmFrameIndex);
}
else
#endif
{
if (!pFlac->_noSeekTableSeek) {
wasSuccessful = drflac__seek_to_pcm_frame__seek_table(pFlac, pcmFrameIndex);
}
#if !defined(DR_FLAC_NO_CRC)
if (!wasSuccessful && !pFlac->_noBinarySearchSeek && pFlac->totalPCMFrameCount > 0) {
wasSuccessful = drflac__seek_to_pcm_frame__binary_search(pFlac, pcmFrameIndex);
}
#endif
if (!wasSuccessful && !pFlac->_noBruteForceSeek) {
wasSuccessful = drflac__seek_to_pcm_frame__brute_force(pFlac, pcmFrameIndex);
}
}
if (wasSuccessful) {
pFlac->currentPCMFrame = pcmFrameIndex;
} else {
if (drflac_seek_to_pcm_frame(pFlac, originalPCMFrame) == DRFLAC_FALSE) {
drflac_seek_to_pcm_frame(pFlac, 0);
}
}
return wasSuccessful;
}
}
#if defined(SIZE_MAX)
#define DRFLAC_SIZE_MAX SIZE_MAX
#else
#if defined(DRFLAC_64BIT)
#define DRFLAC_SIZE_MAX ((drflac_uint64)0xFFFFFFFFFFFFFFFF)
#else
#define DRFLAC_SIZE_MAX 0xFFFFFFFF
#endif
#endif
#define DRFLAC_DEFINE_FULL_READ_AND_CLOSE(extension, type) \
static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut)\
{ \
type* pSampleData = NULL; \
drflac_uint64 totalPCMFrameCount; \
\
DRFLAC_ASSERT(pFlac != NULL); \
\
totalPCMFrameCount = pFlac->totalPCMFrameCount; \
\
if (totalPCMFrameCount == 0) { \
type buffer[4096]; \
drflac_uint64 pcmFramesRead; \
size_t sampleDataBufferSize = sizeof(buffer); \
\
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
if (pSampleData == NULL) { \
goto on_error; \
} \
\
while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
type* pNewSampleData; \
size_t newSampleDataBufferSize; \
\
newSampleDataBufferSize = sampleDataBufferSize * 2; \
pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
if (pNewSampleData == NULL) { \
drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
goto on_error; \
} \
\
sampleDataBufferSize = newSampleDataBufferSize; \
pSampleData = pNewSampleData; \
} \
\
DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
totalPCMFrameCount += pcmFramesRead; \
} \
\
\
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
} else { \
drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
if (dataSize > (drflac_uint64)DRFLAC_SIZE_MAX) { \
goto on_error; \
} \
\
pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); \
if (pSampleData == NULL) { \
goto on_error; \
} \
\
totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
} \
\
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
if (channelsOut) *channelsOut = pFlac->channels; \
if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
\
drflac_close(pFlac); \
return pSampleData; \
\
on_error: \
drflac_close(pFlac); \
return NULL; \
}
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s32, drflac_int32)
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s16, drflac_int16)
DRFLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float)
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_call...
{
drflac* pFlac;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
}
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_call...
{
drflac* pFlac;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
}
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* ...
{
drflac* pFlac;
if (channelsOut) {
*channelsOut = 0;
}
if (sampleRateOut) {
*sampleRateOut = 0;
}
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_f32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
}
#ifndef DR_FLAC_NO_STDIO
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)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_file(filename, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
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)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_file(filename, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
}
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)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_file(filename, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
#endif
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)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
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)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
}
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)
{
drflac* pFlac;
if (sampleRate) {
*sampleRate = 0;
}
if (channels) {
*channels = 0;
}
if (totalPCMFrameCount) {
*totalPCMFrameCount = 0;
}
pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
}
DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
drflac__free_from_callbacks(p, pAllocationCallbacks);
} else {
drflac__free_default(p, NULL);
}
}
DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments)
{
if (pIter == NULL) {
return;
}
pIter->countRemaining = commentCount;
pIter->pRunningData = (const char*)pComments;
}
DRFLAC_API const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut)
{
drflac_int32 length;
const char* pComment;
if (pCommentLengthOut) {
*pCommentLengthOut = 0;
}
if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
return NULL;
}
length = drflac__le2host_32_ptr_unaligned(pIter->pRunningData);
pIter->pRunningData += 4;
pComment = pIter->pRunningData;
pIter->pRunningData += length;
pIter->countRemaining -= 1;
if (pCommentLengthOut) {
*pCommentLengthOut = length;
}
return pComment;
}
DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData)
{
if (pIter == NULL) {
return;
}
pIter->countRemaining = trackCount;
pIter->pRunningData = (const char*)pTrackData;
}
DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack)
{
drflac_cuesheet_track cuesheetTrack;
const char* pRunningData;
drflac_uint64 offsetHi;
drflac_uint64 offsetLo;
if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
return DRFLAC_FALSE;
}
pRunningData = pIter->pRunningData;
offsetHi = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
offsetLo = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
cuesheetTrack.offset = offsetLo | (offsetHi << 32);
cuesheetTrack.trackNumber = pRunningData[0]; pRunningData += 1;
DRFLAC_COPY_MEMORY(cuesheetTrack.ISRC, pRunningData, sizeof(cuesheetTrack.ISRC)); pRunningData += 12;
cuesheetTrack.isAudio = (pRunningData[0] & 0x80) != 0;
cuesheetTrack.preEmphasis = (pRunningData[0] & 0x40) != 0; pRunningData += 14;
cuesheetTrack.indexCount = pRunningData[0]; pRunningData += 1;
cuesheetTrack.pIndexPoints = (const drflac_cuesheet_track_index*)pRunningData; pRunningData += cuesheetTrack.indexCount * sizeof(drflac_cuesheet_track_index);
pIter->pRunningData = pRunningData;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#if defined(SIZE_MAX)
#define DRMP3_SIZE_MAX SIZE_MAX
#else
#if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
#define DRMP3_SIZE_MAX ((drmp3_uint64)0xFFFFFFFFFFFFFFFF)
#else
#define DRMP3_SIZE_MAX 0xFFFFFFFF
#endif
#endif
#ifndef DRMP3_SEEK_LEADING_MP3_FRAMES
#define DRMP3_SEEK_LEADING_MP3_FRAMES 2
#endif
#define DRMP3_MIN_DATA_CHUNK_SIZE 16384
#ifndef DRMP3_DATA_CHUNK_SIZE
#define DRMP3_DATA_CHUNK_SIZE DRMP3_MIN_DATA_CHUNK_SIZE*4
#endif
#define DRMP3_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
#define DRMP3_CLAMP(x, lo, hi) (DRMP3_MAX(lo, DRMP3_MIN(x, hi)))
#ifndef DRMP3_PI_D
#define DRMP3_PI_D 3.14159265358979323846264
#endif
#define DRMP3_DEFAULT_RESAMPLER_LPF_ORDER 2
static DRMP3_INLINE float drmp3_mix_f32(float x, float y, float a)
{
return x*(1-a) + y*a;
}
static DRMP3_INLINE float drmp3_mix_f32_fast(float x, float y, float a)
{
float r0 = (y - x);
float r1 = r0*a;
return x + r1;
}
static DRMP3_INLINE drmp3_uint32 drmp3_gcf_u32(drmp3_uint32 a, drmp3_uint32 b)
{
for (;;) {
if (b == 0) {
break;
} else {
drmp3_uint32 t = a;
a = b;
b = t % a;
}
}
return a;
}
static void* drmp3__malloc_default(size_t sz, void* pUserData)
{
(void)pUserData;
return DRMP3_MALLOC(sz);
}
static void* drmp3__realloc_default(void* p, size_t sz, void* pUserData)
{
(void)pUserData;
return DRMP3_REALLOC(p, sz);
}
static void drmp3__free_default(void* p, void* pUserData)
{
(void)pUserData;
DRMP3_FREE(p);
}
static void* drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onMalloc != NULL) {
return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
}
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
}
return NULL;
}
static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks == NULL) {
return NULL;
}
if (pAllocationCallbacks->onRealloc != NULL) {
return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
}
if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
void* p2;
p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
if (p2 == NULL) {
return NULL;
}
if (p != NULL) {
DRMP3_COPY_MEMORY(p2, p, szOld);
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
return p2;
}
return NULL;
}
static void drmp3__free_from_callbacks(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (p == NULL || pAllocationCallbacks == NULL) {
return;
}
if (pAllocationCallbacks->onFree != NULL) {
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
}
static drmp3_allocation_callbacks drmp3_copy_allocation_callbacks_or_defaults(const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
return *pAllocationCallbacks;
} else {
drmp3_allocation_callbacks allocationCallbacks;
allocationCallbacks.pUserData = NULL;
allocationCallbacks.onMalloc = drmp3__malloc_default;
allocationCallbacks.onRealloc = drmp3__realloc_default;
allocationCallbacks.onFree = drmp3__free_default;
return allocationCallbacks;
}
}
static size_t drmp3__on_read(drmp3* pMP3, void* pBufferOut, size_t bytesToRead)
{
size_t bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead);
pMP3->streamCursor += bytesRead;
return bytesRead;
}
static drmp3_bool32 drmp3__on_seek(drmp3* pMP3, int offset, drmp3_seek_origin origin)
{
DRMP3_ASSERT(offset >= 0);
if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) {
return DRMP3_FALSE;
}
if (origin == drmp3_seek_origin_start) {
pMP3->streamCursor = (drmp3_uint64)offset;
} else {
pMP3->streamCursor += offset;
}
return DRMP3_TRUE;
}
static drmp3_bool32 drmp3__on_seek_64(drmp3* pMP3, drmp3_uint64 offset, drmp3_seek_origin origin)
{
if (offset <= 0x7FFFFFFF) {
return drmp3__on_seek(pMP3, (int)offset, origin);
}
if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_start)) {
return DRMP3_FALSE;
}
offset -= 0x7FFFFFFF;
while (offset > 0) {
if (offset <= 0x7FFFFFFF) {
if (!drmp3__on_seek(pMP3, (int)offset, drmp3_seek_origin_current)) {
return DRMP3_FALSE;
}
offset = 0;
} else {
if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_current)) {
return DRMP3_FALSE;
}
offset -= 0x7FFFFFFF;
}
}
return DRMP3_TRUE;
}
static drmp3_uint32 drmp3_decode_next_frame_ex__callbacks(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
{
drmp3_uint32 pcmFramesRead = 0;
DRMP3_ASSERT(pMP3 != NULL);
DRMP3_ASSERT(pMP3->onRead != NULL);
if (pMP3->atEnd) {
return 0;
}
for (;;) {
drmp3dec_frame_info info;
if (pMP3->dataSize < DRMP3_MIN_DATA_CHUNK_SIZE) {
size_t bytesRead;
if (pMP3->pData != NULL) {
DRMP3_MOVE_MEMORY(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
}
pMP3->dataConsumed = 0;
if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) {
drmp3_uint8* pNewData;
size_t newDataCap;
newDataCap = DRMP3_DATA_CHUNK_SIZE;
pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
if (pNewData == NULL) {
return 0;
}
pMP3->pData = pNewData;
pMP3->dataCapacity = newDataCap;
}
bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
if (bytesRead == 0) {
if (pMP3->dataSize == 0) {
pMP3->atEnd = DRMP3_TRUE;
return 0;
}
}
pMP3->dataSize += bytesRead;
}
if (pMP3->dataSize > INT_MAX) {
pMP3->atEnd = DRMP3_TRUE;
return 0;
}
DRMP3_ASSERT(pMP3->pData != NULL);
DRMP3_ASSERT(pMP3->dataCapacity > 0);
pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info);
if (info.frame_bytes > 0) {
pMP3->dataConsumed += (size_t)info.frame_bytes;
pMP3->dataSize -= (size_t)info.frame_bytes;
}
if (pcmFramesRead > 0) {
pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
pMP3->pcmFramesConsumedInMP3Frame = 0;
pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
pMP3->mp3FrameChannels = info.channels;
pMP3->mp3FrameSampleRate = info.hz;
break;
} else if (info.frame_bytes == 0) {
size_t bytesRead;
DRMP3_MOVE_MEMORY(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
pMP3->dataConsumed = 0;
if (pMP3->dataCapacity == pMP3->dataSize) {
drmp3_uint8* pNewData;
size_t newDataCap;
newDataCap = pMP3->dataCapacity + DRMP3_DATA_CHUNK_SIZE;
pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
if (pNewData == NULL) {
return 0;
}
pMP3->pData = pNewData;
pMP3->dataCapacity = newDataCap;
}
bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
if (bytesRead == 0) {
pMP3->atEnd = DRMP3_TRUE;
return 0;
}
pMP3->dataSize += bytesRead;
}
};
return pcmFramesRead;
}
static drmp3_uint32 drmp3_decode_next_frame_ex__memory(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
{
drmp3_uint32 pcmFramesRead = 0;
drmp3dec_frame_info info;
DRMP3_ASSERT(pMP3 != NULL);
DRMP3_ASSERT(pMP3->memory.pData != NULL);
if (pMP3->atEnd) {
return 0;
}
for (;;) {
pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->memory.pData + pMP3->memory.currentReadPos, (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos), pPCMFrames, &info);
if (pcmFramesRead > 0) {
pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
pMP3->pcmFramesConsumedInMP3Frame = 0;
pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
pMP3->mp3FrameChannels = info.channels;
pMP3->mp3FrameSampleRate = info.hz;
break;
} else if (info.frame_bytes > 0) {
pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
} else {
break;
}
}
pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
return pcmFramesRead;
}
static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
{
if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
return drmp3_decode_next_frame_ex__memory(pMP3, pPCMFrames);
} else {
return drmp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames);
}
}
static drmp3_uint32 drmp3_decode_next_frame(drmp3* pMP3)
{
DRMP3_ASSERT(pMP3 != NULL);
return drmp3_decode_next_frame_ex(pMP3, (drmp3d_sample_t*)pMP3->pcmFrames);
}
#if 0
static drmp3_uint32 drmp3_seek_next_frame(drmp3* pMP3)
{
drmp3_uint32 pcmFrameCount;
DRMP3_ASSERT(pMP3 != NULL);
pcmFrameCount = drmp3_decode_next_frame_ex(pMP3, NULL);
if (pcmFrameCount == 0) {
return 0;
}
pMP3->currentPCMFrame += pcmFrameCount;
pMP3->pcmFramesConsumedInMP3Frame = pcmFrameCount;
pMP3->pcmFramesRemainingInMP3Frame = 0;
return pcmFrameCount;
}
#endif
static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
DRMP3_ASSERT(pMP3 != NULL);
DRMP3_ASSERT(onRead != NULL);
drmp3dec_init(&pMP3->decoder);
pMP3->onRead = onRead;
pMP3->onSeek = onSeek;
pMP3->pUserData = pUserData;
pMP3->allocationCallbacks = drmp3_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
if (pMP3->allocationCallbacks.onFree == NULL || (pMP3->allocationCallbacks.onMalloc == NULL && pMP3->allocationCallbacks.onRealloc == NULL)) {
return DRMP3_FALSE;
}
if (drmp3_decode_next_frame(pMP3) == 0) {
drmp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks);
return DRMP3_FALSE;
}
pMP3->channels = pMP3->mp3FrameChannels;
pMP3->sampleRate = pMP3->mp3FrameSampleRate;
return DRMP3_TRUE;
}
DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pMP3 == NULL || onRead == NULL) {
return DRMP3_FALSE;
}
DRMP3_ZERO_OBJECT(pMP3);
return drmp3_init_internal(pMP3, onRead, onSeek, pUserData, pAllocationCallbacks);
}
static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
drmp3* pMP3 = (drmp3*)pUserData;
size_t bytesRemaining;
DRMP3_ASSERT(pMP3 != NULL);
DRMP3_ASSERT(pMP3->memory.dataSize >= pMP3->memory.currentReadPos);
bytesRemaining = pMP3->memory.dataSize - pMP3->memory.currentReadPos;
if (bytesToRead > bytesRemaining) {
bytesToRead = bytesRemaining;
}
if (bytesToRead > 0) {
DRMP3_COPY_MEMORY(pBufferOut, pMP3->memory.pData + pMP3->memory.currentReadPos, bytesToRead);
pMP3->memory.currentReadPos += bytesToRead;
}
return bytesToRead;
}
static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin)
{
drmp3* pMP3 = (drmp3*)pUserData;
DRMP3_ASSERT(pMP3 != NULL);
if (origin == drmp3_seek_origin_current) {
if (byteOffset > 0) {
if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) {
byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos);
}
} else {
if (pMP3->memory.currentReadPos < (size_t)-byteOffset) {
byteOffset = -(int)pMP3->memory.currentReadPos;
}
}
pMP3->memory.currentReadPos += byteOffset;
} else {
if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) {
pMP3->memory.currentReadPos = byteOffset;
} else {
pMP3->memory.currentReadPos = pMP3->memory.dataSize;
}
}
return DRMP3_TRUE;
}
DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pMP3 == NULL) {
return DRMP3_FALSE;
}
DRMP3_ZERO_OBJECT(pMP3);
if (pData == NULL || dataSize == 0) {
return DRMP3_FALSE;
}
pMP3->memory.pData = (const drmp3_uint8*)pData;
pMP3->memory.dataSize = dataSize;
pMP3->memory.currentReadPos = 0;
return drmp3_init_internal(pMP3, drmp3__on_read_memory, drmp3__on_seek_memory, pMP3, pAllocationCallbacks);
}
#ifndef DR_MP3_NO_STDIO
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
static drmp3_result drmp3_result_from_errno(int e)
{
switch (e)
{
case 0: return DRMP3_SUCCESS;
#ifdef EPERM
case EPERM: return DRMP3_INVALID_OPERATION;
#endif
#ifdef ENOENT
case ENOENT: return DRMP3_DOES_NOT_EXIST;
#endif
#ifdef ESRCH
case ESRCH: return DRMP3_DOES_NOT_EXIST;
#endif
#ifdef EINTR
case EINTR: return DRMP3_INTERRUPT;
#endif
#ifdef EIO
case EIO: return DRMP3_IO_ERROR;
#endif
#ifdef ENXIO
case ENXIO: return DRMP3_DOES_NOT_EXIST;
#endif
#ifdef E2BIG
case E2BIG: return DRMP3_INVALID_ARGS;
#endif
#ifdef ENOEXEC
case ENOEXEC: return DRMP3_INVALID_FILE;
#endif
#ifdef EBADF
case EBADF: return DRMP3_INVALID_FILE;
#endif
#ifdef ECHILD
case ECHILD: return DRMP3_ERROR;
#endif
#ifdef EAGAIN
case EAGAIN: return DRMP3_UNAVAILABLE;
#endif
#ifdef ENOMEM
case ENOMEM: return DRMP3_OUT_OF_MEMORY;
#endif
#ifdef EACCES
case EACCES: return DRMP3_ACCESS_DENIED;
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
#endif
#ifdef EKEYREJECTED
case EKEYREJECTED: return DRMP3_ERROR;
#endif
#ifdef EOWNERDEAD
case EOWNERDEAD: return DRMP3_ERROR;
#endif
#ifdef ENOTRECOVERABLE
case ENOTRECOVERABLE: return DRMP3_ERROR;
#endif
#ifdef ERFKILL
case ERFKILL: return DRMP3_ERROR;
#endif
#ifdef EHWPOISON
case EHWPOISON: return DRMP3_ERROR;
#endif
default: return DRMP3_ERROR;
}
}
static drmp3_result drmp3_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err;
#endif
if (ppFile != NULL) {
*ppFile = NULL;
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRMP3_INVALID_ARGS;
}
#if defined(_MSC_VER) && _MSC_VER >= 1400
err = fopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drmp3_result_from_errno(err);
}
#else
#if defined(_WIN32) || defined(__APPLE__)
*ppFile = fopen(pFilePath, pOpenMode);
#else
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
*ppFile = fopen64(pFilePath, pOpenMode);
#else
*ppFile = fopen(pFilePath, pOpenMode);
#endif
#endif
if (*ppFile == NULL) {
drmp3_result result = drmp3_result_from_errno(errno);
if (result == DRMP3_SUCCESS) {
result = DRMP3_ERROR;
}
return result;
}
#endif
return DRMP3_SUCCESS;
}
#if defined(_WIN32)
#if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
#define DRMP3_HAS_WFOPEN
#endif
#endif
static drmp3_result drmp3_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (ppFile != NULL) {
*ppFile = NULL;
}
if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
return DRMP3_INVALID_ARGS;
}
#if defined(DRMP3_HAS_WFOPEN)
{
#if defined(_MSC_VER) && _MSC_VER >= 1400
errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return drmp3_result_from_errno(err);
}
#else
*ppFile = _wfopen(pFilePath, pOpenMode);
if (*ppFile == NULL) {
return drmp3_result_from_errno(errno);
}
#endif
(void)pAllocationCallbacks;
}
#else
{
mbstate_t mbs;
size_t lenMB;
const wchar_t* pFilePathTemp = pFilePath;
char* pFilePathMB = NULL;
char pOpenModeMB[32] = {0};
DRMP3_ZERO_OBJECT(&mbs);
lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
if (lenMB == (size_t)-1) {
return drmp3_result_from_errno(errno);
}
pFilePathMB = (char*)drmp3__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
if (pFilePathMB == NULL) {
return DRMP3_OUT_OF_MEMORY;
}
pFilePathTemp = pFilePath;
DRMP3_ZERO_OBJECT(&mbs);
wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
{
size_t i = 0;
for (;;) {
if (pOpenMode[i] == 0) {
pOpenModeMB[i] = '\0';
break;
}
pOpenModeMB[i] = (char)pOpenMode[i];
i += 1;
}
}
*ppFile = fopen(pFilePathMB, pOpenModeMB);
drmp3__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
}
if (*ppFile == NULL) {
return DRMP3_ERROR;
}
#endif
return DRMP3_SUCCESS;
}
static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
}
static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin)
{
return fseek((FILE*)pUserData, offset, (origin == drmp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
}
DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
drmp3_bool32 result;
FILE* pFile;
if (drmp3_fopen(&pFile, pFilePath, "rb") != DRMP3_SUCCESS) {
return DRMP3_FALSE;
}
result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (result != DRMP3_TRUE) {
fclose(pFile);
return result;
}
return DRMP3_TRUE;
}
DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
drmp3_bool32 result;
FILE* pFile;
if (drmp3_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks) != DRMP3_SUCCESS) {
return DRMP3_FALSE;
}
result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
if (result != DRMP3_TRUE) {
fclose(pFile);
return result;
}
return DRMP3_TRUE;
}
#endif
DRMP3_API void drmp3_uninit(drmp3* pMP3)
{
if (pMP3 == NULL) {
return;
}
#ifndef DR_MP3_NO_STDIO
if (pMP3->onRead == drmp3__on_read_stdio) {
FILE* pFile = (FILE*)pMP3->pUserData;
if (pFile != NULL) {
fclose(pFile);
pMP3->pUserData = NULL;
}
}
#endif
drmp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks);
}
#if defined(DR_MP3_FLOAT_OUTPUT)
static void drmp3_f32_to_s16(drmp3_int16* dst, const float* src, drmp3_uint64 sampleCount)
{
drmp3_uint64 i;
drmp3_uint64 i4;
drmp3_uint64 sampleCount4;
i = 0;
sampleCount4 = sampleCount >> 2;
for (i4 = 0; i4 < sampleCount4; i4 += 1) {
float x0 = src[i+0];
float x1 = src[i+1];
float x2 = src[i+2];
float x3 = src[i+3];
x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
x0 = x0 * 32767.0f;
x1 = x1 * 32767.0f;
x2 = x2 * 32767.0f;
x3 = x3 * 32767.0f;
dst[i+0] = (drmp3_int16)x0;
dst[i+1] = (drmp3_int16)x1;
dst[i+2] = (drmp3_int16)x2;
dst[i+3] = (drmp3_int16)x3;
i += 4;
}
for (; i < sampleCount; i += 1) {
float x = src[i];
x = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
x = x * 32767.0f;
dst[i] = (drmp3_int16)x;
}
}
#endif
#if !defined(DR_MP3_FLOAT_OUTPUT)
static void drmp3_s16_to_f32(float* dst, const drmp3_int16* src, drmp3_uint64 sampleCount)
{
drmp3_uint64 i;
for (i = 0; i < sampleCount; i += 1) {
float x = (float)src[i];
x = x * 0.000030517578125f;
dst[i] = x;
}
}
#endif
static drmp3_uint64 drmp3_read_pcm_frames_raw(drmp3* pMP3, drmp3_uint64 framesToRead, void* pBufferOut)
{
drmp3_uint64 totalFramesRead = 0;
DRMP3_ASSERT(pMP3 != NULL);
DRMP3_ASSERT(pMP3->onRead != NULL);
while (framesToRead > 0) {
drmp3_uint32 framesToConsume = (drmp3_uint32)DRMP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead);
if (pBufferOut != NULL) {
#if defined(DR_MP3_FLOAT_OUTPUT)
float* pFramesOutF32 = (float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels);
float* pFramesInF32 = (float*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
DRMP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels);
#else
share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h view on Meta::CPAN
pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
break;
}
drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
}
}
}
if (!drmp3_seek_to_start_of_stream(pMP3)) {
return DRMP3_FALSE;
}
if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
return DRMP3_FALSE;
}
}
*pSeekPointCount = seekPointCount;
return DRMP3_TRUE;
}
DRMP3_API drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints)
{
if (pMP3 == NULL) {
return DRMP3_FALSE;
}
if (seekPointCount == 0 || pSeekPoints == NULL) {
pMP3->seekPointCount = 0;
pMP3->pSeekPoints = NULL;
} else {
pMP3->seekPointCount = seekPointCount;
pMP3->pSeekPoints = pSeekPoints;
}
return DRMP3_TRUE;
}
static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
{
drmp3_uint64 totalFramesRead = 0;
drmp3_uint64 framesCapacity = 0;
float* pFrames = NULL;
float temp[4096];
DRMP3_ASSERT(pMP3 != NULL);
for (;;) {
drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_f32(pMP3, framesToReadRightNow, temp);
if (framesJustRead == 0) {
break;
}
if (framesCapacity < totalFramesRead + framesJustRead) {
drmp3_uint64 oldFramesBufferSize;
drmp3_uint64 newFramesBufferSize;
drmp3_uint64 newFramesCap;
float* pNewFrames;
newFramesCap = framesCapacity * 2;
if (newFramesCap < totalFramesRead + framesJustRead) {
newFramesCap = totalFramesRead + framesJustRead;
}
oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(float);
newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(float);
if (newFramesBufferSize > (drmp3_uint64)DRMP3_SIZE_MAX) {
break;
}
pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
if (pNewFrames == NULL) {
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
break;
}
pFrames = pNewFrames;
framesCapacity = newFramesCap;
}
DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(float)));
totalFramesRead += framesJustRead;
if (framesJustRead != framesToReadRightNow) {
break;
}
}
if (pConfig != NULL) {
pConfig->channels = pMP3->channels;
pConfig->sampleRate = pMP3->sampleRate;
}
drmp3_uninit(pMP3);
if (pTotalFrameCount) {
*pTotalFrameCount = totalFramesRead;
}
return pFrames;
}
static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
{
drmp3_uint64 totalFramesRead = 0;
drmp3_uint64 framesCapacity = 0;
drmp3_int16* pFrames = NULL;
drmp3_int16 temp[4096];
DRMP3_ASSERT(pMP3 != NULL);
for (;;) {
drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_s16(pMP3, framesToReadRightNow, temp);
if (framesJustRead == 0) {
break;
}
if (framesCapacity < totalFramesRead + framesJustRead) {
drmp3_uint64 newFramesBufferSize;
drmp3_uint64 oldFramesBufferSize;
drmp3_uint64 newFramesCap;
drmp3_int16* pNewFrames;
newFramesCap = framesCapacity * 2;
if (newFramesCap < totalFramesRead + framesJustRead) {
newFramesCap = totalFramesRead + framesJustRead;
}
oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(drmp3_int16);
newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(drmp3_int16);
if (newFramesBufferSize > (drmp3_uint64)DRMP3_SIZE_MAX) {
break;
}
pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
if (pNewFrames == NULL) {
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
break;
}
pFrames = pNewFrames;
framesCapacity = newFramesCap;
}
DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(drmp3_int16)));
totalFramesRead += framesJustRead;
if (framesJustRead != framesToReadRightNow) {
break;
}
}
if (pConfig != NULL) {
pConfig->channels = pMP3->channels;
pConfig->sampleRate = pMP3->sampleRate;
}
drmp3_uninit(pMP3);
if (pTotalFrameCount) {
*pTotalFrameCount = totalFramesRead;
}
return pFrames;
}
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)
{
drmp3 mp3;
if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
return NULL;
}
return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
}
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)
{
drmp3 mp3;
if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
return NULL;
}
return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
}
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)
{
drmp3 mp3;
if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
return NULL;
}
return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
}
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)
{
drmp3 mp3;
if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
return NULL;
}
return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
}
#ifndef DR_MP3_NO_STDIO
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)
{
drmp3 mp3;
if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
return NULL;
}
return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
}
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)
{
drmp3 mp3;
if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
return NULL;
}
return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
}
#endif
DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
return drmp3__malloc_from_callbacks(sz, pAllocationCallbacks);
} else {
return drmp3__malloc_default(sz, NULL);
}
}
DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
{
if (pAllocationCallbacks != NULL) {
drmp3__free_from_callbacks(p, pAllocationCallbacks);
} else {
drmp3__free_default(p, NULL);
}
}
#endif
/* dr_mp3_c end */
#endif /* DRMP3_IMPLEMENTATION */
#endif /* MA_NO_MP3 */
/* End globally disabled warnings. */
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif /* miniaudio_c */
#endif /* MINIAUDIO_IMPLEMENTATION */
/*
This software is available as a choice of the following licenses. Choose
whichever you prefer.
===============================================================================
ALTERNATIVE 1 - Public Domain (www.unlicense.org)
===============================================================================
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
===============================================================================
ALTERNATIVE 2 - MIT No Attribution
===============================================================================
Copyright 2020 David Reid
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so.