App-MHFS

 view release on metacpan or  search on metacpan

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN


    ```c
    ma_result result;
    ma_uint64 framesRead;

    result = ma_data_source_read_pcm_frames(pDataSource, pFramesOut, frameCount, &framesRead, loop);
    if (result != MA_SUCCESS) {
        return result;  // Failed to read data from the data source.
    }
    ```

If you don't need the number of frames that were successfully read you can pass in `NULL` to the
`pFramesRead` parameter. If this returns a value less than the number of frames requested it means
the end of the file has been reached. `MA_AT_END` will be returned only when the number of frames
read is 0.

When calling any data source function, with the exception of `ma_data_source_init()` and
`ma_data_source_uninit()`, you can pass in any object that implements a data source. For example,
you could plug in a decoder like so:

    ```c
    ma_result result;
    ma_uint64 framesRead;
    ma_decoder decoder;   // <-- This would be initialized with `ma_decoder_init_*()`.

    result = ma_data_source_read_pcm_frames(&decoder, pFramesOut, frameCount, &framesRead, loop);
    if (result != MA_SUCCESS) {
        return result;  // Failed to read data from the decoder.
    }
    ```

If you want to seek forward you can pass in `NULL` to the `pFramesOut` parameter. Alternatively you
can use `ma_data_source_seek_pcm_frames()`.

To seek to a specific PCM frame:

    ```c
    result = ma_data_source_seek_to_pcm_frame(pDataSource, frameIndex);
    if (result != MA_SUCCESS) {
        return result;  // Failed to seek to PCM frame.
    }
    ```

You can retrieve the total length of a data source in PCM frames, but note that some data sources
may not have the notion of a length, such as noise and waveforms, and others may just not have a
way of determining the length such as some decoders. To retrieve the length:

    ```c
    ma_uint64 length;

    result = ma_data_source_get_length_in_pcm_frames(pDataSource, &length);
    if (result != MA_SUCCESS) {
        return result;  // Failed to retrieve the length.
    }
    ```

Care should be taken when retrieving the length of a data source where the underlying decoder is
pulling data from a data stream with an undefined length, such as internet radio or some kind of
broadcast. If you do this, `ma_data_source_get_length_in_pcm_frames()` may never return.

The current position of the cursor in PCM frames can also be retrieved:

    ```c
    ma_uint64 cursor;

    result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &cursor);
    if (result != MA_SUCCESS) {
        return result;  // Failed to retrieve the cursor.
    }
    ```

You will often need to know the data format that will be returned after reading. This can be
retrieved like so:

    ```c
    ma_format format;
    ma_uint32 channels;
    ma_uint32 sampleRate;
    ma_channel channelMap[MA_MAX_CHANNELS];
    
    result = ma_data_source_get_data_format(pDataSource, &format, &channels, &sampleRate, channelMap, MA_MAX_CHANNELS);
    if (result != MA_SUCCESS) {
        return result;  // Failed to retrieve data format.
    }
    ```

If you do not need a specific data format property, just pass in NULL to the respective parameter.

There may be cases where you want to implement something like a sound bank where you only want to
read data within a certain range of the underlying data. To do this you can use a range:

    ```c
    result = ma_data_source_set_range_in_pcm_frames(pDataSource, rangeBegInFrames, rangeEndInFrames);
    if (result != MA_SUCCESS) {
        return result;  // Failed to set the range.
    }
    ```

This is useful if you have a sound bank where many sounds are stored in the same file and you want
the data source to only play one of those sub-sounds.

Custom loop points can also be used with data sources. By default, data sources will loop after
they reach the end of the data source, but if you need to loop at a specific location, you can do
the following:

    ```c
    result = ma_data_set_loop_point_in_pcm_frames(pDataSource, loopBegInFrames, loopEndInFrames);
    if (result != MA_SUCCESS) {
        return result;  // Failed to set the loop point.
    }
    ```

The loop point is relative to the current range.

It's sometimes useful to chain data sources together so that a seamless transition can be achieved.
To do this, you can use chaining:

    ```c
    ma_decoder decoder1;
    ma_decoder decoder2;

    // ... initialize decoders with ma_decoder_init_*() ...

    result = ma_data_source_set_next(&decoder1, &decoder2);
    if (result != MA_SUCCESS) {
        return result;  // Failed to set the next data source.
    }

    result = ma_data_source_read_pcm_frames(&decoder1, pFramesOut, frameCount, pFramesRead, MA_FALSE);
    if (result != MA_SUCCESS) {
        return result;  // Failed to read from the decoder.
    }
    ```

In the example above we're using decoders. When reading from a chain, you always want to read from
the top level data source in the chain. In the example above, `decoder1` is the top level data 
source in the chain. When `decoder1` reaches the end, `decoder2` will start seamlessly without any
gaps.

Note that the `loop` parameter is set to false in the example above. When this is set to true, only
the current data source will be looped. You can loop the entire chain by linking in a loop like so:

    ```c
    ma_data_source_set_next(&decoder1, &decoder2);  // decoder1 -> decoder2
    ma_data_source_set_next(&decoder2, &decoder1);  // decoder2 -> decoder1 (loop back to the start).
    ```

Note that setting up chaining is not thread safe, so care needs to be taken if you're dynamically
changing links while the audio thread is in the middle of reading.

Do not use `ma_decoder_seek_to_pcm_frame()` as a means to reuse a data source to play multiple
instances of the same sound simultaneously. Instead, initialize multiple data sources for each
instance. This can be extremely inefficient depending on the data source and can result in
glitching due to subtle changes to the state of internal filters.


4.1. Custom Data Sources
------------------------
You can implement a custom data source by implementing the functions in `ma_data_source_vtable`.
Your custom object must have `ma_data_source_base` as it's first member:

    ```c
    struct my_data_source
    {
        ma_data_source_base base;
        ...
    };
    ```

In your initialization routine, you need to call `ma_data_source_init()` in order to set up the
base object (`ma_data_source_base`):

    ```c
    static ma_result my_data_source_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
    {
        // Read data here. Output in the same format returned by my_data_source_get_data_format().
    }

    static ma_result my_data_source_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
    {
        // Seek to a specific PCM frame here. Return MA_NOT_IMPLEMENTED if seeking is not supported.
    }

    static ma_result my_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
    {
        // Return the format of the data here.
    }

    static ma_result my_data_source_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
    {
        // Retrieve the current position of the cursor here. Return MA_NOT_IMPLEMENTED and set *pCursor to 0 if there is no notion of a cursor.
    }

    static ma_result my_data_source_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
    {
        // Retrieve the length in PCM frames here. Return MA_NOT_IMPLEMENTED and set *pLength to 0 if there is no notion of a length or if the length is unknown.
    }

    static g_my_data_source_vtable =
    {
        my_data_source_read,
        my_data_source_seek,
        my_data_source_get_data_format,
        my_data_source_get_cursor,
        my_data_source_get_length
    };

    ma_result my_data_source_init(my_data_source* pMyDataSource)
    {
        ma_result result;
        ma_data_source_config baseConfig;

        baseConfig = ma_data_source_config_init();
        baseConfig.vtable = &g_my_data_source_vtable;

        result = ma_data_source_init(&baseConfig, &pMyDataSource->base);
        if (result != MA_SUCCESS) {
            return result;
        }

        // ... do the initialization of your custom data source here ...

        return MA_SUCCESS;
    }

    void my_data_source_uninit(my_data_source* pMyDataSource)
    {
        // ... do the uninitialization of your custom data source here ...
        
        // You must uninitialize the base data source.
        ma_data_source_uninit(&pMyDataSource->base);
    }
    ```

Note that `ma_data_source_init()` and `ma_data_source_uninit()` are never called directly outside
of the custom data source. It's up to the custom data source itself to call these within their own
init/uninit functions.



5. Engine
=========
The `ma_engine` API is a high level API for managing and mixing sounds and effect processing. The
`ma_engine` object encapsulates a resource manager and a node graph, both of which will be
explained in more detail later.

Sounds are called `ma_sound` and are created from an engine. Sounds can be associated with a mixing
group called `ma_sound_group` which are also created from the engine. Both `ma_sound` and
`ma_sound_group` objects are nodes within the engine's node graph.

When the engine is initialized, it will normally create a device internally. If you would rather
manage the device yourself, you can do so and just pass a pointer to it via the engine config when
you initialize the engine. You can also just use the engine without a device, which again can be
configured via the engine config.

The most basic way to initialize the engine is with a default config, like so:

    ```c
    ma_result result;
    ma_engine engine;

    result = ma_engine_init(NULL, &engine);
    if (result != MA_SUCCESS) {
        return result;  // Failed to initialize the engine.

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    ```c
    ma_sound_set_min_distance(&sound, minDistance);
    ma_sound_set_max_distance(&sound, maxDistance);
    ```

The engine's spatialization system supports doppler effect. The doppler factor can be configure on
a per-sound basis like so:

    ```c
    ma_sound_set_doppler_factor(&sound, dopplerFactor);
    ```

You can fade sounds in and out with `ma_sound_set_fade_in_pcm_frames()` and
`ma_sound_set_fade_in_milliseconds()`. Set the volume to -1 to use the current volume as the
starting volume:

    ```c
    // Fade in over 1 second.
    ma_sound_set_fade_in_milliseconds(&sound, 0, 1, 1000);

    // ... sometime later ...

    // Fade out over 1 second, starting from the current volume.
    ma_sound_set_fade_in_milliseconds(&sound, -1, 0, 1000);
    ```

By default sounds will start immediately, but sometimes for timing and synchronization purposes it
can be useful to schedule a sound to start or stop:

    ```c
    // Start the sound in 1 second from now.
    ma_sound_set_start_time_in_pcm_frames(&sound, ma_engine_get_time(&engine) + (ma_engine_get_sample_rate(&engine) * 1));

    // Stop the sound in 2 seconds from now.
    ma_sound_set_stop_time_in_pcm_frames(&sound, ma_engine_get_time(&engine) + (ma_engine_get_sample_rate(&engine) * 2));
    ```

Note that scheduling a start time still requires an explicit call to `ma_sound_start()` before
anything will play.

The time is specified in global time which is controlled by the engine. You can get the engine's
current time with `ma_engine_get_time()`. The engine's global time is incremented automatically as
audio data is read, but it can be reset with `ma_engine_set_time()` in case it needs to be
resynchronized for some reason.

To determine whether or not a sound is currently playing, use `ma_sound_is_playing()`. This will
take the scheduled start and stop times into account.

Whether or not a sound should loop can be controlled with `ma_sound_set_looping()`. Sounds will not
be looping by default. Use `ma_sound_is_looping()` to determine whether or not a sound is looping.

Use `ma_sound_at_end()` to determine whether or not a sound is currently at the end. For a looping
sound this should never return true.

Internally a sound wraps around a data source. Some APIs exist to control the underlying data
source, mainly for convenience:

    ```c
    ma_sound_seek_to_pcm_frame(&sound, frameIndex);
    ma_sound_get_data_format(&sound, &format, &channels, &sampleRate, pChannelMap, channelMapCapacity);
    ma_sound_get_cursor_in_pcm_frames(&sound, &cursor);
    ma_sound_get_length_in_pcm_frames(&sound, &length);
    ```

Sound groups have the same API as sounds, only they are called `ma_sound_group`, and since they do
not have any notion of a data source, anything relating to a data source is unavailable.

Internally, sound data is loaded via the `ma_decoder` API which means by default in only supports
file formats that have built-in support in miniaudio. You can extend this to support any kind of
file format through the use of custom decoders. To do this you'll need to use a self-managed
resource manager and configure it appropriately. See the "Resource Management" section below for
details on how to set this up.


6. Resource Management
======================
Many programs will want to manage sound resources for things such as reference counting and
streaming. This is supported by miniaudio via the `ma_resource_manager` API.

The resource manager is mainly responsible for the following:

  * Loading of sound files into memory with reference counting.
  * Streaming of sound data

When loading a sound file, the resource manager will give you back a `ma_data_source` compatible
object called `ma_resource_manager_data_source`. This object can be passed into any
`ma_data_source` API which is how you can read and seek audio data. When loading a sound file, you
specify whether or not you want the sound to be fully loaded into memory (and optionally
pre-decoded) or streamed. When loading into memory, you can also specify whether or not you want
the data to be loaded asynchronously.

The example below is how you can initialize a resource manager using it's default configuration:

    ```c
    ma_resource_manager_config config;
    ma_resource_manager resourceManager;

    config = ma_resource_manager_config_init();
    result = ma_resource_manager_init(&config, &resourceManager);
    if (result != MA_SUCCESS) {
        ma_device_uninit(&device);
        printf("Failed to initialize the resource manager.");
        return -1;
    }
    ```

You can configure the format, channels and sample rate of the decoded audio data. By default it
will use the file's native data format, but you can configure it to use a consistent format. This
is useful for offloading the cost of data conversion to load time rather than dynamically
converting at mixing time. To do this, you configure the decoded format, channels and sample rate
like the code below:

    ```c
    config = ma_resource_manager_config_init();
    config.decodedFormat     = device.playback.format;
    config.decodedChannels   = device.playback.channels;
    config.decodedSampleRate = device.sampleRate;
    ```

In the code above, the resource manager will be configured so that any decoded audio data will be
pre-converted at load time to the device's native data format. If instead you used defaults and

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

13. Audio Buffers
=================
miniaudio supports reading from a buffer of raw audio data via the `ma_audio_buffer` API. This can
read from memory that's managed by the application, but can also handle the memory management for
you internally. Memory management is flexible and should support most use cases.

Audio buffers are initialised using the standard configuration system used everywhere in miniaudio:

    ```c
    ma_audio_buffer_config config = ma_audio_buffer_config_init(
        format,
        channels,
        sizeInFrames,
        pExistingData,
        &allocationCallbacks);

    ma_audio_buffer buffer;
    result = ma_audio_buffer_init(&config, &buffer);
    if (result != MA_SUCCESS) {
        // Error.
    }

    ...

    ma_audio_buffer_uninit(&buffer);
    ```

In the example above, the memory pointed to by `pExistingData` will *not* be copied and is how an
application can do self-managed memory allocation. If you would rather make a copy of the data, use
`ma_audio_buffer_init_copy()`. To uninitialize the buffer, use `ma_audio_buffer_uninit()`.

Sometimes it can be convenient to allocate the memory for the `ma_audio_buffer` structure and the
raw audio data in a contiguous block of memory. That is, the raw audio data will be located
immediately after the `ma_audio_buffer` structure. To do this, use
`ma_audio_buffer_alloc_and_init()`:

    ```c
    ma_audio_buffer_config config = ma_audio_buffer_config_init(
        format,
        channels,
        sizeInFrames,
        pExistingData,
        &allocationCallbacks);

    ma_audio_buffer* pBuffer
    result = ma_audio_buffer_alloc_and_init(&config, &pBuffer);
    if (result != MA_SUCCESS) {
        // Error
    }

    ...

    ma_audio_buffer_uninit_and_free(&buffer);
    ```

If you initialize the buffer with `ma_audio_buffer_alloc_and_init()` you should uninitialize it
with `ma_audio_buffer_uninit_and_free()`. In the example above, the memory pointed to by
`pExistingData` will be copied into the buffer, which is contrary to the behavior of
`ma_audio_buffer_init()`.

An audio buffer has a playback cursor just like a decoder. As you read frames from the buffer, the
cursor moves forward. The last parameter (`loop`) can be used to determine if the buffer should
loop. The return value is the number of frames actually read. If this is less than the number of
frames requested it means the end has been reached. This should never happen if the `loop`
parameter is set to true. If you want to manually loop back to the start, you can do so with with
`ma_audio_buffer_seek_to_pcm_frame(pAudioBuffer, 0)`. Below is an example for reading data from an
audio buffer.

    ```c
    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

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

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;

MA_API ma_result ma_fader_init(const ma_fader_config* pConfig, ma_fader* pFader);
MA_API ma_result ma_fader_process_pcm_frames(ma_fader* pFader, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount);
MA_API void ma_fader_get_data_format(const ma_fader* pFader, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate);
MA_API void ma_fader_set_fade(ma_fader* pFader, float volumeBeg, float volumeEnd, ma_uint64 lengthInFrames);
MA_API float ma_fader_get_current_volume(ma_fader* pFader);



/* 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;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

*/
MA_API float ma_volume_linear_to_db(float factor);

/*
Helper for converting gain in decibels to a linear factor.
*/
MA_API float ma_volume_db_to_linear(float gain);




/**************************************************************************************************

Data Source

**************************************************************************************************/
typedef void ma_data_source;

#define MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT    0x00000001

typedef struct
{
    ma_result (* onRead)(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
    ma_result (* onSeek)(ma_data_source* pDataSource, ma_uint64 frameIndex);
    ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
    ma_result (* onGetCursor)(ma_data_source* pDataSource, ma_uint64* pCursor);
    ma_result (* onGetLength)(ma_data_source* pDataSource, ma_uint64* pLength);
    ma_result (* onSetLooping)(ma_data_source* pDataSource, ma_bool32 isLooping);
    ma_uint32 flags;
} ma_data_source_vtable;

typedef ma_data_source* (* ma_data_source_get_next_proc)(ma_data_source* pDataSource);

typedef struct
{
    const ma_data_source_vtable* vtable;
} ma_data_source_config;

MA_API ma_data_source_config ma_data_source_config_init(void);


typedef struct
{
    const ma_data_source_vtable* vtable;
    ma_uint64 rangeBegInFrames;
    ma_uint64 rangeEndInFrames;             /* Set to -1 for unranged (default). */
    ma_uint64 loopBegInFrames;              /* Relative to rangeBegInFrames. */
    ma_uint64 loopEndInFrames;              /* Relative to rangeBegInFrames. Set to -1 for the end of the range. */
    ma_data_source* pCurrent;               /* When non-NULL, the data source being initialized will act as a proxy and will route all operations to pCurrent. Used in conjunction with pNext/onGetNext for seamless chaining. */
    ma_data_source* pNext;                  /* When set to NULL, onGetNext will be used. */
    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. */

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    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;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN


typedef enum
{
    ma_resource_manager_data_supply_type_unknown = 0,   /* Used for determining whether or the data supply has been initialized. */
    ma_resource_manager_data_supply_type_encoded,       /* Data supply is an encoded buffer. Connector is ma_decoder. */
    ma_resource_manager_data_supply_type_decoded,       /* Data supply is a decoded buffer. Connector is ma_audio_buffer. */
    ma_resource_manager_data_supply_type_decoded_paged  /* Data supply is a linked list of decoded buffers. Connector is ma_paged_audio_buffer. */
} ma_resource_manager_data_supply_type;

typedef struct
{
    MA_ATOMIC(4, ma_resource_manager_data_supply_type) type;    /* Read and written from different threads so needs to be accessed atomically. */
    union
    {
        struct
        {
            const void* pData;
            size_t sizeInBytes;
        } encoded;
        struct
        {
            const void* pData;
            ma_uint64 totalFrameCount;
            ma_uint64 decodedFrameCount;
            ma_format format;
            ma_uint32 channels;
            ma_uint32 sampleRate;
        } decoded;
        struct
        {
            ma_paged_audio_buffer_data data;
            ma_uint64 decodedFrameCount;
            ma_uint32 sampleRate;
        } decodedPaged;
    } backend;
} ma_resource_manager_data_supply;

struct ma_resource_manager_data_buffer_node
{
    ma_uint32 hashedName32;                         /* The hashed name. This is the key. */
    ma_uint32 refCount;
    MA_ATOMIC(4, ma_result) result;                 /* Result from asynchronous loading. When loading set to MA_BUSY. When fully loaded set to MA_SUCCESS. When deleting set to MA_UNAVAILABLE. */
    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_bool32 isDataOwnedByResourceManager;         /* Set to true when the underlying data buffer was allocated the resource manager. Set to false if it is owned by the application (via ma_resource_manager_register_*()). */
    ma_resource_manager_data_supply data;
    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);

/* Data Streams. */
MA_API ma_result ma_resource_manager_data_stream_init_ex(ma_resource_manager* pResourceManager, const ma_resource_manager_data_source_config* pConfig, ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_init_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_read_pcm_frames(ma_resource_manager_data_stream* pDataStream, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_resource_manager_data_stream_seek_to_pcm_frame(ma_resource_manager_data_stream* pDataStream, ma_uint64 frameIndex);
MA_API ma_result ma_resource_manager_data_stream_get_data_format(ma_resource_manager_data_stream* pDataStream, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_resource_manager_data_stream_get_cursor_in_pcm_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pCursor);
MA_API ma_result ma_resource_manager_data_stream_get_length_in_pcm_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pLength);
MA_API ma_result ma_resource_manager_data_stream_result(const ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_set_looping(ma_resource_manager_data_stream* pDataStream, ma_bool32 isLooping);
MA_API ma_bool32 ma_resource_manager_data_stream_is_looping(const ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pAvailableFrames);

/* Data Sources. */
MA_API ma_result ma_resource_manager_data_source_init_ex(ma_resource_manager* pResourceManager, const ma_resource_manager_data_source_config* pConfig, ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pResourceManager, const char* pName, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_init_w(ma_resource_manager* pResourceManager, const wchar_t* pName, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_init_copy(ma_resource_manager* pResourceManager, const ma_resource_manager_data_source* pExistingDataSource, ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_uninit(ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_read_pcm_frames(ma_resource_manager_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_resource_manager_data_source_seek_to_pcm_frame(ma_resource_manager_data_source* pDataSource, ma_uint64 frameIndex);
MA_API ma_result ma_resource_manager_data_source_get_data_format(ma_resource_manager_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_resource_manager_data_source_get_cursor_in_pcm_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pCursor);
MA_API ma_result ma_resource_manager_data_source_get_length_in_pcm_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pLength);
MA_API ma_result ma_resource_manager_data_source_result(const ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_set_looping(ma_resource_manager_data_source* pDataSource, ma_bool32 isLooping);
MA_API ma_bool32 ma_resource_manager_data_source_is_looping(const ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_get_available_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pAvailableFrames);

/* Job management. */
MA_API ma_result ma_resource_manager_post_job(ma_resource_manager* pResourceManager, const ma_job* pJob);
MA_API ma_result ma_resource_manager_post_job_quit(ma_resource_manager* pResourceManager);  /* Helper for posting a quit job. */
MA_API ma_result ma_resource_manager_next_job(ma_resource_manager* pResourceManager, ma_job* pJob);
MA_API ma_result ma_resource_manager_process_job(ma_resource_manager* pResourceManager, ma_job* pJob);  /* DEPRECATED. Use ma_job_process(). Will be removed in version 0.12. */
MA_API ma_result ma_resource_manager_process_next_job(ma_resource_manager* pResourceManager);   /* Returns MA_CANCELLED if a MA_JOB_TYPE_QUIT job is found. In non-blocking mode, returns MA_NO_DATA_AVAILABLE if no jobs are available. */
#endif  /* MA_NO_RESOURCE_MANAGER */



/************************************************************************************************************************************************************

Node Graph

************************************************************************************************************************************************************/
#ifndef MA_NO_NODE_GRAPH
/* Must never exceed 254. */
#ifndef MA_MAX_NODE_BUS_COUNT
#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
{

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

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);
MA_API ma_result ma_sound_stop(ma_sound* pSound);
MA_API void ma_sound_set_volume(ma_sound* pSound, float volume);
MA_API float ma_sound_get_volume(const ma_sound* pSound);
MA_API void ma_sound_set_pan(ma_sound* pSound, float pan);
MA_API float ma_sound_get_pan(const ma_sound* pSound);
MA_API void ma_sound_set_pan_mode(ma_sound* pSound, ma_pan_mode panMode);
MA_API ma_pan_mode ma_sound_get_pan_mode(const ma_sound* pSound);
MA_API void ma_sound_set_pitch(ma_sound* pSound, float pitch);
MA_API float ma_sound_get_pitch(const ma_sound* pSound);
MA_API void ma_sound_set_spatialization_enabled(ma_sound* pSound, ma_bool32 enabled);
MA_API ma_bool32 ma_sound_is_spatialization_enabled(const ma_sound* pSound);
MA_API void ma_sound_set_pinned_listener_index(ma_sound* pSound, ma_uint32 listenerIndex);
MA_API ma_uint32 ma_sound_get_pinned_listener_index(const ma_sound* pSound);
MA_API ma_uint32 ma_sound_get_listener_index(const ma_sound* pSound);
MA_API ma_vec3f ma_sound_get_direction_to_listener(const ma_sound* pSound);
MA_API void ma_sound_set_position(ma_sound* pSound, float x, float y, float z);
MA_API ma_vec3f ma_sound_get_position(const ma_sound* pSound);
MA_API void ma_sound_set_direction(ma_sound* pSound, float x, float y, float z);
MA_API ma_vec3f ma_sound_get_direction(const ma_sound* pSound);
MA_API void ma_sound_set_velocity(ma_sound* pSound, float x, float y, float z);
MA_API ma_vec3f ma_sound_get_velocity(const ma_sound* pSound);
MA_API void ma_sound_set_attenuation_model(ma_sound* pSound, ma_attenuation_model attenuationModel);
MA_API ma_attenuation_model ma_sound_get_attenuation_model(const ma_sound* pSound);
MA_API void ma_sound_set_positioning(ma_sound* pSound, ma_positioning positioning);
MA_API ma_positioning ma_sound_get_positioning(const ma_sound* pSound);
MA_API void ma_sound_set_rolloff(ma_sound* pSound, float rolloff);
MA_API float ma_sound_get_rolloff(const ma_sound* pSound);
MA_API void ma_sound_set_min_gain(ma_sound* pSound, float minGain);
MA_API float ma_sound_get_min_gain(const ma_sound* pSound);
MA_API void ma_sound_set_max_gain(ma_sound* pSound, float maxGain);
MA_API float ma_sound_get_max_gain(const ma_sound* pSound);
MA_API void ma_sound_set_min_distance(ma_sound* pSound, float minDistance);
MA_API float ma_sound_get_min_distance(const ma_sound* pSound);
MA_API void ma_sound_set_max_distance(ma_sound* pSound, float maxDistance);
MA_API float ma_sound_get_max_distance(const ma_sound* pSound);
MA_API void ma_sound_set_cone(ma_sound* pSound, float innerAngleInRadians, float outerAngleInRadians, float outerGain);
MA_API void ma_sound_get_cone(const ma_sound* pSound, float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain);
MA_API void ma_sound_set_doppler_factor(ma_sound* pSound, float dopplerFactor);
MA_API float ma_sound_get_doppler_factor(const ma_sound* pSound);
MA_API void ma_sound_set_directional_attenuation_factor(ma_sound* pSound, float directionalAttenuationFactor);
MA_API float ma_sound_get_directional_attenuation_factor(const ma_sound* pSound);
MA_API void ma_sound_set_fade_in_pcm_frames(ma_sound* pSound, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInFrames);
MA_API void ma_sound_set_fade_in_milliseconds(ma_sound* pSound, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInMilliseconds);
MA_API float ma_sound_get_current_fade_volume(ma_sound* pSound);
MA_API void ma_sound_set_start_time_in_pcm_frames(ma_sound* pSound, ma_uint64 absoluteGlobalTimeInFrames);
MA_API void ma_sound_set_start_time_in_milliseconds(ma_sound* pSound, ma_uint64 absoluteGlobalTimeInMilliseconds);
MA_API void ma_sound_set_stop_time_in_pcm_frames(ma_sound* pSound, ma_uint64 absoluteGlobalTimeInFrames);
MA_API void ma_sound_set_stop_time_in_milliseconds(ma_sound* pSound, ma_uint64 absoluteGlobalTimeInMilliseconds);
MA_API ma_bool32 ma_sound_is_playing(const ma_sound* pSound);
MA_API ma_uint64 ma_sound_get_time_in_pcm_frames(const ma_sound* pSound);
MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping);
MA_API ma_bool32 ma_sound_is_looping(const ma_sound* pSound);
MA_API ma_bool32 ma_sound_at_end(const ma_sound* pSound);
MA_API ma_result ma_sound_seek_to_pcm_frame(ma_sound* pSound, ma_uint64 frameIndex); /* Just a wrapper around ma_data_source_seek_to_pcm_frame(). */
MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor);
MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength);
MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor);
MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength);

MA_API ma_result ma_sound_group_init(ma_engine* pEngine, ma_uint32 flags, ma_sound_group* pParentGroup, ma_sound_group* pGroup);
MA_API ma_result ma_sound_group_init_ex(ma_engine* pEngine, const ma_sound_group_config* pConfig, ma_sound_group* pGroup);
MA_API void ma_sound_group_uninit(ma_sound_group* pGroup);
MA_API ma_engine* ma_sound_group_get_engine(const ma_sound_group* pGroup);
MA_API ma_result ma_sound_group_start(ma_sound_group* pGroup);
MA_API ma_result ma_sound_group_stop(ma_sound_group* pGroup);
MA_API void ma_sound_group_set_volume(ma_sound_group* pGroup, float volume);
MA_API float ma_sound_group_get_volume(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_pan(ma_sound_group* pGroup, float pan);
MA_API float ma_sound_group_get_pan(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_pan_mode(ma_sound_group* pGroup, ma_pan_mode panMode);
MA_API ma_pan_mode ma_sound_group_get_pan_mode(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_pitch(ma_sound_group* pGroup, float pitch);
MA_API float ma_sound_group_get_pitch(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_spatialization_enabled(ma_sound_group* pGroup, ma_bool32 enabled);
MA_API ma_bool32 ma_sound_group_is_spatialization_enabled(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_pinned_listener_index(ma_sound_group* pGroup, ma_uint32 listenerIndex);
MA_API ma_uint32 ma_sound_group_get_pinned_listener_index(const ma_sound_group* pGroup);
MA_API ma_uint32 ma_sound_group_get_listener_index(const ma_sound_group* pGroup);
MA_API ma_vec3f ma_sound_group_get_direction_to_listener(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_position(ma_sound_group* pGroup, float x, float y, float z);
MA_API ma_vec3f ma_sound_group_get_position(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_direction(ma_sound_group* pGroup, float x, float y, float z);
MA_API ma_vec3f ma_sound_group_get_direction(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_velocity(ma_sound_group* pGroup, float x, float y, float z);
MA_API ma_vec3f ma_sound_group_get_velocity(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_attenuation_model(ma_sound_group* pGroup, ma_attenuation_model attenuationModel);
MA_API ma_attenuation_model ma_sound_group_get_attenuation_model(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_positioning(ma_sound_group* pGroup, ma_positioning positioning);
MA_API ma_positioning ma_sound_group_get_positioning(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_rolloff(ma_sound_group* pGroup, float rolloff);
MA_API float ma_sound_group_get_rolloff(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_min_gain(ma_sound_group* pGroup, float minGain);
MA_API float ma_sound_group_get_min_gain(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_max_gain(ma_sound_group* pGroup, float maxGain);
MA_API float ma_sound_group_get_max_gain(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_min_distance(ma_sound_group* pGroup, float minDistance);
MA_API float ma_sound_group_get_min_distance(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_max_distance(ma_sound_group* pGroup, float maxDistance);
MA_API float ma_sound_group_get_max_distance(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_cone(ma_sound_group* pGroup, float innerAngleInRadians, float outerAngleInRadians, float outerGain);
MA_API void ma_sound_group_get_cone(const ma_sound_group* pGroup, float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain);
MA_API void ma_sound_group_set_doppler_factor(ma_sound_group* pGroup, float dopplerFactor);
MA_API float ma_sound_group_get_doppler_factor(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_directional_attenuation_factor(ma_sound_group* pGroup, float directionalAttenuationFactor);
MA_API float ma_sound_group_get_directional_attenuation_factor(const ma_sound_group* pGroup);
MA_API void ma_sound_group_set_fade_in_pcm_frames(ma_sound_group* pGroup, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInFrames);
MA_API void ma_sound_group_set_fade_in_milliseconds(ma_sound_group* pGroup, float volumeBeg, float volumeEnd, ma_uint64 fadeLengthInMilliseconds);
MA_API float ma_sound_group_get_current_fade_volume(ma_sound_group* pGroup);
MA_API void ma_sound_group_set_start_time_in_pcm_frames(ma_sound_group* pGroup, ma_uint64 absoluteGlobalTimeInFrames);
MA_API void ma_sound_group_set_start_time_in_milliseconds(ma_sound_group* pGroup, ma_uint64 absoluteGlobalTimeInMilliseconds);
MA_API void ma_sound_group_set_stop_time_in_pcm_frames(ma_sound_group* pGroup, ma_uint64 absoluteGlobalTimeInFrames);
MA_API void ma_sound_group_set_stop_time_in_milliseconds(ma_sound_group* pGroup, ma_uint64 absoluteGlobalTimeInMilliseconds);
MA_API ma_bool32 ma_sound_group_is_playing(const ma_sound_group* pGroup);
MA_API ma_uint64 ma_sound_group_get_time_in_pcm_frames(const ma_sound_group* pGroup);
#endif  /* MA_NO_ENGINE */

#ifdef __cplusplus

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

            if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
                wf.Format.nSamplesPerSec = ma_get_best_sample_rate_within_range(caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate);
            } else {
                wf.Format.nSamplesPerSec = caps.dwMaxSecondarySampleRate;
            }
        }

        wf.Format.nBlockAlign     = (WORD)(wf.Format.nChannels * wf.Format.wBitsPerSample / 8);
        wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;

        /*
        From MSDN:

        The method succeeds even if the hardware does not support the requested format; DirectSound sets the buffer to the closest
        supported format. To determine whether this has happened, an application can call the GetFormat method for the primary buffer
        and compare the result with the format that was requested with the SetFormat method.
        */
        hr = ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)&wf);
        if (FAILED(hr)) {
            ma_device_uninit__dsound(pDevice);
            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to set format of playback device's primary buffer.");
            return ma_result_from_HRESULT(hr);
        }

        /* Get the _actual_ properties of the buffer. */
        pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
        hr = ma_IDirectSoundBuffer_GetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)pActualFormat, sizeof(rawdata), NULL);
        if (FAILED(hr)) {
            ma_device_uninit__dsound(pDevice);
            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to retrieve the actual format of the playback device's primary buffer.");
            return ma_result_from_HRESULT(hr);
        }

        /* We now have enough information to start setting some output properties. */
        pDescriptorPlayback->format     = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
        pDescriptorPlayback->channels   = pActualFormat->Format.nChannels;
        pDescriptorPlayback->sampleRate = pActualFormat->Format.nSamplesPerSec;

        /* Get the internal channel map based on the channel mask. */
        if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
            ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
        } else {
            ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDescriptorPlayback->channels, pDescriptorPlayback->channelMap);
        }

        /* The size of the buffer must be a clean multiple of the period count. */
        periodSizeInFrames = ma_calculate_period_size_in_frames_from_descriptor__dsound(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
        periodCount = (pDescriptorPlayback->periodCount > 0) ? pDescriptorPlayback->periodCount : MA_DEFAULT_PERIODS;

        /*
        Meaning of dwFlags (from MSDN):

        DSBCAPS_CTRLPOSITIONNOTIFY
          The buffer has position notification capability.

        DSBCAPS_GLOBALFOCUS
          With this flag set, an application using DirectSound can continue to play its buffers if the user switches focus to
          another application, even if the new application uses DirectSound.

        DSBCAPS_GETCURRENTPOSITION2
          In the first version of DirectSound, the play cursor was significantly ahead of the actual playing sound on emulated
          sound cards; it was directly behind the write cursor. Now, if the DSBCAPS_GETCURRENTPOSITION2 flag is specified, the
          application can get a more accurate play cursor.
        */
        MA_ZERO_OBJECT(&descDS);
        descDS.dwSize = sizeof(descDS);
        descDS.dwFlags = MA_DSBCAPS_CTRLPOSITIONNOTIFY | MA_DSBCAPS_GLOBALFOCUS | MA_DSBCAPS_GETCURRENTPOSITION2;
        descDS.dwBufferBytes = periodSizeInFrames * periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels);
        descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
        hr = ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDS, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackBuffer, NULL);
        if (FAILED(hr)) {
            ma_device_uninit__dsound(pDevice);
            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSound_CreateSoundBuffer() failed for playback device's secondary buffer.");
            return ma_result_from_HRESULT(hr);
        }

        /* DirectSound should give us a buffer exactly the size we asked for. */
        pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
        pDescriptorPlayback->periodCount        = periodCount;
    }

    return MA_SUCCESS;
}


static ma_result ma_device_data_loop__dsound(ma_device* pDevice)
{
    ma_result result = MA_SUCCESS;
    ma_uint32 bpfDeviceCapture  = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
    ma_uint32 bpfDevicePlayback = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
    HRESULT hr;
    DWORD lockOffsetInBytesCapture;
    DWORD lockSizeInBytesCapture;
    DWORD mappedSizeInBytesCapture;
    DWORD mappedDeviceFramesProcessedCapture;
    void* pMappedDeviceBufferCapture;
    DWORD lockOffsetInBytesPlayback;
    DWORD lockSizeInBytesPlayback;
    DWORD mappedSizeInBytesPlayback;
    void* pMappedDeviceBufferPlayback;
    DWORD prevReadCursorInBytesCapture = 0;
    DWORD prevPlayCursorInBytesPlayback = 0;
    ma_bool32 physicalPlayCursorLoopFlagPlayback = 0;
    DWORD virtualWriteCursorInBytesPlayback = 0;
    ma_bool32 virtualWriteCursorLoopFlagPlayback = 0;
    ma_bool32 isPlaybackDeviceStarted = MA_FALSE;
    ma_uint32 framesWrittenToPlaybackDevice = 0;   /* For knowing whether or not the playback device needs to be started. */
    ma_uint32 waitTimeInMilliseconds = 1;

    MA_ASSERT(pDevice != NULL);

    /* The first thing to do is start the capture device. The playback device is only started after the first period is written. */
    if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
        hr = ma_IDirectSoundCaptureBuffer_Start((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, MA_DSCBSTART_LOOPING);
        if (FAILED(hr)) {
            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCaptureBuffer_Start() failed.");
            return ma_result_from_HRESULT(hr);
        }
    }

    while (ma_device_get_state(pDevice) == ma_device_state_started) {
        switch (pDevice->type)
        {

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

                } else {
                    /*
                    The capture position has looped. This is the more complex case. Map to the end of the buffer. If this does not return anything,
                    do it again from the start.
                    */
                    if (prevReadCursorInBytesCapture < pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) {
                        /* Lock up to the end of the buffer. */
                        lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
                        lockSizeInBytesCapture   = (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) - prevReadCursorInBytesCapture;
                    } else {
                        /* Lock starting from the start of the buffer. */
                        lockOffsetInBytesCapture = 0;
                        lockSizeInBytesCapture   = physicalReadCursorInBytes;
                    }
                }

                if (lockSizeInBytesCapture == 0) {
                    ma_sleep(waitTimeInMilliseconds);
                    continue; /* Nothing is available in the capture buffer. */
                }

                hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedDeviceBufferCapture, &mappedSizeInBytesCapture, NULL, NULL, 0);
                if (FAILED(hr)) {
                    ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from capture device in preparation for writing to the device.");
                    return ma_result_from_HRESULT(hr);
                }


                /* At this point we have some input data that we need to output. We do not return until every mapped frame of the input data is written to the playback device. */
                mappedDeviceFramesProcessedCapture = 0;

                for (;;) {  /* Keep writing to the playback device. */
                    ma_uint8  inputFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
                    ma_uint32 inputFramesInClientFormatCap = sizeof(inputFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
                    ma_uint8  outputFramesInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
                    ma_uint32 outputFramesInClientFormatCap = sizeof(outputFramesInClientFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
                    ma_uint32 outputFramesInClientFormatCount;
                    ma_uint32 outputFramesInClientFormatConsumed = 0;
                    ma_uint64 clientCapturedFramesToProcess = ma_min(inputFramesInClientFormatCap, outputFramesInClientFormatCap);
                    ma_uint64 deviceCapturedFramesToProcess = (mappedSizeInBytesCapture / bpfDeviceCapture) - mappedDeviceFramesProcessedCapture;
                    void* pRunningMappedDeviceBufferCapture = ma_offset_ptr(pMappedDeviceBufferCapture, mappedDeviceFramesProcessedCapture * bpfDeviceCapture);

                    result = ma_data_converter_process_pcm_frames(&pDevice->capture.converter, pRunningMappedDeviceBufferCapture, &deviceCapturedFramesToProcess, inputFramesInClientFormat, &clientCapturedFramesToProcess);
                    if (result != MA_SUCCESS) {
                        break;
                    }

                    outputFramesInClientFormatCount     = (ma_uint32)clientCapturedFramesToProcess;
                    mappedDeviceFramesProcessedCapture += (ma_uint32)deviceCapturedFramesToProcess;

                    ma_device__handle_data_callback(pDevice, outputFramesInClientFormat, inputFramesInClientFormat, (ma_uint32)clientCapturedFramesToProcess);

                    /* At this point we have input and output data in client format. All we need to do now is convert it to the output device format. This may take a few passes. */
                    for (;;) {
                        ma_uint32 framesWrittenThisIteration;
                        DWORD physicalPlayCursorInBytes;
                        DWORD physicalWriteCursorInBytes;
                        DWORD availableBytesPlayback;
                        DWORD silentPaddingInBytes = 0; /* <-- Must be initialized to 0. */

                        /* We need the physical play and write cursors. */
                        if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
                            break;
                        }

                        if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
                            physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
                        }
                        prevPlayCursorInBytesPlayback  = physicalPlayCursorInBytes;

                        /* If there's any bytes available for writing we can do that now. The space between the virtual cursor position and play cursor. */
                        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 {
                                /* This is an error. */
                                ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Duplex/Playback): Play cursor has moved in front of the write cursor (same loop iteration). physicalPlayCursorInBytes=%ld, virtualWriteCurs...
                                availableBytesPlayback = 0;
                            }
                        } 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 {
                                /* This is an error. */
                                ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Duplex/Playback): Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCur...
                                availableBytesPlayback = 0;
                            }
                        }

                        /* If there's no room available for writing we need to wait for more. */
                        if (availableBytesPlayback == 0) {
                            /* If we haven't started the device yet, this will never get beyond 0. In this case we need to get the device started. */
                            if (!isPlaybackDeviceStarted) {
                                hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
                                if (FAILED(hr)) {
                                    ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
                                    ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.");
                                    return ma_result_from_HRESULT(hr);
                                }
                                isPlaybackDeviceStarted = MA_TRUE;
                            } else {
                                ma_sleep(waitTimeInMilliseconds);
                                continue;
                            }
                        }


                        /* Getting here means there room available somewhere. We limit this to either the end of the buffer or the physical play cursor, whichever is closest. */
                        lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
                        if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
                            /* Same loop iteration. Go up to the end of the buffer. */
                            lockSizeInBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
                        } else {
                            /* Different loop iterations. Go up to the physical play cursor. */
                            lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
                        }

                        hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedDeviceBufferPlayback, &mappedSizeInBytesPlayback, NULL, NULL, 0);
                        if (FAILED(hr)) {
                            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from playback device in preparation for writing to the device.");
                            result = ma_result_from_HRESULT(hr);
                            break;
                        }

                        /*
                        Experiment: If the playback buffer is being starved, pad it with some silence to get it back in sync. This will cause a glitch, but it may prevent
                        endless glitching due to it constantly running out of data.
                        */
                        if (isPlaybackDeviceStarted) {
                            DWORD bytesQueuedForPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - availableBytesPlayback;
                            if (bytesQueuedForPlayback < (pDevice->playback.internalPeriodSizeInFrames*bpfDevicePlayback)) {
                                silentPaddingInBytes   = (pDevice->playback.internalPeriodSizeInFrames*2*bpfDevicePlayback) - bytesQueuedForPlayback;
                                if (silentPaddingInBytes > lockSizeInBytesPlayback) {
                                    silentPaddingInBytes = lockSizeInBytesPlayback;
                                }

                                ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Duplex/Playback) Playback buffer starved. availableBytesPlayback=%ld, silentPaddingInBytes=%ld\n", availableBytesPlayback, silentPaddingInB...
                            }
                        }

                        /* At this point we have a buffer for output. */
                        if (silentPaddingInBytes > 0) {
                            MA_ZERO_MEMORY(pMappedDeviceBufferPlayback, silentPaddingInBytes);
                            framesWrittenThisIteration = silentPaddingInBytes/bpfDevicePlayback;
                        } else {
                            ma_uint64 convertedFrameCountIn  = (outputFramesInClientFormatCount - outputFramesInClientFormatConsumed);
                            ma_uint64 convertedFrameCountOut = mappedSizeInBytesPlayback/bpfDevicePlayback;
                            void* pConvertedFramesIn  = ma_offset_ptr(outputFramesInClientFormat, outputFramesInClientFormatConsumed * bpfDevicePlayback);
                            void* pConvertedFramesOut = pMappedDeviceBufferPlayback;

                            result = ma_data_converter_process_pcm_frames(&pDevice->playback.converter, pConvertedFramesIn, &convertedFrameCountIn, pConvertedFramesOut, &convertedFrameCountOut);
                            if (result != MA_SUCCESS) {
                                break;
                            }

                            outputFramesInClientFormatConsumed += (ma_uint32)convertedFrameCountOut;
                            framesWrittenThisIteration          = (ma_uint32)convertedFrameCountOut;
                        }


                        hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedDeviceBufferPlayback, framesWrittenThisIteration*bpfDevicePlayback, NULL, 0);
                        if (FAILED(hr)) {
                            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to unlock internal buffer from playback device after writing to the device.");
                            result = ma_result_from_HRESULT(hr);
                            break;
                        }

                        virtualWriteCursorInBytesPlayback += framesWrittenThisIteration*bpfDevicePlayback;
                        if ((virtualWriteCursorInBytesPlayback/bpfDevicePlayback) == pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods) {
                            virtualWriteCursorInBytesPlayback  = 0;
                            virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
                        }

                        /*

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

                    The capture position has looped. This is the more complex case. Map to the end of the buffer. If this does not return anything,
                    do it again from the start.
                    */
                    if (prevReadCursorInBytesCapture < pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) {
                        /* Lock up to the end of the buffer. */
                        lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
                        lockSizeInBytesCapture   = (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture) - prevReadCursorInBytesCapture;
                    } else {
                        /* Lock starting from the start of the buffer. */
                        lockOffsetInBytesCapture = 0;
                        lockSizeInBytesCapture   = physicalReadCursorInBytes;
                    }
                }

                if (lockSizeInBytesCapture < pDevice->capture.internalPeriodSizeInFrames) {
                    ma_sleep(waitTimeInMilliseconds);
                    continue; /* Nothing is available in the capture buffer. */
                }

                hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedDeviceBufferCapture, &mappedSizeInBytesCapture, NULL, NULL, 0);
                if (FAILED(hr)) {
                    ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from capture device in preparation for writing to the device.");
                    result = ma_result_from_HRESULT(hr);
                }

                if (lockSizeInBytesCapture != mappedSizeInBytesCapture) {
                    ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_DEBUG, "[DirectSound] (Capture) lockSizeInBytesCapture=%ld != mappedSizeInBytesCapture=%ld\n", lockSizeInBytesCapture, mappedSizeInBytesCapture);
                }

                ma_device__send_frames_to_client(pDevice, mappedSizeInBytesCapture/bpfDeviceCapture, pMappedDeviceBufferCapture);

                hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedDeviceBufferCapture, mappedSizeInBytesCapture, NULL, 0);
                if (FAILED(hr)) {
                    ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to unlock internal buffer from capture device after reading from the device.");
                    return ma_result_from_HRESULT(hr);
                }
                prevReadCursorInBytesCapture = lockOffsetInBytesCapture + mappedSizeInBytesCapture;

                if (prevReadCursorInBytesCapture == (pDevice->capture.internalPeriodSizeInFrames*pDevice->capture.internalPeriods*bpfDeviceCapture)) {
                    prevReadCursorInBytesCapture = 0;
                }
            } break;



            case ma_device_type_playback:
            {
                DWORD availableBytesPlayback;
                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 there's any bytes available for writing we can do that now. The space between the virtual cursor position and play cursor. */
                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 {
                        /* This is an error. */
                        ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Playback): Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld....
                        availableBytesPlayback = 0;
                    }
                } 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 {
                        /* This is an error. */
                        ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[DirectSound] (Playback): Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%ld, virtualWriteCursorInBytes=%ld....
                        availableBytesPlayback = 0;
                    }
                }

                /* If there's no room available for writing we need to wait for more. */
                if (availableBytesPlayback < pDevice->playback.internalPeriodSizeInFrames) {
                    /* If we haven't started the device yet, this will never get beyond 0. In this case we need to get the device started. */
                    if (availableBytesPlayback == 0 && !isPlaybackDeviceStarted) {
                        hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
                        if (FAILED(hr)) {
                            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.");
                            return ma_result_from_HRESULT(hr);
                        }
                        isPlaybackDeviceStarted = MA_TRUE;
                    } else {
                        ma_sleep(waitTimeInMilliseconds);
                        continue;
                    }
                }

                /* Getting here means there room available somewhere. We limit this to either the end of the buffer or the physical play cursor, whichever is closest. */
                lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
                if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
                    /* Same loop iteration. Go up to the end of the buffer. */
                    lockSizeInBytesPlayback = (pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) - virtualWriteCursorInBytesPlayback;
                } else {
                    /* Different loop iterations. Go up to the physical play cursor. */
                    lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
                }

                hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedDeviceBufferPlayback, &mappedSizeInBytesPlayback, NULL, NULL, 0);
                if (FAILED(hr)) {
                    ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to map buffer from playback device in preparation for writing to the device.");
                    result = ma_result_from_HRESULT(hr);
                    break;
                }

                /* At this point we have a buffer for output. */
                ma_device__read_frames_from_client(pDevice, (mappedSizeInBytesPlayback/bpfDevicePlayback), pMappedDeviceBufferPlayback);

                hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedDeviceBufferPlayback, mappedSizeInBytesPlayback, NULL, 0);
                if (FAILED(hr)) {
                    ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to unlock internal buffer from playback device after writing to the device.");
                    result = ma_result_from_HRESULT(hr);
                    break;
                }

                virtualWriteCursorInBytesPlayback += mappedSizeInBytesPlayback;
                if (virtualWriteCursorInBytesPlayback == pDevice->playback.internalPeriodSizeInFrames*pDevice->playback.internalPeriods*bpfDevicePlayback) {
                    virtualWriteCursorInBytesPlayback  = 0;
                    virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
                }

                /*
                We may need to start the device. We want two full periods to be written before starting the playback device. Having an extra period adds
                a bit of a buffer to prevent the playback buffer from getting starved.
                */
                framesWrittenToPlaybackDevice += mappedSizeInBytesPlayback/bpfDevicePlayback;
                if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= pDevice->playback.internalPeriodSizeInFrames) {
                    hr = ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING);
                    if (FAILED(hr)) {
                        ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundBuffer_Play() failed.");
                        return ma_result_from_HRESULT(hr);
                    }
                    isPlaybackDeviceStarted = MA_TRUE;
                }
            } break;


            default: return MA_INVALID_ARGS;   /* Invalid device type. */
        }

        if (result != MA_SUCCESS) {
            return result;
        }
    }

    /* Getting here means the device is being stopped. */
    if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
        hr = ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
        if (FAILED(hr)) {
            ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] IDirectSoundCaptureBuffer_Stop() failed.");
            return ma_result_from_HRESULT(hr);
        }
    }

    if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
        /* The playback device should be drained before stopping. All we do is wait until the available bytes is equal to the size of the buffer. */
        if (isPlaybackDeviceStarted) {
            for (;;) {
                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. */

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

}

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;
}

MA_API float ma_delay_get_wet(const ma_delay* pDelay)
{
    if (pDelay == NULL) {
        return 0;
    }

    return pDelay->config.wet;
}

MA_API void ma_delay_set_dry(ma_delay* pDelay, float value)
{
    if (pDelay == NULL) {
        return;
    }

    pDelay->config.dry = value;
}

MA_API float ma_delay_get_dry(const ma_delay* pDelay)
{
    if (pDelay == NULL) {
        return 0;
    }

    return pDelay->config.dry;
}

MA_API void ma_delay_set_decay(ma_delay* pDelay, float value)
{
    if (pDelay == NULL) {
        return;
    }

    pDelay->config.decay = value;
}

MA_API float ma_delay_get_decay(const ma_delay* pDelay)
{
    if (pDelay == NULL) {
        return 0;
    }

    return pDelay->config.decay;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    }

    return pPanner->mode;
}

MA_API void ma_panner_set_pan(ma_panner* pPanner, float pan)
{
    if (pPanner == NULL) {
        return;
    }

    pPanner->pan = ma_clamp(pan, -1.0f, 1.0f);
}

MA_API float ma_panner_get_pan(const ma_panner* pPanner)
{
    if (pPanner == NULL) {
        return 0;
    }

    return pPanner->pan;
}




MA_API ma_fader_config ma_fader_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate)
{
    ma_fader_config config;

    MA_ZERO_OBJECT(&config);
    config.format     = format;
    config.channels   = channels;
    config.sampleRate = sampleRate;

    return config;
}


MA_API ma_result ma_fader_init(const ma_fader_config* pConfig, ma_fader* pFader)
{
    if (pFader == NULL) {
        return MA_INVALID_ARGS;
    }

    MA_ZERO_OBJECT(pFader);

    if (pConfig == NULL) {
        return MA_INVALID_ARGS;
    }

    /* Only f32 is supported for now. */
    if (pConfig->format != ma_format_f32) {
        return MA_INVALID_ARGS;
    }

    pFader->config         = *pConfig;
    pFader->volumeBeg      = 1;
    pFader->volumeEnd      = 1;
    pFader->lengthInFrames = 0;
    pFader->cursorInFrames = 0;

    return MA_SUCCESS;
}

MA_API ma_result ma_fader_process_pcm_frames(ma_fader* pFader, void* pFramesOut, const void* pFramesIn, ma_uint64 frameCount)
{
    if (pFader == NULL) {
        return MA_INVALID_ARGS;
    }

    /*
    For now we need to clamp frameCount so that the cursor never overflows 32-bits. This is required for
    the conversion to a float which we use for the linear interpolation. This might be changed later.
    */
    if (frameCount + pFader->cursorInFrames > UINT_MAX) {
        frameCount = UINT_MAX - pFader->cursorInFrames;
    }

    /* Optimized path if volumeBeg and volumeEnd are equal. */
    if (pFader->volumeBeg == pFader->volumeEnd) {
        if (pFader->volumeBeg == 1) {
            /* Straight copy. */
            ma_copy_pcm_frames(pFramesOut, pFramesIn, frameCount, pFader->config.format, pFader->config.channels);
        } else {
            /* Copy with volume. */
            ma_copy_and_apply_volume_and_clip_pcm_frames(pFramesOut, pFramesIn, frameCount, pFader->config.format, pFader->config.channels, pFader->volumeEnd);
        }
    } else {
        /* Slower path. Volumes are different, so may need to do an interpolation. */
        if (pFader->cursorInFrames >= pFader->lengthInFrames) {
            /* Fast path. We've gone past the end of the fade period so just apply the end volume to all samples. */
            ma_copy_and_apply_volume_and_clip_pcm_frames(pFramesOut, pFramesIn, frameCount, pFader->config.format, pFader->config.channels, pFader->volumeEnd);
        } else {
            /* Slow path. This is where we do the actual fading. */
            ma_uint64 iFrame;
            ma_uint32 iChannel;

            /* For now we only support f32. Support for other formats will be added later. */
            if (pFader->config.format == ma_format_f32) {
                const float* pFramesInF32  = (const float*)pFramesIn;
                /* */ float* pFramesOutF32 = (      float*)pFramesOut;

                for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
                    float a = (ma_uint32)ma_min(pFader->cursorInFrames + iFrame, pFader->lengthInFrames) / (float)((ma_uint32)pFader->lengthInFrames);   /* Safe cast due to the frameCount clamp at the top of this function. */
                    float volume = ma_mix_f32_fast(pFader->volumeBeg, pFader->volumeEnd, a);

                    for (iChannel = 0; iChannel < pFader->config.channels; iChannel += 1) {
                        pFramesOutF32[iFrame*pFader->config.channels + iChannel] = pFramesInF32[iFrame*pFader->config.channels + iChannel] * volume;
                    }
                }
            } else {
                return MA_NOT_IMPLEMENTED;
            }
        }
    }

    pFader->cursorInFrames += frameCount;

    return MA_SUCCESS;
}

MA_API void ma_fader_get_data_format(const ma_fader* pFader, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate)
{
    if (pFader == NULL) {
        return;
    }

    if (pFormat != NULL) {
        *pFormat = pFader->config.format;
    }

    if (pChannels != NULL) {
        *pChannels = pFader->config.channels;
    }

    if (pSampleRate != NULL) {
        *pSampleRate = pFader->config.sampleRate;
    }
}

MA_API void ma_fader_set_fade(ma_fader* pFader, float volumeBeg, float volumeEnd, ma_uint64 lengthInFrames)
{
    if (pFader == NULL) {
        return;
    }

    /* If the volume is negative, use current volume. */
    if (volumeBeg < 0) {
        volumeBeg = ma_fader_get_current_volume(pFader);
    }

    /*
    The length needs to be clamped to 32-bits due to how we convert it to a float for linear
    interpolation reasons. I might change this requirement later, but for now it's not important.
    */
    if (lengthInFrames > UINT_MAX) {
        lengthInFrames = UINT_MAX;
    }

    pFader->volumeBeg      = volumeBeg;
    pFader->volumeEnd      = volumeEnd;
    pFader->lengthInFrames = lengthInFrames;
    pFader->cursorInFrames = 0; /* Reset cursor. */
}

MA_API float ma_fader_get_current_volume(ma_fader* pFader)
{
    if (pFader == NULL) {
        return 0.0f;
    }

    /* The current volume depends on the position of the cursor. */
    if (pFader->cursorInFrames == 0) {
        return pFader->volumeBeg;
    } else if (pFader->cursorInFrames >= pFader->lengthInFrames) {
        return pFader->volumeEnd;
    } else {
        /* The cursor is somewhere inside the fading period. We can figure this out with a simple linear interpoluation between volumeBeg and volumeEnd based on our cursor position. */
        return ma_mix_f32_fast(pFader->volumeBeg, pFader->volumeEnd, (ma_uint32)pFader->cursorInFrames / (float)((ma_uint32)pFader->lengthInFrames));    /* Safe cast to uint32 because we clamp it in ma_fader_process_pcm_frames(). */
    }
}





MA_API ma_vec3f ma_vec3f_init_3f(float x, float y, float z)
{
    ma_vec3f v;

    v.x = x;
    v.y = y;
    v.z = z;

    return v;
}

MA_API ma_vec3f ma_vec3f_sub(ma_vec3f a, ma_vec3f b)
{
    return ma_vec3f_init_3f(
        a.x - b.x,
        a.y - b.y,
        a.z - b.z
    );
}

MA_API ma_vec3f ma_vec3f_neg(ma_vec3f a)
{
    return ma_vec3f_init_3f(
        -a.x,
        -a.y,
        -a.z
    );
}

MA_API float ma_vec3f_dot(ma_vec3f a, ma_vec3f b)
{
    return a.x*b.x + a.y*b.y + a.z*b.z;
}

MA_API float ma_vec3f_len2(ma_vec3f v)
{
    return ma_vec3f_dot(v, v);
}

MA_API float ma_vec3f_len(ma_vec3f v)
{
    return (float)ma_sqrtd(ma_vec3f_len2(v));
}

MA_API float ma_vec3f_dist(ma_vec3f a, ma_vec3f b)
{
    return ma_vec3f_len(ma_vec3f_sub(a, b));
}

MA_API ma_vec3f ma_vec3f_normalize(ma_vec3f v)
{
    float f;
    float l = ma_vec3f_len(v);

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

}

MA_API void ma_data_source_uninit(ma_data_source* pDataSource)
{
    if (pDataSource == NULL) {
        return;
    }

    /*
    This is placeholder in case we need this later. Data sources need to call this in their
    uninitialization routine to ensure things work later on if something is added here.
    */
}

static ma_result ma_data_source_resolve_current(ma_data_source* pDataSource, ma_data_source** ppCurrentDataSource)
{
    ma_data_source_base* pCurrentDataSource = (ma_data_source_base*)pDataSource;

    MA_ASSERT(pDataSource         != NULL);
    MA_ASSERT(ppCurrentDataSource != NULL);

    if (pCurrentDataSource->pCurrent == NULL) {
        /*
        The current data source is NULL. If we're using this in the context of a chain we need to return NULL
        here so that we don't end up looping. Otherwise we just return the data source itself.
        */
        if (pCurrentDataSource->pNext != NULL || pCurrentDataSource->onGetNext != NULL) {
            pCurrentDataSource = NULL;
        } else {
            pCurrentDataSource = (ma_data_source_base*)pDataSource; /* Not being used in a chain. Make sure we just always read from the data source itself at all times. */
        }
    } else {
        pCurrentDataSource = (ma_data_source_base*)pCurrentDataSource->pCurrent;
    }

    *ppCurrentDataSource = pCurrentDataSource;

    return MA_SUCCESS;
}

static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
    ma_result result;
    ma_uint64 framesRead = 0;
    ma_bool32 loop = ma_data_source_is_looping(pDataSource);

    if (pDataSourceBase == NULL) {
        return MA_AT_END;
    }

    if (frameCount == 0) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSourceBase->vtable->flags & MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT) != 0 || (pDataSourceBase->rangeEndInFrames == ~((ma_uint64)0) && (pDataSourceBase->loopEndInFrames == ~((ma_uint64)0) || loop == MA_FALSE))) {
        /* Either the data source is self-managing the range, or no range is set - just read like normal. The data source itself will tell us when the end is reached. */
        result = pDataSourceBase->vtable->onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead);
    } else {
        /* Need to clamp to within the range. */
        ma_uint64 cursor;

        result = ma_data_source_get_cursor_in_pcm_frames(pDataSourceBase, &cursor);
        if (result != MA_SUCCESS) {
            /* Failed to retrieve the cursor. Cannot read within a range or loop points. Just read like normal - this may happen for things like noise data sources where it doesn't really matter. */
            result = pDataSourceBase->vtable->onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead);
        } else {
            ma_uint64 rangeEnd;

            /* We have the cursor. We need to make sure we don't read beyond our range. */
            rangeEnd = pDataSourceBase->rangeEndInFrames;

            /* If looping, make sure we're within range. */
            if (loop) {
                if (pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) {
                    rangeEnd = ma_min(rangeEnd, pDataSourceBase->rangeBegInFrames + pDataSourceBase->loopEndInFrames);
                }
            }

            if (frameCount > (rangeEnd - cursor) && rangeEnd != ~((ma_uint64)0)) {
                frameCount = (rangeEnd - cursor);
            }

            /*
            If the cursor is sitting on the end of the range the frame count will be set to 0 which can
            result in MA_INVALID_ARGS. In this case, we don't want to try reading, but instead return
            MA_AT_END so the higher level function can know about it.
            */
            if (frameCount > 0) {
                result = pDataSourceBase->vtable->onRead(pDataSourceBase, pFramesOut, frameCount, &framesRead);
            } else {
                result = MA_AT_END; /* The cursor is sitting on the end of the range which means we're at the end. */
            }
        }
    }

    if (pFramesRead != NULL) {
        *pFramesRead = framesRead;
    }

    /* We need to make sure MA_AT_END is returned if we hit the end of the range. */
    if (result == MA_SUCCESS && framesRead == 0) {
        result  = MA_AT_END;
    }

    return result;
}

MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    ma_result result = MA_SUCCESS;
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
    ma_data_source_base* pCurrentDataSource;
    void* pRunningFramesOut = pFramesOut;
    ma_uint64 totalFramesProcessed = 0;
    ma_format format;
    ma_uint32 channels;
    ma_uint32 emptyLoopCounter = 0; /* Keeps track of how many times 0 frames have been read. For infinite loop detection of sounds with no audio data. */
    ma_bool32 loop;

    if (pFramesRead != NULL) {
        *pFramesRead = 0;
    }

    if (frameCount == 0) {
        return MA_INVALID_ARGS;
    }

    if (pDataSourceBase == NULL) {
        return MA_INVALID_ARGS;
    }

    loop = ma_data_source_is_looping(pDataSource);

    /*
    We need to know the data format so we can advance the output buffer as we read frames. If this
    fails, chaining will not work and we'll just read as much as we can from the current source.
    */
    if (ma_data_source_get_data_format(pDataSource, &format, &channels, NULL, NULL, 0) != MA_SUCCESS) {
        result = ma_data_source_resolve_current(pDataSource, (ma_data_source**)&pCurrentDataSource);
        if (result != MA_SUCCESS) {
            return result;
        }

        return ma_data_source_read_pcm_frames_within_range(pCurrentDataSource, pFramesOut, frameCount, pFramesRead);
    }

    /*
    Looping is a bit of a special case. When the `loop` argument is true, chaining will not work and
    only the current data source will be read from.
    */

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

        return MA_NOT_IMPLEMENTED;
    }

    if (frameIndex > pDataSourceBase->rangeEndInFrames) {
        return MA_INVALID_OPERATION;    /* Trying to seek to far forward. */
    }

    return pDataSourceBase->vtable->onSeek(pDataSource, pDataSourceBase->rangeBegInFrames + 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_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
    ma_result result;
    ma_format format;
    ma_uint32 channels;
    ma_uint32 sampleRate;

    /* Initialize to defaults for safety just in case the data source does not implement this callback. */
    if (pFormat != NULL) {
        *pFormat = ma_format_unknown;
    }
    if (pChannels != NULL) {
        *pChannels = 0;
    }
    if (pSampleRate != NULL) {
        *pSampleRate = 0;
    }
    if (pChannelMap != NULL) {
        MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
    }

    if (pDataSourceBase == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pDataSourceBase->vtable->onGetDataFormat == NULL) {
        return MA_NOT_IMPLEMENTED;
    }

    result = pDataSourceBase->vtable->onGetDataFormat(pDataSource, &format, &channels, &sampleRate, pChannelMap, channelMapCap);
    if (result != MA_SUCCESS) {
        return result;
    }

    if (pFormat != NULL) {
        *pFormat = format;
    }
    if (pChannels != NULL) {
        *pChannels = channels;
    }
    if (pSampleRate != NULL) {
        *pSampleRate = sampleRate;
    }

    /* Channel map was passed in directly to the callback. This is safe due to the channelMapCap parameter. */

    return MA_SUCCESS;
}

MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor)
{
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
    ma_result result;
    ma_uint64 cursor;

    if (pCursor == NULL) {
        return MA_INVALID_ARGS;
    }

    *pCursor = 0;

    if (pDataSourceBase == NULL) {
        return MA_SUCCESS;
    }

    if (pDataSourceBase->vtable->onGetCursor == NULL) {
        return MA_NOT_IMPLEMENTED;
    }

    result = pDataSourceBase->vtable->onGetCursor(pDataSourceBase, &cursor);
    if (result != MA_SUCCESS) {
        return result;
    }

    /* The cursor needs to be made relative to the start of the range. */
    if (cursor < pDataSourceBase->rangeBegInFrames) {   /* Safety check so we don't return some huge number. */
        *pCursor = 0;
    } else {
        *pCursor = cursor - pDataSourceBase->rangeBegInFrames;
    }

    return MA_SUCCESS;
}

MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength)
{
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;

    if (pLength == NULL) {
        return MA_INVALID_ARGS;
    }

    *pLength = 0;

    if (pDataSourceBase == NULL) {
        return MA_INVALID_ARGS;
    }

    /*
    If we have a range defined we'll use that to determine the length. This is one of rare times
    where we'll actually trust the caller. If they've set the range, I think it's mostly safe to
    assume they've set it based on some higher level knowledge of the structure of the sound bank.
    */
    if (pDataSourceBase->rangeEndInFrames != ~((ma_uint64)0)) {
        *pLength = pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames;
        return MA_SUCCESS;
    }

    /*
    Getting here means a range is not defined so we'll need to get the data source itself to tell
    us the length.
    */
    if (pDataSourceBase->vtable->onGetLength == NULL) {
        return MA_NOT_IMPLEMENTED;
    }

    return pDataSourceBase->vtable->onGetLength(pDataSource, pLength);
}

MA_API ma_result ma_data_source_get_cursor_in_seconds(ma_data_source* pDataSource, float* pCursor)
{
    ma_result result;
    ma_uint64 cursorInPCMFrames;
    ma_uint32 sampleRate;

    if (pCursor == NULL) {
        return MA_INVALID_ARGS;
    }

    *pCursor = 0;

    result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &cursorInPCMFrames);
    if (result != MA_SUCCESS) {
        return result;
    }

    result = ma_data_source_get_data_format(pDataSource, NULL, NULL, &sampleRate, NULL, 0);
    if (result != MA_SUCCESS) {
        return result;
    }

    *pCursor = cursorInPCMFrames / (float)sampleRate;

    return MA_SUCCESS;
}

MA_API ma_result ma_data_source_get_length_in_seconds(ma_data_source* pDataSource, float* pLength)
{
    ma_result result;
    ma_uint64 lengthInPCMFrames;
    ma_uint32 sampleRate;

    if (pLength == NULL) {
        return MA_INVALID_ARGS;
    }

    *pLength = 0;

    result = ma_data_source_get_length_in_pcm_frames(pDataSource, &lengthInPCMFrames);
    if (result != MA_SUCCESS) {
        return result;
    }

    result = ma_data_source_get_data_format(pDataSource, NULL, NULL, &sampleRate, NULL, 0);
    if (result != MA_SUCCESS) {
        return result;
    }

    *pLength = lengthInPCMFrames / (float)sampleRate;

    return MA_SUCCESS;
}

MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping)
{
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;

    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    c89atomic_exchange_32(&pDataSourceBase->isLooping, isLooping);

    /* If there's no callback for this just treat it as a successful no-op. */
    if (pDataSourceBase->vtable->onSetLooping == NULL) {
        return MA_SUCCESS;
    }

    return pDataSourceBase->vtable->onSetLooping(pDataSource, isLooping);
}

MA_API ma_bool32 ma_data_source_is_looping(const ma_data_source* pDataSource)
{
    const ma_data_source_base* pDataSourceBase = (const ma_data_source_base*)pDataSource;

    if (pDataSource == NULL) {
        return MA_FALSE;
    }

    return c89atomic_load_32(&pDataSourceBase->isLooping);
}

MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames)
{
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;
    ma_result result;
    ma_uint64 cursor;
    ma_uint64 loopBegAbsolute;
    ma_uint64 loopEndAbsolute;

    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if (rangeEndInFrames < rangeBegInFrames) {
        return MA_INVALID_ARGS; /* The end of the range must come after the beginning. */
    }

    /*
    The loop points need to be updated. We'll be storing the loop points relative to the range. We'll update
    these so that they maintain their absolute positioning. The loop points will then be clamped to the range.
    */
    loopBegAbsolute = pDataSourceBase->loopBegInFrames + pDataSourceBase->rangeBegInFrames;
    loopEndAbsolute = pDataSourceBase->loopEndInFrames + ((pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) ? pDataSourceBase->rangeBegInFrames : 0);

    pDataSourceBase->rangeBegInFrames = rangeBegInFrames;
    pDataSourceBase->rangeEndInFrames = rangeEndInFrames;

    /* Make the loop points relative again, and make sure they're clamped to within the range. */
    if (loopBegAbsolute > pDataSourceBase->rangeBegInFrames) {
        pDataSourceBase->loopBegInFrames = loopBegAbsolute - pDataSourceBase->rangeBegInFrames;
    } else {
        pDataSourceBase->loopBegInFrames = 0;
    }

    if (pDataSourceBase->loopBegInFrames > pDataSourceBase->rangeEndInFrames) {
        pDataSourceBase->loopBegInFrames = pDataSourceBase->rangeEndInFrames;
    }

    /* Only need to update the loop end point if it's not -1. */
    if (loopEndAbsolute != ~((ma_uint64)0)) {
        if (loopEndAbsolute > pDataSourceBase->rangeBegInFrames) {
            pDataSourceBase->loopEndInFrames = loopEndAbsolute - pDataSourceBase->rangeBegInFrames;
        } else {
            pDataSourceBase->loopEndInFrames = 0;
        }

        if (pDataSourceBase->loopEndInFrames > pDataSourceBase->rangeEndInFrames && pDataSourceBase->loopEndInFrames) {
            pDataSourceBase->loopEndInFrames = pDataSourceBase->rangeEndInFrames;
        }
    }


    /* If the new range is past the current cursor position we need to seek to it. */
    result = ma_data_source_get_cursor_in_pcm_frames(pDataSource, &cursor);
    if (result == MA_SUCCESS) {
        /* Seek to within range. Note that our seek positions here are relative to the new range. */
        if (cursor < rangeBegInFrames) {
            ma_data_source_seek_to_pcm_frame(pDataSource, 0);
        } else if (cursor > rangeEndInFrames) {
            ma_data_source_seek_to_pcm_frame(pDataSource, rangeEndInFrames - rangeBegInFrames);
        }
    } else {
        /* We failed to get the cursor position. Probably means the data source has no notion of a cursor such a noise data source. Just pretend the seeking worked. */
    }

    return MA_SUCCESS;
}

MA_API void ma_data_source_get_range_in_pcm_frames(const ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames)
{
    const ma_data_source_base* pDataSourceBase = (const ma_data_source_base*)pDataSource;

    if (pDataSource == NULL) {
        return;
    }

    if (pRangeBegInFrames != NULL) {
        *pRangeBegInFrames = pDataSourceBase->rangeBegInFrames;
    }

    if (pRangeEndInFrames != NULL) {
        *pRangeEndInFrames = pDataSourceBase->rangeEndInFrames;
    }
}

MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames)
{
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;

    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if (loopEndInFrames < loopBegInFrames) {
        return MA_INVALID_ARGS; /* The end of the loop point must come after the beginning. */
    }

    if (loopEndInFrames > pDataSourceBase->rangeEndInFrames && loopEndInFrames != ~((ma_uint64)0)) {
        return MA_INVALID_ARGS; /* The end of the loop point must not go beyond the range. */
    }

    pDataSourceBase->loopBegInFrames = loopBegInFrames;
    pDataSourceBase->loopEndInFrames = loopEndInFrames;

    /* The end cannot exceed the range. */
    if (pDataSourceBase->loopEndInFrames > (pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames) && pDataSourceBase->loopEndInFrames != ~((ma_uint64)0)) {
        pDataSourceBase->loopEndInFrames = (pDataSourceBase->rangeEndInFrames - pDataSourceBase->rangeBegInFrames);
    }

    return MA_SUCCESS;
}

MA_API void ma_data_source_get_loop_point_in_pcm_frames(const ma_data_source* pDataSource, ma_uint64* pLoopBegInFrames, ma_uint64* pLoopEndInFrames)
{
    const ma_data_source_base* pDataSourceBase = (const ma_data_source_base*)pDataSource;

    if (pDataSource == NULL) {
        return;
    }

    if (pLoopBegInFrames != NULL) {
        *pLoopBegInFrames = pDataSourceBase->loopBegInFrames;
    }

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

}

MA_API ma_result ma_data_source_set_next_callback(ma_data_source* pDataSource, ma_data_source_get_next_proc onGetNext)
{
    ma_data_source_base* pDataSourceBase = (ma_data_source_base*)pDataSource;

    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    pDataSourceBase->onGetNext = onGetNext;

    return MA_SUCCESS;
}

MA_API ma_data_source_get_next_proc ma_data_source_get_next_callback(const ma_data_source* pDataSource)
{
    const ma_data_source_base* pDataSourceBase = (const ma_data_source_base*)pDataSource;

    if (pDataSource == NULL) {
        return NULL;
    }

    return pDataSourceBase->onGetNext;
}


static ma_result ma_audio_buffer_ref__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;
    ma_uint64 framesRead = ma_audio_buffer_ref_read_pcm_frames(pAudioBufferRef, pFramesOut, frameCount, MA_FALSE);

    if (pFramesRead != NULL) {
        *pFramesRead = framesRead;
    }

    if (framesRead < frameCount || framesRead == 0) {
        return MA_AT_END;
    }

    return MA_SUCCESS;
}

static ma_result ma_audio_buffer_ref__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
    return ma_audio_buffer_ref_seek_to_pcm_frame((ma_audio_buffer_ref*)pDataSource, frameIndex);
}

static ma_result ma_audio_buffer_ref__data_source_on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
    ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;

    *pFormat     = pAudioBufferRef->format;
    *pChannels   = pAudioBufferRef->channels;
    *pSampleRate = pAudioBufferRef->sampleRate;
    ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pAudioBufferRef->channels);

    return MA_SUCCESS;
}

static ma_result ma_audio_buffer_ref__data_source_on_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
    ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;

    *pCursor = pAudioBufferRef->cursor;

    return MA_SUCCESS;
}

static ma_result ma_audio_buffer_ref__data_source_on_get_length(ma_data_source* pDataSource, ma_uint64* pLength)
{
    ma_audio_buffer_ref* pAudioBufferRef = (ma_audio_buffer_ref*)pDataSource;

    *pLength = pAudioBufferRef->sizeInFrames;

    return MA_SUCCESS;
}

static ma_data_source_vtable g_ma_audio_buffer_ref_data_source_vtable =
{
    ma_audio_buffer_ref__data_source_on_read,
    ma_audio_buffer_ref__data_source_on_seek,
    ma_audio_buffer_ref__data_source_on_get_data_format,
    ma_audio_buffer_ref__data_source_on_get_cursor,
    ma_audio_buffer_ref__data_source_on_get_length,
    NULL,   /* onSetLooping */
    0
};

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_result result;
    ma_data_source_config dataSourceConfig;

    if (pAudioBufferRef == NULL) {
        return MA_INVALID_ARGS;
    }

    MA_ZERO_OBJECT(pAudioBufferRef);

    dataSourceConfig = ma_data_source_config_init();
    dataSourceConfig.vtable = &g_ma_audio_buffer_ref_data_source_vtable;

    result = ma_data_source_init(&dataSourceConfig, &pAudioBufferRef->ds);
    if (result != MA_SUCCESS) {
        return result;
    }

    pAudioBufferRef->format       = format;
    pAudioBufferRef->channels     = channels;
    pAudioBufferRef->sampleRate   = 0;  /* TODO: Version 0.12. Set this to sampleRate. */
    pAudioBufferRef->cursor       = 0;
    pAudioBufferRef->sizeInFrames = sizeInFrames;
    pAudioBufferRef->pData        = pData;

    return MA_SUCCESS;
}

MA_API void ma_audio_buffer_ref_uninit(ma_audio_buffer_ref* pAudioBufferRef)
{
    if (pAudioBufferRef == NULL) {
        return;
    }

    ma_data_source_uninit(&pAudioBufferRef->ds);
}

MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames)
{
    if (pAudioBufferRef == NULL) {
        return MA_INVALID_ARGS;
    }

    pAudioBufferRef->cursor       = 0;
    pAudioBufferRef->sizeInFrames = sizeInFrames;
    pAudioBufferRef->pData        = pData;

    return MA_SUCCESS;
}

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_uint64 totalFramesRead = 0;

    if (pAudioBufferRef == NULL) {
        return 0;
    }

    if (frameCount == 0) {
        return 0;
    }

    while (totalFramesRead < frameCount) {
        ma_uint64 framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
        ma_uint64 framesRemaining = frameCount - totalFramesRead;
        ma_uint64 framesToRead;

        framesToRead = framesRemaining;
        if (framesToRead > framesAvailable) {
            framesToRead = framesAvailable;
        }

        if (pFramesOut != NULL) {
            ma_copy_pcm_frames(ma_offset_ptr(pFramesOut, totalFramesRead * ma_get_bytes_per_frame(pAudioBufferRef->format, pAudioBufferRef->channels)), ma_offset_ptr(pAudioBufferRef->pData, pAudioBufferRef->cursor * ma_get_bytes_per_frame(pAudioBuffe...
        }

        totalFramesRead += framesToRead;

        pAudioBufferRef->cursor += framesToRead;
        if (pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames) {
            if (loop) {
                pAudioBufferRef->cursor = 0;
            } else {
                break;  /* We've reached the end and we're not looping. Done. */
            }
        }

        MA_ASSERT(pAudioBufferRef->cursor < pAudioBufferRef->sizeInFrames);
    }

    return totalFramesRead;
}

MA_API ma_result ma_audio_buffer_ref_seek_to_pcm_frame(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameIndex)
{
    if (pAudioBufferRef == NULL) {
        return MA_INVALID_ARGS;
    }

    if (frameIndex > pAudioBufferRef->sizeInFrames) {
        return MA_INVALID_ARGS;
    }

    pAudioBufferRef->cursor = (size_t)frameIndex;

    return MA_SUCCESS;
}

MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref* pAudioBufferRef, void** ppFramesOut, ma_uint64* pFrameCount)
{
    ma_uint64 framesAvailable;
    ma_uint64 frameCount = 0;

    if (ppFramesOut != NULL) {
        *ppFramesOut = NULL;    /* Safety. */
    }

    if (pFrameCount != NULL) {
        frameCount = *pFrameCount;
        *pFrameCount = 0;       /* Safety. */
    }

    if (pAudioBufferRef == NULL || ppFramesOut == NULL || pFrameCount == NULL) {
        return MA_INVALID_ARGS;
    }

    framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
    if (frameCount > framesAvailable) {
        frameCount = framesAvailable;
    }

    *ppFramesOut = ma_offset_ptr(pAudioBufferRef->pData, pAudioBufferRef->cursor * ma_get_bytes_per_frame(pAudioBufferRef->format, pAudioBufferRef->channels));
    *pFrameCount = frameCount;

    return MA_SUCCESS;
}

MA_API ma_result ma_audio_buffer_ref_unmap(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameCount)
{
    ma_uint64 framesAvailable;

    if (pAudioBufferRef == NULL) {
        return MA_INVALID_ARGS;
    }

    framesAvailable = pAudioBufferRef->sizeInFrames - pAudioBufferRef->cursor;
    if (frameCount > framesAvailable) {
        return MA_INVALID_ARGS;   /* The frame count was too big. This should never happen in an unmapping. Need to make sure the caller is aware of this. */
    }

    pAudioBufferRef->cursor += frameCount;

    if (pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames) {
        return MA_AT_END;   /* Successful. Need to tell the caller that the end has been reached so that it can loop if desired. */
    } else {
        return MA_SUCCESS;
    }
}

MA_API ma_bool32 ma_audio_buffer_ref_at_end(const ma_audio_buffer_ref* pAudioBufferRef)
{
    if (pAudioBufferRef == NULL) {
        return MA_FALSE;
    }

    return pAudioBufferRef->cursor == pAudioBufferRef->sizeInFrames;
}

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. */
        }

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

}

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)
{
    if (ppFramesOut != NULL) {
        *ppFramesOut = NULL;    /* Safety. */
    }

    if (pAudioBuffer == NULL) {
        if (pFrameCount != NULL) {
            *pFrameCount = 0;
        }

        return MA_INVALID_ARGS;
    }

    return ma_audio_buffer_ref_map(&pAudioBuffer->ref, ppFramesOut, pFrameCount);
}

MA_API ma_result ma_audio_buffer_unmap(ma_audio_buffer* pAudioBuffer, ma_uint64 frameCount)
{
    if (pAudioBuffer == NULL) {
        return MA_INVALID_ARGS;
    }

    return ma_audio_buffer_ref_unmap(&pAudioBuffer->ref, frameCount);
}

MA_API ma_bool32 ma_audio_buffer_at_end(const ma_audio_buffer* pAudioBuffer)
{
    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;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

        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,
    ma_paged_audio_buffer__data_source_on_get_data_format,
    ma_paged_audio_buffer__data_source_on_get_cursor,
    ma_paged_audio_buffer__data_source_on_get_length,
    NULL,   /* onSetLooping */
    0
};

MA_API ma_result ma_paged_audio_buffer_init(const ma_paged_audio_buffer_config* pConfig, ma_paged_audio_buffer* pPagedAudioBuffer)
{
    ma_result result;
    ma_data_source_config dataSourceConfig;

    if (pPagedAudioBuffer == NULL) {
        return MA_INVALID_ARGS;
    }

    MA_ZERO_OBJECT(pPagedAudioBuffer);

    /* A config is required for the format and channel count. */
    if (pConfig == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pConfig->pData == NULL) {
        return MA_INVALID_ARGS; /* No underlying data specified. */
    }

    dataSourceConfig = ma_data_source_config_init();
    dataSourceConfig.vtable = &g_ma_paged_audio_buffer_data_source_vtable;

    result = ma_data_source_init(&dataSourceConfig, &pPagedAudioBuffer->ds);
    if (result != MA_SUCCESS) {
        return result;
    }

    pPagedAudioBuffer->pData          = pConfig->pData;
    pPagedAudioBuffer->pCurrent       = ma_paged_audio_buffer_data_get_head(pConfig->pData);
    pPagedAudioBuffer->relativeCursor = 0;
    pPagedAudioBuffer->absoluteCursor = 0;

    return MA_SUCCESS;
}

MA_API void ma_paged_audio_buffer_uninit(ma_paged_audio_buffer* pPagedAudioBuffer)
{
    if (pPagedAudioBuffer == NULL) {
        return;
    }

    /* Nothing to do. The data needs to be deleted separately. */
}

MA_API ma_result ma_paged_audio_buffer_read_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    ma_result result = MA_SUCCESS;
    ma_uint64 totalFramesRead = 0;
    ma_format format;
    ma_uint32 channels;

    if (pPagedAudioBuffer == NULL) {
        return MA_INVALID_ARGS;
    }

    format   = pPagedAudioBuffer->pData->format;
    channels = pPagedAudioBuffer->pData->channels;

    while (totalFramesRead < frameCount) {
        /* Read from the current page. The buffer should never be in a state where this is NULL. */
        ma_uint64 framesRemainingInCurrentPage;
        ma_uint64 framesRemainingToRead = frameCount - totalFramesRead;
        ma_uint64 framesToReadThisIteration;

        MA_ASSERT(pPagedAudioBuffer->pCurrent != NULL);

        framesRemainingInCurrentPage = pPagedAudioBuffer->pCurrent->sizeInFrames - pPagedAudioBuffer->relativeCursor;

        framesToReadThisIteration = ma_min(framesRemainingInCurrentPage, framesRemainingToRead);
        ma_copy_pcm_frames(ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, format, channels), ma_offset_pcm_frames_ptr(pPagedAudioBuffer->pCurrent->pAudioData, pPagedAudioBuffer->relativeCursor, format, channels), framesToReadThisIteration, for...
        totalFramesRead += framesToReadThisIteration;

        pPagedAudioBuffer->absoluteCursor += framesToReadThisIteration;
        pPagedAudioBuffer->relativeCursor += framesToReadThisIteration;

        /* Move to the next page if necessary. If there's no more pages, we need to return MA_AT_END. */
        MA_ASSERT(pPagedAudioBuffer->relativeCursor <= pPagedAudioBuffer->pCurrent->sizeInFrames);

        if (pPagedAudioBuffer->relativeCursor == pPagedAudioBuffer->pCurrent->sizeInFrames) {
            /* We reached the end of the page. Need to move to the next. If there's no more pages, we're done. */
            ma_paged_audio_buffer_page* pNext = (ma_paged_audio_buffer_page*)c89atomic_load_ptr(&pPagedAudioBuffer->pCurrent->pNext);
            if (pNext == NULL) {
                result = MA_AT_END;
                break;  /* We've reached the end. */
            } else {
                pPagedAudioBuffer->pCurrent       = pNext;
                pPagedAudioBuffer->relativeCursor = 0;
            }
        }
    }

    if (pFramesRead != NULL) {
        *pFramesRead = totalFramesRead;
    }

    return result;
}

MA_API ma_result ma_paged_audio_buffer_seek_to_pcm_frame(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64 frameIndex)
{
    if (pPagedAudioBuffer == NULL) {
        return MA_INVALID_ARGS;
    }

    if (frameIndex == pPagedAudioBuffer->absoluteCursor) {
        return MA_SUCCESS;  /* Nothing to do. */
    }

    if (frameIndex < pPagedAudioBuffer->absoluteCursor) {
        /* Moving backwards. Need to move the cursor back to the start, and then move forward. */
        pPagedAudioBuffer->pCurrent       = ma_paged_audio_buffer_data_get_head(pPagedAudioBuffer->pData);
        pPagedAudioBuffer->absoluteCursor = 0;
        pPagedAudioBuffer->relativeCursor = 0;

        /* Fall through to the forward seeking section below. */
    }

    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) {

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    } 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...

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

{
    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;
}

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    {
        /* wav is disabled. Should never hit this since initialization would have failed. */
        MA_ASSERT(MA_FALSE);

        (void)frameIndex;

        return MA_NOT_IMPLEMENTED;
    }
    #endif
}

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)
{
    /* Defaults for safety. */
    if (pFormat != NULL) {
        *pFormat = ma_format_unknown;
    }
    if (pChannels != NULL) {
        *pChannels = 0;
    }
    if (pSampleRate != NULL) {
        *pSampleRate = 0;
    }
    if (pChannelMap != NULL) {
        MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
    }

    if (pWav == NULL) {
        return MA_INVALID_OPERATION;
    }

    if (pFormat != NULL) {
        *pFormat = pWav->format;
    }

    #if !defined(MA_NO_WAV)
    {
        if (pChannels != NULL) {
            *pChannels = pWav->dr.channels;
        }

        if (pSampleRate != NULL) {
            *pSampleRate = pWav->dr.sampleRate;
        }

        if (pChannelMap != NULL) {
            ma_channel_map_init_standard(ma_standard_channel_map_microsoft, pChannelMap, channelMapCap, pWav->dr.channels);
        }

        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_cursor_in_pcm_frames(ma_wav* pWav, ma_uint64* pCursor)
{
    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);

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    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;
}

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    {
        /* flac is disabled. Should never hit this since initialization would have failed. */
        MA_ASSERT(MA_FALSE);

        (void)frameIndex;

        return MA_NOT_IMPLEMENTED;
    }
    #endif
}

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)
{
    /* Defaults for safety. */
    if (pFormat != NULL) {
        *pFormat = ma_format_unknown;
    }
    if (pChannels != NULL) {
        *pChannels = 0;
    }
    if (pSampleRate != NULL) {
        *pSampleRate = 0;
    }
    if (pChannelMap != NULL) {
        MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
    }

    if (pFlac == NULL) {
        return MA_INVALID_OPERATION;
    }

    if (pFormat != NULL) {
        *pFormat = pFlac->format;
    }

    #if !defined(MA_NO_FLAC)
    {
        if (pChannels != NULL) {
            *pChannels = pFlac->dr->channels;
        }

        if (pSampleRate != NULL) {
            *pSampleRate = pFlac->dr->sampleRate;
        }

        if (pChannelMap != NULL) {
            ma_channel_map_init_standard(ma_standard_channel_map_microsoft, pChannelMap, channelMapCap, pFlac->dr->channels);
        }

        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_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. */

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

        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;
}

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    {
        /* mp3 is disabled. Should never hit this since initialization would have failed. */
        MA_ASSERT(MA_FALSE);

        (void)frameIndex;

        return MA_NOT_IMPLEMENTED;
    }
    #endif
}

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)
{
    /* Defaults for safety. */
    if (pFormat != NULL) {
        *pFormat = ma_format_unknown;
    }
    if (pChannels != NULL) {
        *pChannels = 0;
    }
    if (pSampleRate != NULL) {
        *pSampleRate = 0;
    }
    if (pChannelMap != NULL) {
        MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
    }

    if (pMP3 == NULL) {
        return MA_INVALID_OPERATION;
    }

    if (pFormat != NULL) {
        *pFormat = pMP3->format;
    }

    #if !defined(MA_NO_MP3)
    {
        if (pChannels != NULL) {
            *pChannels = pMP3->dr.channels;
        }

        if (pSampleRate != NULL) {
            *pSampleRate = pMP3->dr.sampleRate;
        }

        if (pChannelMap != NULL) {
            ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pMP3->dr.channels);
        }

        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_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. */

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    /* 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. */
    }

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

                            pVorbis->push.framesConsumed  = 0;
                            pVorbis->push.framesRemaining = samplesRead;

                            break;
                        } else {
                            /* Not enough data. Read more. */
                            size_t bytesRead;

                            /* Expand the data buffer if necessary. */
                            if (pVorbis->push.dataCapacity == pVorbis->push.dataSize) {
                                size_t newCap = pVorbis->push.dataCapacity + MA_VORBIS_DATA_CHUNK_SIZE;
                                ma_uint8* pNewData;

                                pNewData = (ma_uint8*)ma_realloc(pVorbis->push.pData, newCap, &pVorbis->allocationCallbacks);
                                if (pNewData == NULL) {
                                    result = MA_OUT_OF_MEMORY;
                                    break;
                                }

                                pVorbis->push.pData = pNewData;
                                pVorbis->push.dataCapacity = newCap;
                            }

                            /* We should have enough room to load some data. */
                            result = pVorbis->onRead(pVorbis->pReadSeekTellUserData, ma_offset_ptr(pVorbis->push.pData, pVorbis->push.dataSize), (pVorbis->push.dataCapacity - pVorbis->push.dataSize), &bytesRead);
                            pVorbis->push.dataSize += bytesRead;

                            if (result != MA_SUCCESS) {
                                break;  /* Failed to read any data. Get out. */
                            }
                        }
                    }

                    /* If we don't have a success code at this point it means we've encounted an error or the end of the file has been reached (probably the latter). */
                    if (result != MA_SUCCESS) {
                        break;
                    }
                }
            } else {
                /* Pull mode. This is the simple case, but we still need to run in a loop because stb_vorbis loves using 32-bit instead of 64-bit. */
                while (totalFramesRead < frameCount) {
                    ma_uint64 framesRemaining = (frameCount - totalFramesRead);
                    int framesRead;

                    if (framesRemaining > INT_MAX) {
                        framesRemaining = INT_MAX;
                    }

                    framesRead = stb_vorbis_get_samples_float_interleaved(pVorbis->stb, channels, (float*)ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, format, channels), (int)framesRemaining * channels);   /* Safe cast. */
                    totalFramesRead += framesRead;

                    if (framesRead < (int)framesRemaining) {
                        break;  /* Nothing left to read. Get out. */
                    }
                }
            }
        } else {
            result = MA_INVALID_ARGS;
        }

        pVorbis->cursor += totalFramesRead;

        if (totalFramesRead == 0) {
            result = MA_AT_END;
        }

        if (pFramesRead != NULL) {
            *pFramesRead = totalFramesRead;
        }

        if (result == MA_SUCCESS && totalFramesRead == 0) {
            result  = MA_AT_END;
        }

        return result;
    }
    #else
    {
        /* vorbis is disabled. Should never hit this since initialization would have failed. */
        MA_ASSERT(MA_FALSE);

        (void)pFramesOut;
        (void)frameCount;
        (void)pFramesRead;

        return MA_NOT_IMPLEMENTED;
    }
    #endif
}

MA_API ma_result ma_stbvorbis_seek_to_pcm_frame(ma_stbvorbis* pVorbis, ma_uint64 frameIndex)
{
    if (pVorbis == NULL) {
        return MA_INVALID_ARGS;
    }

    #if !defined(MA_NO_VORBIS)
    {
        /* Different seeking methods depending on whether or not we're using push mode. */
        if (pVorbis->usingPushMode) {
            /* Push mode. This is the complex case. */
            ma_result result;
            float buffer[4096];

            /*
            This is terribly inefficient because stb_vorbis does not have a good seeking solution with it's push API. Currently this just performs
            a full decode right from the start of the stream. Later on I'll need to write a layer that goes through all of the Ogg pages until we
            find the one containing the sample we need. Then we know exactly where to seek for stb_vorbis.

            TODO: Use seeking logic documented for stb_vorbis_flush_pushdata().
            */

            /* Seek to the start of the file to begin with. */
            result = pVorbis->onSeek(pVorbis->pReadSeekTellUserData, 0, ma_seek_origin_start);
            if (result != MA_SUCCESS) {
                return result;
            }

            stb_vorbis_flush_pushdata(pVorbis->stb);
            pVorbis->push.framesRemaining = 0;
            pVorbis->push.dataSize        = 0;

            /* Move the cursor back to the start. We'll increment this in the loop below. */
            pVorbis->cursor = 0;

            while (pVorbis->cursor < frameIndex) {
                ma_uint64 framesRead;
                ma_uint64 framesToRead = ma_countof(buffer)/pVorbis->channels;
                if (framesToRead > (frameIndex - pVorbis->cursor)) {
                    framesToRead = (frameIndex - pVorbis->cursor);
                }

                result = ma_stbvorbis_read_pcm_frames(pVorbis, buffer, framesToRead, &framesRead);
                pVorbis->cursor += framesRead;

                if (result != MA_SUCCESS) {
                    return result;
                }
            }
        } else {
            /* Pull mode. This is the simple case. */
            int vorbisResult;

            if (frameIndex > UINT_MAX) {
                return MA_INVALID_ARGS; /* Trying to seek beyond the 32-bit maximum of stb_vorbis. */
            }

            vorbisResult = stb_vorbis_seek(pVorbis->stb, (unsigned int)frameIndex);  /* Safe cast. */
            if (vorbisResult == 0) {
                return MA_ERROR;    /* See failed. */
            }

            pVorbis->cursor = frameIndex;
        }

        return MA_SUCCESS;
    }
    #else
    {
        /* vorbis is disabled. Should never hit this since initialization would have failed. */
        MA_ASSERT(MA_FALSE);

        (void)frameIndex;

        return MA_NOT_IMPLEMENTED;
    }
    #endif
}

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)
{
    /* Defaults for safety. */
    if (pFormat != NULL) {
        *pFormat = ma_format_unknown;
    }
    if (pChannels != NULL) {
        *pChannels = 0;
    }
    if (pSampleRate != NULL) {
        *pSampleRate = 0;
    }
    if (pChannelMap != NULL) {
        MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
    }

    if (pVorbis == NULL) {
        return MA_INVALID_OPERATION;
    }

    if (pFormat != NULL) {
        *pFormat = pVorbis->format;
    }

    #if !defined(MA_NO_VORBIS)
    {
        if (pChannels != NULL) {
            *pChannels = pVorbis->channels;
        }

        if (pSampleRate != NULL) {
            *pSampleRate = pVorbis->sampleRate;
        }

        if (pChannelMap != NULL) {
            ma_channel_map_init_standard(ma_standard_channel_map_vorbis, pChannelMap, channelMapCap, pVorbis->channels);
        }

        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_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);

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN


    *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;
}


share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

                    At this point we have our decoded data in input format and now we need to convert to output format. Note that even if we didn't read any
                    input frames, we still want to try processing frames because there may some output frames generated from cached input data.
                    */
                    framesReadThisIterationOut = framesToReadThisIterationOut;
                    result = ma_data_converter_process_pcm_frames(&pDecoder->converter, pIntermediaryBuffer, &framesReadThisIterationIn, pRunningFramesOut, &framesReadThisIterationOut);
                    if (result != MA_SUCCESS) {
                        break;
                    }

                    totalFramesReadOut += framesReadThisIterationOut;

                    if (pRunningFramesOut != NULL) {
                        pRunningFramesOut = ma_offset_ptr(pRunningFramesOut, framesReadThisIterationOut * ma_get_bytes_per_frame(pDecoder->outputFormat, pDecoder->outputChannels));
                    }

                    if (framesReadThisIterationIn == 0 && framesReadThisIterationOut == 0) {
                        break;  /* We're done. */
                    }
                }
            }
        }
    }

    pDecoder->readPointerInPCMFrames += totalFramesReadOut;

    if (pFramesRead != NULL) {
        *pFramesRead = totalFramesReadOut;
    }

    if (result == MA_SUCCESS && totalFramesReadOut == 0) {
        result =  MA_AT_END;
    }

    return result;
}

MA_API ma_result ma_decoder_seek_to_pcm_frame(ma_decoder* pDecoder, ma_uint64 frameIndex)
{
    if (pDecoder == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pDecoder->pBackend != NULL) {
        ma_result result;
        ma_uint64 internalFrameIndex;
        ma_uint32 internalSampleRate;
        ma_uint64 currentFrameIndex;

        result = ma_data_source_get_data_format(pDecoder->pBackend, NULL, NULL, &internalSampleRate, NULL, 0);
        if (result != MA_SUCCESS) {
            return result;  /* Failed to retrieve the internal sample rate. */
        }

        if (internalSampleRate == pDecoder->outputSampleRate) {
            internalFrameIndex = frameIndex;
        } else {
            internalFrameIndex = ma_calculate_frame_count_after_resampling(internalSampleRate, pDecoder->outputSampleRate, frameIndex);
        }

        /* Only seek if we're requesting a different frame to what we're currently sitting on. */
        ma_data_source_get_cursor_in_pcm_frames(pDecoder->pBackend, &currentFrameIndex);
        if (currentFrameIndex != internalFrameIndex) {
            result = ma_data_source_seek_to_pcm_frame(pDecoder->pBackend, internalFrameIndex);
            if (result == MA_SUCCESS) {
                pDecoder->readPointerInPCMFrames = frameIndex;
            }

            /* Reset the data converter so that any cached data in the resampler is cleared. */
            ma_data_converter_reset(&pDecoder->converter);
        }

        return result;
    }

    /* Should never get here, but if we do it means onSeekToPCMFrame was not set by the backend. */
    return MA_INVALID_ARGS;
}

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)
{
    if (pDecoder == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pFormat != NULL) {
        *pFormat = pDecoder->outputFormat;
    }

    if (pChannels != NULL) {
        *pChannels = pDecoder->outputChannels;
    }

    if (pSampleRate != NULL) {
        *pSampleRate = pDecoder->outputSampleRate;
    }

    if (pChannelMap != NULL) {
        ma_data_converter_get_output_channel_map(&pDecoder->converter, pChannelMap, channelMapCap);
    }

    return MA_SUCCESS;
}

MA_API ma_result ma_decoder_get_cursor_in_pcm_frames(ma_decoder* pDecoder, ma_uint64* pCursor)
{
    if (pCursor == NULL) {
        return MA_INVALID_ARGS;
    }

    *pCursor = 0;

    if (pDecoder == NULL) {
        return MA_INVALID_ARGS;
    }

    *pCursor = pDecoder->readPointerInPCMFrames;

    return MA_SUCCESS;
}

MA_API ma_result ma_decoder_get_length_in_pcm_frames(ma_decoder* pDecoder, ma_uint64* pLength)
{
    if (pLength == NULL) {
        return MA_INVALID_ARGS;
    }

    *pLength = 0;

    if (pDecoder == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pDecoder->pBackend != NULL) {
        ma_result result;
        ma_uint64 internalLengthInPCMFrames;
        ma_uint32 internalSampleRate;

        result = ma_data_source_get_length_in_pcm_frames(pDecoder->pBackend, &internalLengthInPCMFrames);
        if (result != MA_SUCCESS) {
            return result;  /* Failed to retrieve the internal length. */
        }

        result = ma_data_source_get_data_format(pDecoder->pBackend, NULL, NULL, &internalSampleRate, NULL, 0);
        if (result != MA_SUCCESS) {
            return result;   /* Failed to retrieve the internal sample rate. */
        }

        if (internalSampleRate == pDecoder->outputSampleRate) {
            *pLength = internalLengthInPCMFrames;
        } else {
            *pLength = ma_calculate_frame_count_after_resampling(pDecoder->outputSampleRate, internalSampleRate, internalLengthInPCMFrames);
        }

        return MA_SUCCESS;
    } else {
        return MA_NO_BACKEND;
    }
}

MA_API ma_result ma_decoder_get_available_frames(ma_decoder* pDecoder, ma_uint64* pAvailableFrames)
{
    ma_result result;
    ma_uint64 totalFrameCount;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN


MA_API ma_result ma_encoder_write_pcm_frames(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount, ma_uint64* pFramesWritten)
{
    if (pFramesWritten != NULL) {
        *pFramesWritten = 0;
    }

    if (pEncoder == NULL || pFramesIn == NULL) {
        return MA_INVALID_ARGS;
    }

    return pEncoder->onWritePCMFrames(pEncoder, pFramesIn, frameCount, pFramesWritten);
}
#endif  /* MA_NO_ENCODING */



/**************************************************************************************************************************************************************

Generation

**************************************************************************************************************************************************************/
#ifndef MA_NO_GENERATION
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)
{
    ma_waveform_config config;

    MA_ZERO_OBJECT(&config);
    config.format     = format;
    config.channels   = channels;
    config.sampleRate = sampleRate;
    config.type       = type;
    config.amplitude  = amplitude;
    config.frequency  = frequency;

    return config;
}

static ma_result ma_waveform__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    return ma_waveform_read_pcm_frames((ma_waveform*)pDataSource, pFramesOut, frameCount, pFramesRead);
}

static ma_result ma_waveform__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
    return ma_waveform_seek_to_pcm_frame((ma_waveform*)pDataSource, frameIndex);
}

static ma_result ma_waveform__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_waveform* pWaveform = (ma_waveform*)pDataSource;

    *pFormat     = pWaveform->config.format;
    *pChannels   = pWaveform->config.channels;
    *pSampleRate = pWaveform->config.sampleRate;
    ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pWaveform->config.channels);

    return MA_SUCCESS;
}

static ma_result ma_waveform__data_source_on_get_cursor(ma_data_source* pDataSource, ma_uint64* pCursor)
{
    ma_waveform* pWaveform = (ma_waveform*)pDataSource;

    *pCursor = (ma_uint64)(pWaveform->time / pWaveform->advance);

    return MA_SUCCESS;
}

static double ma_waveform__calculate_advance(ma_uint32 sampleRate, double frequency)
{
    return (1.0 / (sampleRate / frequency));
}

static void ma_waveform__update_advance(ma_waveform* pWaveform)
{
    pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
}

static ma_data_source_vtable g_ma_waveform_data_source_vtable =
{
    ma_waveform__data_source_on_read,
    ma_waveform__data_source_on_seek,
    ma_waveform__data_source_on_get_data_format,
    ma_waveform__data_source_on_get_cursor,
    NULL,   /* onGetLength. There's no notion of a length in waveforms. */
    NULL,   /* onSetLooping */
    0
};

MA_API ma_result ma_waveform_init(const ma_waveform_config* pConfig, ma_waveform* pWaveform)
{
    ma_result result;
    ma_data_source_config dataSourceConfig;

    if (pWaveform == NULL) {
        return MA_INVALID_ARGS;
    }

    MA_ZERO_OBJECT(pWaveform);

    dataSourceConfig = ma_data_source_config_init();
    dataSourceConfig.vtable = &g_ma_waveform_data_source_vtable;

    result = ma_data_source_init(&dataSourceConfig, &pWaveform->ds);
    if (result != MA_SUCCESS) {
        return result;
    }

    pWaveform->config  = *pConfig;
    pWaveform->advance = ma_waveform__calculate_advance(pWaveform->config.sampleRate, pWaveform->config.frequency);
    pWaveform->time    = 0;

    return MA_SUCCESS;
}

MA_API void ma_waveform_uninit(ma_waveform* pWaveform)
{
    if (pWaveform == NULL) {
        return;
    }

    ma_data_source_uninit(&pWaveform->ds);
}

MA_API ma_result ma_waveform_set_amplitude(ma_waveform* pWaveform, double amplitude)
{
    if (pWaveform == NULL) {
        return MA_INVALID_ARGS;
    }

    pWaveform->config.amplitude = amplitude;
    return MA_SUCCESS;
}

MA_API ma_result ma_waveform_set_frequency(ma_waveform* pWaveform, double frequency)
{
    if (pWaveform == NULL) {
        return MA_INVALID_ARGS;
    }

    pWaveform->config.frequency = frequency;
    ma_waveform__update_advance(pWaveform);

    return MA_SUCCESS;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

{
    if (pWaveform == NULL) {
        return MA_INVALID_ARGS;
    }

    pWaveform->time = pWaveform->advance * (ma_int64)frameIndex;    /* Casting for VC6. Won't be an issue in practice. */

    return MA_SUCCESS;
}


MA_API ma_noise_config ma_noise_config_init(ma_format format, ma_uint32 channels, ma_noise_type type, ma_int32 seed, double amplitude)
{
    ma_noise_config config;
    MA_ZERO_OBJECT(&config);

    config.format    = format;
    config.channels  = channels;
    config.type      = type;
    config.seed      = seed;
    config.amplitude = amplitude;

    if (config.seed == 0) {
        config.seed = MA_DEFAULT_LCG_SEED;
    }

    return config;
}


static ma_result ma_noise__data_source_on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    return ma_noise_read_pcm_frames((ma_noise*)pDataSource, pFramesOut, frameCount, pFramesRead);
}

static ma_result ma_noise__data_source_on_seek(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
    /* No-op. Just pretend to be successful. */
    (void)pDataSource;
    (void)frameIndex;
    return MA_SUCCESS;
}

static ma_result ma_noise__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_noise* pNoise = (ma_noise*)pDataSource;

    *pFormat     = pNoise->config.format;
    *pChannels   = pNoise->config.channels;
    *pSampleRate = 0;   /* There is no notion of sample rate with noise generation. */
    ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pNoise->config.channels);

    return MA_SUCCESS;
}

static ma_data_source_vtable g_ma_noise_data_source_vtable =
{
    ma_noise__data_source_on_read,
    ma_noise__data_source_on_seek,  /* No-op for noise. */
    ma_noise__data_source_on_get_data_format,
    NULL,   /* onGetCursor. No notion of a cursor for noise. */
    NULL,   /* onGetLength. No notion of a length for noise. */
    NULL,   /* onSetLooping */
    0
};


#ifndef MA_PINK_NOISE_BIN_SIZE
#define MA_PINK_NOISE_BIN_SIZE 16
#endif

typedef struct
{
    size_t sizeInBytes;
    struct
    {
        size_t binOffset;
        size_t accumulationOffset;
        size_t counterOffset;
    } pink;
    struct
    {
        size_t accumulationOffset;
    } brownian;
} ma_noise_heap_layout;

static ma_result ma_noise_get_heap_layout(const ma_noise_config* pConfig, ma_noise_heap_layout* pHeapLayout)
{
    MA_ASSERT(pHeapLayout != NULL);

    MA_ZERO_OBJECT(pHeapLayout);

    if (pConfig == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pConfig->channels == 0) {
        return MA_INVALID_ARGS;
    }

    pHeapLayout->sizeInBytes = 0;

    /* Pink. */
    if (pConfig->type == ma_noise_type_pink) {
        /* bin */
        pHeapLayout->pink.binOffset = pHeapLayout->sizeInBytes;
        pHeapLayout->sizeInBytes += sizeof(double*) * pConfig->channels;
        pHeapLayout->sizeInBytes += sizeof(double ) * pConfig->channels * MA_PINK_NOISE_BIN_SIZE;

        /* accumulation */
        pHeapLayout->pink.accumulationOffset = pHeapLayout->sizeInBytes;
        pHeapLayout->sizeInBytes += sizeof(double) * pConfig->channels;

        /* counter */
        pHeapLayout->pink.counterOffset = pHeapLayout->sizeInBytes;
        pHeapLayout->sizeInBytes += sizeof(ma_uint32) * pConfig->channels;
    }

    /* Brownian. */
    if (pConfig->type == ma_noise_type_brownian) {
        /* accumulation */

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

                    pFramesOutF32[iFrame*channels + iChannel] = ma_noise_f32_brownian(pNoise, iChannel);
                }
            }
        }
    } else if (pNoise->config.format == ma_format_s16) {
        ma_int16* pFramesOutS16 = (ma_int16*)pFramesOut;
        if (pNoise->config.duplicateChannels) {
            for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
                ma_int16 s = ma_noise_s16_brownian(pNoise, 0);
                for (iChannel = 0; iChannel < channels; iChannel += 1) {
                    pFramesOutS16[iFrame*channels + iChannel] = s;
                }
            }
        } else {
            for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
                for (iChannel = 0; iChannel < channels; iChannel += 1) {
                    pFramesOutS16[iFrame*channels + iChannel] = ma_noise_s16_brownian(pNoise, iChannel);
                }
            }
        }
    } else {
        const ma_uint32 bps = ma_get_bytes_per_sample(pNoise->config.format);
        const ma_uint32 bpf = bps * channels;

        if (pNoise->config.duplicateChannels) {
            for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
                float s = ma_noise_f32_brownian(pNoise, 0);
                for (iChannel = 0; iChannel < channels; iChannel += 1) {
                    ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
                }
            }
        } else {
            for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
                for (iChannel = 0; iChannel < channels; iChannel += 1) {
                    float s = ma_noise_f32_brownian(pNoise, iChannel);
                    ma_pcm_convert(ma_offset_ptr(pFramesOut, iFrame*bpf + iChannel*bps), pNoise->config.format, &s, ma_format_f32, 1, ma_dither_mode_none);
                }
            }
        }
    }

    return frameCount;
}

MA_API ma_result ma_noise_read_pcm_frames(ma_noise* pNoise, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    ma_uint64 framesRead = 0;

    if (pFramesRead != NULL) {
        *pFramesRead = 0;
    }

    if (frameCount == 0) {
        return MA_INVALID_ARGS;
    }

    if (pNoise == NULL) {
        return MA_INVALID_ARGS;
    }

    /* The output buffer is allowed to be NULL. Since we aren't tracking cursors or anything we can just do nothing and pretend to be successful. */
    if (pFramesOut == NULL) {
        framesRead = frameCount;
    } else {
        switch (pNoise->config.type) {
            case ma_noise_type_white:    framesRead = ma_noise_read_pcm_frames__white   (pNoise, pFramesOut, frameCount); break;
            case ma_noise_type_pink:     framesRead = ma_noise_read_pcm_frames__pink    (pNoise, pFramesOut, frameCount); break;
            case ma_noise_type_brownian: framesRead = ma_noise_read_pcm_frames__brownian(pNoise, pFramesOut, frameCount); break;
            default: return MA_INVALID_OPERATION;   /* Unknown noise type. */
        }
    }

    if (pFramesRead != NULL) {
        *pFramesRead = framesRead;
    }

    return MA_SUCCESS;
}
#endif /* MA_NO_GENERATION */



#ifndef MA_NO_RESOURCE_MANAGER
#ifndef MA_RESOURCE_MANAGER_PAGE_SIZE_IN_MILLISECONDS
#define MA_RESOURCE_MANAGER_PAGE_SIZE_IN_MILLISECONDS   1000
#endif

#ifndef MA_JOB_TYPE_RESOURCE_MANAGER_QUEUE_CAPACITY
#define MA_JOB_TYPE_RESOURCE_MANAGER_QUEUE_CAPACITY          1024
#endif

MA_API ma_resource_manager_pipeline_notifications ma_resource_manager_pipeline_notifications_init(void)
{
    ma_resource_manager_pipeline_notifications notifications;

    MA_ZERO_OBJECT(&notifications);

    return notifications;
}

static void ma_resource_manager_pipeline_notifications_signal_all_notifications(const ma_resource_manager_pipeline_notifications* pPipelineNotifications)
{
    if (pPipelineNotifications == NULL) {
        return;
    }

    if (pPipelineNotifications->init.pNotification) { ma_async_notification_signal(pPipelineNotifications->init.pNotification); }
    if (pPipelineNotifications->done.pNotification) { ma_async_notification_signal(pPipelineNotifications->done.pNotification); }
}

static void ma_resource_manager_pipeline_notifications_acquire_all_fences(const ma_resource_manager_pipeline_notifications* pPipelineNotifications)
{
    if (pPipelineNotifications == NULL) {
        return;
    }

    if (pPipelineNotifications->init.pFence != NULL) { ma_fence_acquire(pPipelineNotifications->init.pFence); }
    if (pPipelineNotifications->done.pFence != NULL) { ma_fence_acquire(pPipelineNotifications->done.pFence); }
}

static void ma_resource_manager_pipeline_notifications_release_all_fences(const ma_resource_manager_pipeline_notifications* pPipelineNotifications)

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

            ma_job job;

            /* We need to mark the node as unavailable for the sake of the resource manager worker threads. */
            c89atomic_exchange_i32(&pDataBufferNode->result, MA_UNAVAILABLE);

            job = ma_job_init(MA_JOB_TYPE_RESOURCE_MANAGER_FREE_DATA_BUFFER_NODE);
            job.order = ma_resource_manager_data_buffer_node_next_execution_order(pDataBufferNode);
            job.data.resourceManager.freeDataBufferNode.pResourceManager = pResourceManager;
            job.data.resourceManager.freeDataBufferNode.pDataBufferNode  = pDataBufferNode;

            result = ma_resource_manager_post_job(pResourceManager, &job);
            if (result != MA_SUCCESS) {
                ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to post MA_JOB_TYPE_RESOURCE_MANAGER_FREE_DATA_BUFFER_NODE job. %s.\n", ma_result_description(result));
                return result;
            }

            /* If we don't support threading, process the job queue here. */
            if (ma_resource_manager_is_threading_enabled(pResourceManager) == MA_FALSE) {
                while (ma_resource_manager_data_buffer_node_result(pDataBufferNode) == MA_BUSY) {
                    result = ma_resource_manager_process_next_job(pResourceManager);
                    if (result == MA_NO_DATA_AVAILABLE || result == MA_CANCELLED) {
                        result = MA_SUCCESS;
                        break;
                    }
                }
            } else {
                /* Threading is enabled. The job queue will deal with the rest of the cleanup from here. */
            }
        } else {
            /* The sound isn't loading so we can just free the node here. */
            ma_resource_manager_data_buffer_node_free(pResourceManager, pDataBufferNode);
        }
    }

    return result;
}



static ma_uint32 ma_resource_manager_data_buffer_next_execution_order(ma_resource_manager_data_buffer* pDataBuffer)
{
    MA_ASSERT(pDataBuffer != NULL);
    return c89atomic_fetch_add_32(&pDataBuffer->executionCounter, 1);
}

static ma_result ma_resource_manager_data_buffer_cb__read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    return ma_resource_manager_data_buffer_read_pcm_frames((ma_resource_manager_data_buffer*)pDataSource, pFramesOut, frameCount, pFramesRead);
}

static ma_result ma_resource_manager_data_buffer_cb__seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
    return ma_resource_manager_data_buffer_seek_to_pcm_frame((ma_resource_manager_data_buffer*)pDataSource, frameIndex);
}

static ma_result ma_resource_manager_data_buffer_cb__get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
    return ma_resource_manager_data_buffer_get_data_format((ma_resource_manager_data_buffer*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}

static ma_result ma_resource_manager_data_buffer_cb__get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor)
{
    return ma_resource_manager_data_buffer_get_cursor_in_pcm_frames((ma_resource_manager_data_buffer*)pDataSource, pCursor);
}

static ma_result ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength)
{
    return ma_resource_manager_data_buffer_get_length_in_pcm_frames((ma_resource_manager_data_buffer*)pDataSource, pLength);
}

static ma_result ma_resource_manager_data_buffer_cb__set_looping(ma_data_source* pDataSource, ma_bool32 isLooping)
{
    ma_resource_manager_data_buffer* pDataBuffer = (ma_resource_manager_data_buffer*)pDataSource;
    MA_ASSERT(pDataBuffer != NULL);

    c89atomic_exchange_32(&pDataBuffer->isLooping, isLooping);

    /* The looping state needs to be set on the connector as well or else looping won't work when we read audio data. */
    ma_data_source_set_looping(ma_resource_manager_data_buffer_get_connector(pDataBuffer), isLooping);

    return MA_SUCCESS;
}

static ma_data_source_vtable g_ma_resource_manager_data_buffer_vtable =
{
    ma_resource_manager_data_buffer_cb__read_pcm_frames,
    ma_resource_manager_data_buffer_cb__seek_to_pcm_frame,
    ma_resource_manager_data_buffer_cb__get_data_format,
    ma_resource_manager_data_buffer_cb__get_cursor_in_pcm_frames,
    ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames,
    ma_resource_manager_data_buffer_cb__set_looping,
    0
};

static ma_result ma_resource_manager_data_buffer_init_ex_internal(ma_resource_manager* pResourceManager, const ma_resource_manager_data_source_config* pConfig, ma_uint32 hashedName32, ma_resource_manager_data_buffer* pDataBuffer)
{
    ma_result result = MA_SUCCESS;
    ma_resource_manager_data_buffer_node* pDataBufferNode;
    ma_data_source_config dataSourceConfig;
    ma_bool32 async;
    ma_uint32 flags;
    ma_resource_manager_pipeline_notifications notifications;

    if (pDataBuffer == NULL) {
        if (pConfig != NULL && pConfig->pNotifications != NULL) {
            ma_resource_manager_pipeline_notifications_signal_all_notifications(pConfig->pNotifications);
        }

        return MA_INVALID_ARGS;
    }

    MA_ZERO_OBJECT(pDataBuffer);

    if (pConfig == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pConfig->pNotifications != NULL) {
        notifications = *pConfig->pNotifications;   /* From here on out we should be referencing `notifications` instead of `pNotifications`. Set this to NULL to catch errors at testing time. */
    } else {
        MA_ZERO_OBJECT(&notifications);
    }

    /* For safety, always remove the ASYNC flag if threading is disabled on the resource manager. */
    flags = pConfig->flags;
    if (ma_resource_manager_is_threading_enabled(pResourceManager) == MA_FALSE) {
        flags &= ~MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC;
    }

    async = (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC) != 0;

    /*
    Fences need to be acquired before doing anything. These must be aquired and released outside of
    the node to ensure there's no holes where ma_fence_wait() could prematurely return before the
    data buffer has completed initialization.

    When loading asynchronously, the node acquisition routine below will acquire the fences on this
    thread and then release them on the async thread when the operation is complete.

    These fences are always released at the "done" tag at the end of this function. They'll be
    acquired a second if loading asynchronously. This double acquisition system is just done to
    simplify code maintanence.
    */
    ma_resource_manager_pipeline_notifications_acquire_all_fences(&notifications);
    {
        /* We first need to acquire a node. If ASYNC is not set, this will not return until the entire sound has been loaded. */
        result = ma_resource_manager_data_buffer_node_acquire(pResourceManager, pConfig->pFilePath, pConfig->pFilePathW, hashedName32, flags, NULL, notifications.init.pFence, notifications.done.pFence, &pDataBufferNode);
        if (result != MA_SUCCESS) {
            ma_resource_manager_pipeline_notifications_signal_all_notifications(&notifications);

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_unknown) {
        pDataBuffer->seekTargetInPCMFrames = frameIndex;
        pDataBuffer->seekToCursorOnNextRead = MA_TRUE;
        return MA_BUSY; /* Still loading. */
    }

    result = ma_data_source_seek_to_pcm_frame(ma_resource_manager_data_buffer_get_connector(pDataBuffer), frameIndex);
    if (result != MA_SUCCESS) {
        return result;
    }

    pDataBuffer->seekTargetInPCMFrames = ~(ma_uint64)0; /* <-- For identification purposes. */
    pDataBuffer->seekToCursorOnNextRead = MA_FALSE;

    return MA_SUCCESS;
}

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)
{
    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) != MA_UNAVAILABLE);

    switch (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode))
    {
        case ma_resource_manager_data_supply_type_encoded:
        {
            return ma_data_source_get_data_format(&pDataBuffer->connector.decoder, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
        };

        case ma_resource_manager_data_supply_type_decoded:
        {
            *pFormat     = pDataBuffer->pNode->data.backend.decoded.format;
            *pChannels   = pDataBuffer->pNode->data.backend.decoded.channels;
            *pSampleRate = pDataBuffer->pNode->data.backend.decoded.sampleRate;
            ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pDataBuffer->pNode->data.backend.decoded.channels);
            return MA_SUCCESS;
        };

        case ma_resource_manager_data_supply_type_decoded_paged:
        {
            *pFormat     = pDataBuffer->pNode->data.backend.decodedPaged.data.format;
            *pChannels   = pDataBuffer->pNode->data.backend.decodedPaged.data.channels;
            *pSampleRate = pDataBuffer->pNode->data.backend.decodedPaged.sampleRate;
            ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pDataBuffer->pNode->data.backend.decoded.channels);
            return MA_SUCCESS;
        };

        case ma_resource_manager_data_supply_type_unknown:
        {
            return MA_BUSY; /* Still loading. */
        };

        default:
        {
            /* Unknown supply type. Should never hit this. */
            return MA_INVALID_ARGS;
        }
    }
}

MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pCursor)
{
    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) != MA_UNAVAILABLE);

    if (pDataBuffer == NULL || pCursor == NULL) {
        return MA_INVALID_ARGS;
    }

    *pCursor = 0;

    switch (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode))
    {
        case ma_resource_manager_data_supply_type_encoded:
        {
            return ma_decoder_get_cursor_in_pcm_frames(&pDataBuffer->connector.decoder, pCursor);
        };

        case ma_resource_manager_data_supply_type_decoded:
        {
            return ma_audio_buffer_get_cursor_in_pcm_frames(&pDataBuffer->connector.buffer, pCursor);
        };

        case ma_resource_manager_data_supply_type_decoded_paged:
        {
            return ma_paged_audio_buffer_get_cursor_in_pcm_frames(&pDataBuffer->connector.pagedBuffer, pCursor);
        };

        case ma_resource_manager_data_supply_type_unknown:
        {
            return MA_BUSY;
        };

        default:
        {
            return MA_INVALID_ARGS;
        }
    }
}

MA_API ma_result ma_resource_manager_data_buffer_get_length_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pLength)
{
    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) != MA_UNAVAILABLE);

    if (pDataBuffer == NULL || pLength == NULL) {
        return MA_INVALID_ARGS;
    }

    if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_unknown) {
        return MA_BUSY; /* Still loading. */
    }

    return ma_data_source_get_length_in_pcm_frames(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pLength);
}

MA_API ma_result ma_resource_manager_data_buffer_result(const ma_resource_manager_data_buffer* pDataBuffer)
{
    if (pDataBuffer == NULL) {
        return MA_INVALID_ARGS;
    }

    return (ma_result)c89atomic_load_i32((ma_result*)&pDataBuffer->result);    /* Need a naughty const-cast here. */
}

MA_API ma_result ma_resource_manager_data_buffer_set_looping(ma_resource_manager_data_buffer* pDataBuffer, ma_bool32 isLooping)
{
    return ma_data_source_set_looping(pDataBuffer, isLooping);
}

MA_API ma_bool32 ma_resource_manager_data_buffer_is_looping(const ma_resource_manager_data_buffer* pDataBuffer)
{
    return ma_data_source_is_looping(pDataBuffer);
}

MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames)
{
    if (pAvailableFrames == NULL) {
        return MA_INVALID_ARGS;
    }

    *pAvailableFrames = 0;

    if (pDataBuffer == NULL) {
        return MA_INVALID_ARGS;
    }

    if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_unknown) {
        if (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY) {
            return MA_BUSY;
        } else {
            return MA_INVALID_OPERATION;    /* No connector. */
        }
    }

    switch (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode))
    {
        case ma_resource_manager_data_supply_type_encoded:
        {
            return ma_decoder_get_available_frames(&pDataBuffer->connector.decoder, pAvailableFrames);
        };

        case ma_resource_manager_data_supply_type_decoded:
        {
            return ma_audio_buffer_get_available_frames(&pDataBuffer->connector.buffer, pAvailableFrames);
        };

        case ma_resource_manager_data_supply_type_decoded_paged:
        {
            ma_uint64 cursor;
            ma_paged_audio_buffer_get_cursor_in_pcm_frames(&pDataBuffer->connector.pagedBuffer, &cursor);

            if (pDataBuffer->pNode->data.backend.decodedPaged.decodedFrameCount > cursor) {
                *pAvailableFrames = pDataBuffer->pNode->data.backend.decodedPaged.decodedFrameCount - cursor;
            } else {
                *pAvailableFrames = 0;
            }

            return MA_SUCCESS;
        };

        case ma_resource_manager_data_supply_type_unknown:
        default:
        {
            /* Unknown supply type. Should never hit this. */
            return MA_INVALID_ARGS;
        }
    }
}

MA_API ma_result ma_resource_manager_register_file(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags)
{
    return ma_resource_manager_data_buffer_node_acquire(pResourceManager, pFilePath, NULL, 0, flags, NULL, NULL, NULL, NULL);
}

MA_API ma_result ma_resource_manager_register_file_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath, ma_uint32 flags)
{
    return ma_resource_manager_data_buffer_node_acquire(pResourceManager, NULL, pFilePath, 0, flags, NULL, NULL, NULL, NULL);
}


static ma_result ma_resource_manager_register_data(ma_resource_manager* pResourceManager, const char* pName, const wchar_t* pNameW, ma_resource_manager_data_supply* pExistingData)
{
    return ma_resource_manager_data_buffer_node_acquire(pResourceManager, pName, pNameW, 0, 0, pExistingData, NULL, NULL, NULL);
}

static ma_result ma_resource_manager_register_decoded_data_internal(ma_resource_manager* pResourceManager, const char* pName, const wchar_t* pNameW, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate)
{
    ma_resource_manager_data_supply data;
    data.type                            = ma_resource_manager_data_supply_type_decoded;
    data.backend.decoded.pData           = pData;
    data.backend.decoded.totalFrameCount = frameCount;
    data.backend.decoded.format          = format;
    data.backend.decoded.channels        = channels;
    data.backend.decoded.sampleRate      = sampleRate;

    return ma_resource_manager_register_data(pResourceManager, pName, pNameW, &data);
}

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)
{
    return ma_resource_manager_register_decoded_data_internal(pResourceManager, pName, NULL, pData, frameCount, format, channels, sampleRate);
}

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)
{
    return ma_resource_manager_register_decoded_data_internal(pResourceManager, NULL, pName, pData, frameCount, format, channels, sampleRate);
}


static ma_result ma_resource_manager_register_encoded_data_internal(ma_resource_manager* pResourceManager, const char* pName, const wchar_t* pNameW, const void* pData, size_t sizeInBytes)
{
    ma_resource_manager_data_supply data;
    data.type                        = ma_resource_manager_data_supply_type_encoded;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

{
    return ma_resource_manager_register_encoded_data_internal(pResourceManager, NULL, pName, pData, sizeInBytes);
}


MA_API ma_result ma_resource_manager_unregister_file(ma_resource_manager* pResourceManager, const char* pFilePath)
{
    return ma_resource_manager_unregister_data(pResourceManager, pFilePath);
}

MA_API ma_result ma_resource_manager_unregister_file_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath)
{
    return ma_resource_manager_unregister_data_w(pResourceManager, pFilePath);
}

MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResourceManager, const char* pName)
{
    return ma_resource_manager_data_buffer_node_unacquire(pResourceManager, NULL, pName, NULL);
}

MA_API ma_result ma_resource_manager_unregister_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName)
{
    return ma_resource_manager_data_buffer_node_unacquire(pResourceManager, NULL, NULL, pName);
}


static ma_uint32 ma_resource_manager_data_stream_next_execution_order(ma_resource_manager_data_stream* pDataStream)
{
    MA_ASSERT(pDataStream != NULL);
    return c89atomic_fetch_add_32(&pDataStream->executionCounter, 1);
}

static ma_bool32 ma_resource_manager_data_stream_is_decoder_at_end(const ma_resource_manager_data_stream* pDataStream)
{
    MA_ASSERT(pDataStream != NULL);
    return c89atomic_load_32((ma_bool32*)&pDataStream->isDecoderAtEnd);
}

static ma_uint32 ma_resource_manager_data_stream_seek_counter(const ma_resource_manager_data_stream* pDataStream)
{
    MA_ASSERT(pDataStream != NULL);
    return c89atomic_load_32((ma_uint32*)&pDataStream->seekCounter);
}


static ma_result ma_resource_manager_data_stream_cb__read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    return ma_resource_manager_data_stream_read_pcm_frames((ma_resource_manager_data_stream*)pDataSource, pFramesOut, frameCount, pFramesRead);
}

static ma_result ma_resource_manager_data_stream_cb__seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex)
{
    return ma_resource_manager_data_stream_seek_to_pcm_frame((ma_resource_manager_data_stream*)pDataSource, frameIndex);
}

static ma_result ma_resource_manager_data_stream_cb__get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
    return ma_resource_manager_data_stream_get_data_format((ma_resource_manager_data_stream*)pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}

static ma_result ma_resource_manager_data_stream_cb__get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor)
{
    return ma_resource_manager_data_stream_get_cursor_in_pcm_frames((ma_resource_manager_data_stream*)pDataSource, pCursor);
}

static ma_result ma_resource_manager_data_stream_cb__get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength)
{
    return ma_resource_manager_data_stream_get_length_in_pcm_frames((ma_resource_manager_data_stream*)pDataSource, pLength);
}

static ma_result ma_resource_manager_data_stream_cb__set_looping(ma_data_source* pDataSource, ma_bool32 isLooping)
{
    ma_resource_manager_data_stream* pDataStream = (ma_resource_manager_data_stream*)pDataSource;
    MA_ASSERT(pDataStream != NULL);

    c89atomic_exchange_32(&pDataStream->isLooping, isLooping);

    return MA_SUCCESS;
}

static ma_data_source_vtable g_ma_resource_manager_data_stream_vtable =
{
    ma_resource_manager_data_stream_cb__read_pcm_frames,
    ma_resource_manager_data_stream_cb__seek_to_pcm_frame,
    ma_resource_manager_data_stream_cb__get_data_format,
    ma_resource_manager_data_stream_cb__get_cursor_in_pcm_frames,
    ma_resource_manager_data_stream_cb__get_length_in_pcm_frames,
    ma_resource_manager_data_stream_cb__set_looping,
    MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT
};

static void ma_resource_manager_data_stream_set_absolute_cursor(ma_resource_manager_data_stream* pDataStream, ma_uint64 absoluteCursor)
{
    /* Loop if possible. */
    if (absoluteCursor > pDataStream->totalLengthInPCMFrames && pDataStream->totalLengthInPCMFrames > 0) {
        absoluteCursor = absoluteCursor % pDataStream->totalLengthInPCMFrames;
    }

    c89atomic_exchange_64(&pDataStream->absoluteCursor, absoluteCursor);
}

MA_API ma_result ma_resource_manager_data_stream_init_ex(ma_resource_manager* pResourceManager, const ma_resource_manager_data_source_config* pConfig, ma_resource_manager_data_stream* pDataStream)
{
    ma_result result;
    ma_data_source_config dataSourceConfig;
    char* pFilePathCopy = NULL;
    wchar_t* pFilePathWCopy = NULL;
    ma_job job;
    ma_bool32 waitBeforeReturning = MA_FALSE;
    ma_resource_manager_inline_notification waitNotification;
    ma_resource_manager_pipeline_notifications notifications;

    if (pDataStream == NULL) {
        if (pConfig != NULL && pConfig->pNotifications != NULL) {
            ma_resource_manager_pipeline_notifications_signal_all_notifications(pConfig->pNotifications);
        }

        return MA_INVALID_ARGS;
    }

    MA_ZERO_OBJECT(pDataStream);

    if (pConfig == NULL) {
        return MA_INVALID_ARGS;
    }

    if (pConfig->pNotifications != NULL) {
        notifications = *pConfig->pNotifications;    /* From here on out, `notifications` should be used instead of `pNotifications`. Setting this to NULL to catch any errors at testing time. */
    } else {
        MA_ZERO_OBJECT(&notifications);
    }

    dataSourceConfig = ma_data_source_config_init();
    dataSourceConfig.vtable = &g_ma_resource_manager_data_stream_vtable;

    result = ma_data_source_init(&dataSourceConfig, &pDataStream->ds);
    if (result != MA_SUCCESS) {
        ma_resource_manager_pipeline_notifications_signal_all_notifications(&notifications);
        return result;
    }

    pDataStream->pResourceManager = pResourceManager;
    pDataStream->flags            = pConfig->flags;
    pDataStream->result           = MA_BUSY;

    ma_data_source_set_range_in_pcm_frames(pDataStream, pConfig->rangeBegInPCMFrames, pConfig->rangeEndInPCMFrames);
    ma_data_source_set_loop_point_in_pcm_frames(pDataStream, pConfig->loopPointBegInPCMFrames, pConfig->loopPointEndInPCMFrames);
    ma_data_source_set_looping(pDataStream, pConfig->isLooping);

    if (pResourceManager == NULL || (pConfig->pFilePath == NULL && pConfig->pFilePathW == NULL)) {
        ma_resource_manager_pipeline_notifications_signal_all_notifications(&notifications);
        return MA_INVALID_ARGS;
    }

    /* We want all access to the VFS and the internal decoder to happen on the job thread just to keep things easier to manage for the VFS.  */

    /* We need a copy of the file path. We should probably make this more efficient, but for now we'll do a transient memory allocation. */
    if (pConfig->pFilePath != NULL) {
        pFilePathCopy  = ma_copy_string(pConfig->pFilePath, &pResourceManager->config.allocationCallbacks);
    } else {
        pFilePathWCopy = ma_copy_string_w(pConfig->pFilePathW, &pResourceManager->config.allocationCallbacks);
    }

    if (pFilePathCopy == NULL && pFilePathWCopy == NULL) {
        ma_resource_manager_pipeline_notifications_signal_all_notifications(&notifications);
        return MA_OUT_OF_MEMORY;
    }

    /*
    We need to check for the presence of MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC. If it's not set, we need to wait before returning. Otherwise we
    can return immediately. Likewise, we'll also check for MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT and do the same.
    */
    if ((pConfig->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC) == 0 || (pConfig->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
        waitBeforeReturning = MA_TRUE;
        ma_resource_manager_inline_notification_init(pResourceManager, &waitNotification);
    }

    ma_resource_manager_pipeline_notifications_acquire_all_fences(&notifications);

    /* Set the absolute cursor to our initial seek position so retrieval of the cursor returns a good value. */
    ma_resource_manager_data_stream_set_absolute_cursor(pDataStream, pConfig->initialSeekPointInPCMFrames);

    /* We now have everything we need to post the job. This is the last thing we need to do from here. The rest will be done by the job thread. */
    job = ma_job_init(MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_STREAM);
    job.order = ma_resource_manager_data_stream_next_execution_order(pDataStream);
    job.data.resourceManager.loadDataStream.pDataStream       = pDataStream;
    job.data.resourceManager.loadDataStream.pFilePath         = pFilePathCopy;
    job.data.resourceManager.loadDataStream.pFilePathW        = pFilePathWCopy;
    job.data.resourceManager.loadDataStream.initialSeekPoint  = pConfig->initialSeekPointInPCMFrames;
    job.data.resourceManager.loadDataStream.pInitNotification = (waitBeforeReturning == MA_TRUE) ? &waitNotification : notifications.init.pNotification;
    job.data.resourceManager.loadDataStream.pInitFence        = notifications.init.pFence;
    result = ma_resource_manager_post_job(pResourceManager, &job);
    if (result != MA_SUCCESS) {
        ma_resource_manager_pipeline_notifications_signal_all_notifications(&notifications);
        ma_resource_manager_pipeline_notifications_release_all_fences(&notifications);

        if (waitBeforeReturning) {
            ma_resource_manager_inline_notification_uninit(&waitNotification);
        }

        ma_free(pFilePathCopy,  &pResourceManager->config.allocationCallbacks);
        ma_free(pFilePathWCopy, &pResourceManager->config.allocationCallbacks);
        return result;
    }

    /* Wait if needed. */
    if (waitBeforeReturning) {
        ma_resource_manager_inline_notification_wait_and_uninit(&waitNotification);

        if (notifications.init.pNotification != NULL) {
            ma_async_notification_signal(notifications.init.pNotification);
        }

        /* NOTE: Do not release pInitFence here. That will be done by the job. */
    }

    return MA_SUCCESS;
}

MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_stream* pDataStream)
{
    ma_resource_manager_data_source_config config;

    config = ma_resource_manager_data_source_config_init();
    config.pFilePath      = pFilePath;
    config.flags          = flags;
    config.pNotifications = pNotifications;
    
    return ma_resource_manager_data_stream_init_ex(pResourceManager, &config, pDataStream);
}

MA_API ma_result ma_resource_manager_data_stream_init_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath, ma_uint32 flags, const ma_resource_manager_pipeline_notifications* pNotifications, ma_resource_manager_data_stream* pDataStream)
{
    ma_resource_manager_data_source_config config;

    config = ma_resource_manager_data_source_config_init();
    config.pFilePathW     = pFilePath;
    config.flags          = flags;
    config.pNotifications = pNotifications;
    
    return ma_resource_manager_data_stream_init_ex(pResourceManager, &config, pDataStream);

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN


    /* If the page we're on is invalid it means we've caught up to the job thread. */
    if (c89atomic_load_32(&pDataStream->isPageValid[pDataStream->currentPageIndex]) == MA_FALSE) {
        framesAvailable = 0;
    } else {
        /*
        The page we're on is valid so we must have some frames available. We need to make sure that we don't overflow into the next page, even if it's valid. The reason is
        that the unmap process will only post an update for one page at a time. Keeping mapping tied to page boundaries makes this simpler.
        */
        ma_uint32 currentPageFrameCount = c89atomic_load_32(&pDataStream->pageFrameCount[pDataStream->currentPageIndex]);
        MA_ASSERT(currentPageFrameCount >= pDataStream->relativeCursor);

        framesAvailable = currentPageFrameCount - pDataStream->relativeCursor;
    }

    /* If there's no frames available and the result is set to MA_AT_END we need to return MA_AT_END. */
    if (framesAvailable == 0) {
        if (ma_resource_manager_data_stream_is_decoder_at_end(pDataStream)) {
            return MA_AT_END;
        } else {
            return MA_BUSY; /* There are no frames available, but we're not marked as EOF so we might have caught up to the job thread. Need to return MA_BUSY and wait for more data. */
        }
    }

    MA_ASSERT(framesAvailable > 0);

    if (frameCount > framesAvailable) {
        frameCount = framesAvailable;
    }

    *ppFramesOut = ma_resource_manager_data_stream_get_page_data_pointer(pDataStream, pDataStream->currentPageIndex, pDataStream->relativeCursor);
    *pFrameCount = frameCount;

    return MA_SUCCESS;
}

static ma_result ma_resource_manager_data_stream_unmap(ma_resource_manager_data_stream* pDataStream, ma_uint64 frameCount)
{
    ma_uint32 newRelativeCursor;
    ma_uint32 pageSizeInFrames;
    ma_job job;

    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(ma_resource_manager_data_stream_result(pDataStream) != MA_UNAVAILABLE);

    if (pDataStream == NULL) {
        return MA_INVALID_ARGS;
    }

    if (ma_resource_manager_data_stream_result(pDataStream) != MA_SUCCESS) {
        return MA_INVALID_OPERATION;
    }

    /* The frame count should always fit inside a 32-bit integer. */
    if (frameCount > 0xFFFFFFFF) {
        return MA_INVALID_ARGS;
    }

    pageSizeInFrames = ma_resource_manager_data_stream_get_page_size_in_frames(pDataStream);

    /* The absolute cursor needs to be updated for ma_resource_manager_data_stream_get_cursor_in_pcm_frames(). */
    ma_resource_manager_data_stream_set_absolute_cursor(pDataStream, c89atomic_load_64(&pDataStream->absoluteCursor) + frameCount);

    /* Here is where we need to check if we need to load a new page, and if so, post a job to load it. */
    newRelativeCursor = pDataStream->relativeCursor + (ma_uint32)frameCount;

    /* If the new cursor has flowed over to the next page we need to mark the old one as invalid and post an event for it. */
    if (newRelativeCursor >= pageSizeInFrames) {
        newRelativeCursor -= pageSizeInFrames;

        /* Here is where we post the job start decoding. */
        job = ma_job_init(MA_JOB_TYPE_RESOURCE_MANAGER_PAGE_DATA_STREAM);
        job.order = ma_resource_manager_data_stream_next_execution_order(pDataStream);
        job.data.resourceManager.pageDataStream.pDataStream = pDataStream;
        job.data.resourceManager.pageDataStream.pageIndex   = pDataStream->currentPageIndex;

        /* The page needs to be marked as invalid so that the public API doesn't try reading from it. */
        c89atomic_exchange_32(&pDataStream->isPageValid[pDataStream->currentPageIndex], MA_FALSE);

        /* Before posting the job we need to make sure we set some state. */
        pDataStream->relativeCursor   = newRelativeCursor;
        pDataStream->currentPageIndex = (pDataStream->currentPageIndex + 1) & 0x01;
        return ma_resource_manager_post_job(pDataStream->pResourceManager, &job);
    } else {
        /* We haven't moved into a new page so we can just move the cursor forward. */
        pDataStream->relativeCursor = newRelativeCursor;
        return MA_SUCCESS;
    }
}


MA_API ma_result ma_resource_manager_data_stream_read_pcm_frames(ma_resource_manager_data_stream* pDataStream, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
{
    ma_result result = MA_SUCCESS;
    ma_uint64 totalFramesProcessed;
    ma_format format;
    ma_uint32 channels;

    /* Safety. */
    if (pFramesRead != NULL) {
        *pFramesRead = 0;
    }

    if (frameCount == 0) {
        return MA_INVALID_ARGS;
    }

    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(ma_resource_manager_data_stream_result(pDataStream) != MA_UNAVAILABLE);

    if (pDataStream == NULL) {
        return MA_INVALID_ARGS;
    }

    if (ma_resource_manager_data_stream_result(pDataStream) != MA_SUCCESS) {
        return MA_INVALID_OPERATION;
    }

    /* Don't attempt to read while we're in the middle of seeking. Tell the caller that we're busy. */
    if (ma_resource_manager_data_stream_seek_counter(pDataStream) > 0) {
        return MA_BUSY;
    }

    ma_resource_manager_data_stream_get_data_format(pDataStream, &format, &channels, NULL, NULL, 0);

    /* Reading is implemented in terms of map/unmap. We need to run this in a loop because mapping is clamped against page boundaries. */
    totalFramesProcessed = 0;
    while (totalFramesProcessed < frameCount) {
        void* pMappedFrames;
        ma_uint64 mappedFrameCount;

        mappedFrameCount = frameCount - totalFramesProcessed;
        result = ma_resource_manager_data_stream_map(pDataStream, &pMappedFrames, &mappedFrameCount);
        if (result != MA_SUCCESS) {
            break;
        }

        /* Copy the mapped data to the output buffer if we have one. It's allowed for pFramesOut to be NULL in which case a relative forward seek is performed. */
        if (pFramesOut != NULL) {
            ma_copy_pcm_frames(ma_offset_pcm_frames_ptr(pFramesOut, totalFramesProcessed, format, channels), pMappedFrames, mappedFrameCount, format, channels);
        }

        totalFramesProcessed += mappedFrameCount;

        result = ma_resource_manager_data_stream_unmap(pDataStream, mappedFrameCount);
        if (result != MA_SUCCESS) {
            break;  /* This is really bad - will only get an error here if we failed to post a job to the queue for loading the next page. */
        }
    }

    if (pFramesRead != NULL) {
        *pFramesRead = totalFramesProcessed;
    }

    if (result == MA_SUCCESS && totalFramesProcessed == 0) {
        result  = MA_AT_END;
    }

    return result;
}

MA_API ma_result ma_resource_manager_data_stream_seek_to_pcm_frame(ma_resource_manager_data_stream* pDataStream, ma_uint64 frameIndex)
{
    ma_job job;
    ma_result streamResult;

    streamResult = ma_resource_manager_data_stream_result(pDataStream);

    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(streamResult != MA_UNAVAILABLE);

    if (pDataStream == NULL) {
        return MA_INVALID_ARGS;
    }

    if (streamResult != MA_SUCCESS && streamResult != MA_BUSY) {
        return MA_INVALID_OPERATION;
    }

    /* If we're not already seeking and we're sitting on the same frame, just make this a no-op. */
    if (c89atomic_load_32(&pDataStream->seekCounter) == 0) {
        if (c89atomic_load_64(&pDataStream->absoluteCursor) == frameIndex) {
            return MA_SUCCESS;
        }
    }


    /* Increment the seek counter first to indicate to read_paged_pcm_frames() and map_paged_pcm_frames() that we are in the middle of a seek and MA_BUSY should be returned. */
    c89atomic_fetch_add_32(&pDataStream->seekCounter, 1);

    /* Update the absolute cursor so that ma_resource_manager_data_stream_get_cursor_in_pcm_frames() returns the new position. */
    ma_resource_manager_data_stream_set_absolute_cursor(pDataStream, frameIndex);

    /*
    We need to clear our currently loaded pages so that the stream starts playback from the new seek point as soon as possible. These are for the purpose of the public
    API and will be ignored by the seek job. The seek job will operate on the assumption that both pages have been marked as invalid and the cursor is at the start of
    the first page.
    */
    pDataStream->relativeCursor   = 0;
    pDataStream->currentPageIndex = 0;
    c89atomic_exchange_32(&pDataStream->isPageValid[0], MA_FALSE);
    c89atomic_exchange_32(&pDataStream->isPageValid[1], MA_FALSE);

    /* Make sure the data stream is not marked as at the end or else if we seek in response to hitting the end, we won't be able to read any more data. */
    c89atomic_exchange_32(&pDataStream->isDecoderAtEnd, MA_FALSE);

    /*
    The public API is not allowed to touch the internal decoder so we need to use a job to perform the seek. When seeking, the job thread will assume both pages
    are invalid and any content contained within them will be discarded and replaced with newly decoded data.
    */
    job = ma_job_init(MA_JOB_TYPE_RESOURCE_MANAGER_SEEK_DATA_STREAM);
    job.order = ma_resource_manager_data_stream_next_execution_order(pDataStream);
    job.data.resourceManager.seekDataStream.pDataStream = pDataStream;
    job.data.resourceManager.seekDataStream.frameIndex  = frameIndex;
    return ma_resource_manager_post_job(pDataStream->pResourceManager, &job);
}

MA_API ma_result ma_resource_manager_data_stream_get_data_format(ma_resource_manager_data_stream* pDataStream, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(ma_resource_manager_data_stream_result(pDataStream) != MA_UNAVAILABLE);

    if (pFormat != NULL) {
        *pFormat = ma_format_unknown;
    }

    if (pChannels != NULL) {
        *pChannels = 0;
    }

    if (pSampleRate != NULL) {
        *pSampleRate = 0;
    }

    if (pChannelMap != NULL) {
        MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap);
    }

    if (pDataStream == NULL) {
        return MA_INVALID_ARGS;
    }

    if (ma_resource_manager_data_stream_result(pDataStream) != MA_SUCCESS) {
        return MA_INVALID_OPERATION;
    }

    /*
    We're being a little bit naughty here and accessing the internal decoder from the public API. The output data format is constant, and we've defined this function
    such that the application is responsible for ensuring it's not called while uninitializing so it should be safe.
    */
    return ma_data_source_get_data_format(&pDataStream->decoder, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
}

MA_API ma_result ma_resource_manager_data_stream_get_cursor_in_pcm_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pCursor)
{
    ma_result result;

    if (pCursor == NULL) {
        return MA_INVALID_ARGS;
    }

    *pCursor = 0;

    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(ma_resource_manager_data_stream_result(pDataStream) != MA_UNAVAILABLE);

    if (pDataStream == NULL) {
        return MA_INVALID_ARGS;
    }

    /*
    If the stream is in an erroneous state we need to return an invalid operation. We can allow
    this to be called when the data stream is in a busy state because the caller may have asked
    for an initial seek position and it's convenient to return that as the cursor position.
    */
    result = ma_resource_manager_data_stream_result(pDataStream);
    if (result != MA_SUCCESS && result != MA_BUSY) {
        return MA_INVALID_OPERATION;
    }

    *pCursor = c89atomic_load_64(&pDataStream->absoluteCursor);

    return MA_SUCCESS;
}

MA_API ma_result ma_resource_manager_data_stream_get_length_in_pcm_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pLength)
{
    ma_result streamResult;

    if (pLength == NULL) {
        return MA_INVALID_ARGS;
    }

    *pLength = 0;

    streamResult = ma_resource_manager_data_stream_result(pDataStream);

    /* We cannot be using the data source after it's been uninitialized. */
    MA_ASSERT(streamResult != MA_UNAVAILABLE);

    if (pDataStream == NULL) {
        return MA_INVALID_ARGS;
    }

    if (streamResult != MA_SUCCESS) {
        return streamResult;
    }

    /*
    We most definitely do not want to be calling ma_decoder_get_length_in_pcm_frames() directly. Instead we want to use a cached value that we
    calculated when we initialized it on the job thread.
    */
    *pLength = pDataStream->totalLengthInPCMFrames;
    if (*pLength == 0) {
        return MA_NOT_IMPLEMENTED;  /* Some decoders may not have a known length. */
    }

    return MA_SUCCESS;
}

MA_API ma_result ma_resource_manager_data_stream_result(const ma_resource_manager_data_stream* pDataStream)
{
    if (pDataStream == NULL) {
        return MA_INVALID_ARGS;
    }

    return (ma_result)c89atomic_load_i32(&pDataStream->result);
}

MA_API ma_result ma_resource_manager_data_stream_set_looping(ma_resource_manager_data_stream* pDataStream, ma_bool32 isLooping)
{
    return ma_data_source_set_looping(pDataStream, isLooping);
}

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN


    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_read_pcm_frames(&pDataSource->backend.stream, pFramesOut, frameCount, pFramesRead);
    } else {
        return ma_resource_manager_data_buffer_read_pcm_frames(&pDataSource->backend.buffer, pFramesOut, frameCount, pFramesRead);
    }
}

MA_API ma_result ma_resource_manager_data_source_seek_to_pcm_frame(ma_resource_manager_data_source* pDataSource, ma_uint64 frameIndex)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_seek_to_pcm_frame(&pDataSource->backend.stream, frameIndex);
    } else {
        return ma_resource_manager_data_buffer_seek_to_pcm_frame(&pDataSource->backend.buffer, frameIndex);
    }
}

MA_API ma_result ma_resource_manager_data_source_map(ma_resource_manager_data_source* pDataSource, void** ppFramesOut, ma_uint64* pFrameCount)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_map(&pDataSource->backend.stream, ppFramesOut, pFrameCount);
    } else {
        return MA_NOT_IMPLEMENTED;  /* Mapping not supported with data buffers. */
    }
}

MA_API ma_result ma_resource_manager_data_source_unmap(ma_resource_manager_data_source* pDataSource, ma_uint64 frameCount)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_unmap(&pDataSource->backend.stream, frameCount);
    } else {
        return MA_NOT_IMPLEMENTED;  /* Mapping not supported with data buffers. */
    }
}

MA_API ma_result ma_resource_manager_data_source_get_data_format(ma_resource_manager_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_get_data_format(&pDataSource->backend.stream, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
    } else {
        return ma_resource_manager_data_buffer_get_data_format(&pDataSource->backend.buffer, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
    }
}

MA_API ma_result ma_resource_manager_data_source_get_cursor_in_pcm_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pCursor)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_get_cursor_in_pcm_frames(&pDataSource->backend.stream, pCursor);
    } else {
        return ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(&pDataSource->backend.buffer, pCursor);
    }
}

MA_API ma_result ma_resource_manager_data_source_get_length_in_pcm_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pLength)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_get_length_in_pcm_frames(&pDataSource->backend.stream, pLength);
    } else {
        return ma_resource_manager_data_buffer_get_length_in_pcm_frames(&pDataSource->backend.buffer, pLength);
    }
}

MA_API ma_result ma_resource_manager_data_source_result(const ma_resource_manager_data_source* pDataSource)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_result(&pDataSource->backend.stream);
    } else {
        return ma_resource_manager_data_buffer_result(&pDataSource->backend.buffer);
    }
}

MA_API ma_result ma_resource_manager_data_source_set_looping(ma_resource_manager_data_source* pDataSource, ma_bool32 isLooping)
{
    if (pDataSource == NULL) {
        return MA_INVALID_ARGS;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_set_looping(&pDataSource->backend.stream, isLooping);
    } else {
        return ma_resource_manager_data_buffer_set_looping(&pDataSource->backend.buffer, isLooping);
    }
}

MA_API ma_bool32 ma_resource_manager_data_source_is_looping(const ma_resource_manager_data_source* pDataSource)
{
    if (pDataSource == NULL) {
        return MA_FALSE;
    }

    if ((pDataSource->flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM) != 0) {
        return ma_resource_manager_data_stream_is_looping(&pDataSource->backend.stream);
    } else {
        return ma_resource_manager_data_buffer_is_looping(&pDataSource->backend.buffer);
    }
}

MA_API ma_result ma_resource_manager_data_source_get_available_frames(ma_resource_manager_data_source* pDataSource, ma_uint64* pAvailableFrames)
{
    if (pAvailableFrames == NULL) {
        return MA_INVALID_ARGS;
    }

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    }

    /*c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);*/
    return MA_SUCCESS;
}

static ma_result ma_job_process__resource_manager__page_data_stream(ma_job* pJob)
{
    ma_result result = MA_SUCCESS;
    ma_resource_manager* pResourceManager;
    ma_resource_manager_data_stream* pDataStream;

    MA_ASSERT(pJob != NULL);

    pDataStream = (ma_resource_manager_data_stream*)pJob->data.resourceManager.pageDataStream.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. */
    if (ma_resource_manager_data_stream_result(pDataStream) != MA_SUCCESS) {
        result = MA_INVALID_OPERATION;
        goto done;
    }

    ma_resource_manager_data_stream_fill_page(pDataStream, pJob->data.resourceManager.pageDataStream.pageIndex);

done:
    c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);
    return result;
}

static ma_result ma_job_process__resource_manager__seek_data_stream(ma_job* pJob)
{
    ma_result result = MA_SUCCESS;
    ma_resource_manager* pResourceManager;
    ma_resource_manager_data_stream* pDataStream;

    MA_ASSERT(pJob != NULL);

    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

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

    }

    /* There is no notion of an end of a sound if it's not backed by a data source. */
    if (pSound->pDataSource == NULL) {
        return MA_FALSE;
    }

    return c89atomic_load_32(&pSound->atEnd);
}

MA_API ma_result ma_sound_seek_to_pcm_frame(ma_sound* pSound, ma_uint64 frameIndex)
{
    if (pSound == NULL) {
        return MA_INVALID_ARGS;
    }

    /* Seeking is only valid for sounds that are backed by a data source. */
    if (pSound->pDataSource == NULL) {
        return MA_INVALID_OPERATION;
    }

    /* We can't be seeking while reading at the same time. We just set the seek target and get the mixing thread to do the actual seek. */
    c89atomic_exchange_64(&pSound->seekTarget, frameIndex);

    return MA_SUCCESS;
}

MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
    if (pSound == NULL) {
        return MA_INVALID_ARGS;
    }

    /* The data format is retrieved directly from the data source if the sound is backed by one. Otherwise we pull it from the node. */
    if (pSound->pDataSource == NULL) {
        ma_uint32 channels;

        if (pFormat != NULL) {
            *pFormat = ma_format_f32;
        }

        channels = ma_node_get_input_channels(&pSound->engineNode, 0);
        if (pChannels != NULL) {
            *pChannels = channels;
        }

        if (pSampleRate != NULL) {
            *pSampleRate = pSound->engineNode.resampler.config.sampleRateIn;
        }

        if (pChannelMap != NULL) {
            ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, channels);
        }

        return MA_SUCCESS;
    } else {
        return ma_data_source_get_data_format(pSound->pDataSource, pFormat, pChannels, pSampleRate, pChannelMap, channelMapCap);
    }
}

MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor)
{
    if (pSound == NULL) {
        return MA_INVALID_ARGS;
    }

    /* The notion of a cursor is only valid for sounds that are backed by a data source. */
    if (pSound->pDataSource == NULL) {
        return MA_INVALID_OPERATION;
    }

    return ma_data_source_get_cursor_in_pcm_frames(pSound->pDataSource, pCursor);
}

MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength)
{
    if (pSound == NULL) {
        return MA_INVALID_ARGS;
    }

    /* The notion of a sound length is only valid for sounds that are backed by a data source. */
    if (pSound->pDataSource == NULL) {
        return MA_INVALID_OPERATION;
    }

    return ma_data_source_get_length_in_pcm_frames(pSound->pDataSource, pLength);
}

MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor)
{
    if (pSound == NULL) {
        return MA_INVALID_ARGS;
    }

    /* The notion of a cursor is only valid for sounds that are backed by a data source. */
    if (pSound->pDataSource == NULL) {
        return MA_INVALID_OPERATION;
    }

    return ma_data_source_get_cursor_in_seconds(pSound->pDataSource, pCursor);
}

MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength)
{
    if (pSound == NULL) {
        return MA_INVALID_ARGS;
    }

    /* The notion of a sound length is only valid for sounds that are backed by a data source. */
    if (pSound->pDataSource == NULL) {
        return MA_INVALID_OPERATION;
    }

    return ma_data_source_get_length_in_seconds(pSound->pDataSource, pLength);
}


MA_API ma_result ma_sound_group_init(ma_engine* pEngine, ma_uint32 flags, ma_sound_group* pParentGroup, ma_sound_group* pGroup)
{
    ma_sound_group_config config = ma_sound_group_config_init();
    config.flags              = flags;
    config.pInitialAttachment = pParentGroup;
    return ma_sound_group_init_ex(pEngine, &config, pGroup);
}

MA_API ma_result ma_sound_group_init_ex(ma_engine* pEngine, const ma_sound_group_config* pConfig, ma_sound_group* pGroup)
{
    ma_sound_config soundConfig;

    if (pGroup == NULL) {
        return MA_INVALID_ARGS;
    }

    MA_ZERO_OBJECT(pGroup);

    if (pConfig == NULL) {
        return MA_INVALID_ARGS;
    }

    /* A sound group is just a sound without a data source. */
    soundConfig = *pConfig;
    soundConfig.pFilePath   = NULL;
    soundConfig.pFilePathW  = NULL;
    soundConfig.pDataSource = NULL;

    /*
    Groups need to have spatialization disabled by default because I think it'll be pretty rare
    that programs will want to spatialize groups (but not unheard of). Certainly it feels like
    disabling this by default feels like the right option. Spatialization can be enabled with a
    call to ma_sound_group_set_spatialization_enabled().
    */
    soundConfig.flags |= MA_SOUND_FLAG_NO_SPATIALIZATION;

    return ma_sound_init_ex(pEngine, &soundConfig, pGroup);
}

MA_API void ma_sound_group_uninit(ma_sound_group* pGroup)
{
    ma_sound_uninit(pGroup);
}

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

        pMetadata->data.inst.fineTuneCents = (drwav_int8)instData[1];
        pMetadata->data.inst.gainDecibels  = (drwav_int8)instData[2];
        pMetadata->data.inst.lowNote       = (drwav_int8)instData[3];
        pMetadata->data.inst.highNote      = (drwav_int8)instData[4];
        pMetadata->data.inst.lowVelocity   = (drwav_int8)instData[5];
        pMetadata->data.inst.highVelocity  = (drwav_int8)instData[6];
    }
    return bytesRead;
}
DRWAV_PRIVATE drwav_uint64 drwav__read_acid_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
{
    drwav_uint8 acidData[DRWAV_ACID_BYTES];
    drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, acidData, sizeof(acidData), NULL);
    DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
    if (bytesRead == sizeof(acidData)) {
        pMetadata->type                       = drwav_metadata_type_acid;
        pMetadata->data.acid.flags            = drwav_bytes_to_u32(acidData + 0);
        pMetadata->data.acid.midiUnityNote    = drwav_bytes_to_u16(acidData + 4);
        pMetadata->data.acid.reserved1        = drwav_bytes_to_u16(acidData + 6);
        pMetadata->data.acid.reserved2        = drwav_bytes_to_f32(acidData + 8);
        pMetadata->data.acid.numBeats         = drwav_bytes_to_u32(acidData + 12);
        pMetadata->data.acid.meterDenominator = drwav_bytes_to_u16(acidData + 16);
        pMetadata->data.acid.meterNumerator   = drwav_bytes_to_u16(acidData + 18);
        pMetadata->data.acid.tempo            = drwav_bytes_to_f32(acidData + 20);
    }
    return bytesRead;
}
DRWAV_PRIVATE size_t drwav__strlen(const char* str)
{
    size_t result = 0;
    while (*str++) {
        result += 1;
    }
    return result;
}
DRWAV_PRIVATE size_t drwav__strlen_clamped(const char* str, size_t maxToRead)
{
    size_t result = 0;
    while (*str++ && result < maxToRead) {
        result += 1;
    }
    return result;
}
DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser, const char* str, size_t maxToRead)
{
    size_t len = drwav__strlen_clamped(str, maxToRead);
    if (len) {
        char* result = (char*)drwav__metadata_get_memory(pParser, len + 1, 1);
        DRWAV_ASSERT(result != NULL);
        DRWAV_COPY_MEMORY(result, str, len);
        result[len] = '\0';
        return result;
    } else {
        return NULL;
    }
}
typedef struct
{
    const void* pBuffer;
    size_t sizeInBytes;
    size_t cursor;
} drwav_buffer_reader;
DRWAV_PRIVATE drwav_result drwav_buffer_reader_init(const void* pBuffer, size_t sizeInBytes, drwav_buffer_reader* pReader)
{
    DRWAV_ASSERT(pBuffer != NULL);
    DRWAV_ASSERT(pReader != NULL);
    DRWAV_ZERO_OBJECT(pReader);
    pReader->pBuffer     = pBuffer;
    pReader->sizeInBytes = sizeInBytes;
    pReader->cursor      = 0;
    return DRWAV_SUCCESS;
}
DRWAV_PRIVATE const void* drwav_buffer_reader_ptr(const drwav_buffer_reader* pReader)
{
    DRWAV_ASSERT(pReader != NULL);
    return drwav_offset_ptr(pReader->pBuffer, pReader->cursor);
}
DRWAV_PRIVATE drwav_result drwav_buffer_reader_seek(drwav_buffer_reader* pReader, size_t bytesToSeek)
{
    DRWAV_ASSERT(pReader != NULL);
    if (pReader->cursor + bytesToSeek > pReader->sizeInBytes) {
        return DRWAV_BAD_SEEK;
    }
    pReader->cursor += bytesToSeek;
    return DRWAV_SUCCESS;
}
DRWAV_PRIVATE drwav_result drwav_buffer_reader_read(drwav_buffer_reader* pReader, void* pDst, size_t bytesToRead, size_t* pBytesRead)
{
    drwav_result result = DRWAV_SUCCESS;
    size_t bytesRemaining;
    DRWAV_ASSERT(pReader != NULL);
    if (pBytesRead != NULL) {
        *pBytesRead = 0;
    }
    bytesRemaining = (pReader->sizeInBytes - pReader->cursor);
    if (bytesToRead > bytesRemaining) {
        bytesToRead = bytesRemaining;
    }
    if (pDst == NULL) {
        result = drwav_buffer_reader_seek(pReader, bytesToRead);
    } else {
        DRWAV_COPY_MEMORY(pDst, drwav_buffer_reader_ptr(pReader), bytesToRead);
        pReader->cursor += bytesToRead;
    }
    DRWAV_ASSERT(pReader->cursor <= pReader->sizeInBytes);
    if (result == DRWAV_SUCCESS) {
        if (pBytesRead != NULL) {
            *pBytesRead = bytesToRead;
        }
    }
    return DRWAV_SUCCESS;
}
DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u16(drwav_buffer_reader* pReader, drwav_uint16* pDst)
{
    drwav_result result;
    size_t bytesRead;
    drwav_uint8 data[2];
    DRWAV_ASSERT(pReader != NULL);
    DRWAV_ASSERT(pDst != NULL);
    *pDst = 0;
    result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
    if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
        return result;
    }
    *pDst = drwav_bytes_to_u16(data);
    return DRWAV_SUCCESS;
}
DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u32(drwav_buffer_reader* pReader, drwav_uint32* pDst)
{
    drwav_result result;
    size_t bytesRead;
    drwav_uint8 data[4];
    DRWAV_ASSERT(pReader != NULL);
    DRWAV_ASSERT(pDst != NULL);
    *pDst = 0;
    result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
    if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
        return result;
    }
    *pDst = drwav_bytes_to_u32(data);
    return DRWAV_SUCCESS;
}
DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize)
{
    drwav_uint8 bextData[DRWAV_BEXT_BYTES];
    size_t bytesRead = drwav__metadata_parser_read(pParser, bextData, sizeof(bextData), NULL);
    DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
    if (bytesRead == sizeof(bextData)) {
        drwav_buffer_reader reader;
        drwav_uint32 timeReferenceLow;
        drwav_uint32 timeReferenceHigh;
        size_t extraBytes;
        pMetadata->type = drwav_metadata_type_bext;
        if (drwav_buffer_reader_init(bextData, bytesRead, &reader) == DRWAV_SUCCESS) {
            pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_DESCRIPTION_BYTES);
            drwav_buffer_reader_seek(&reader, DRWAV_BEXT_DESCRIPTION_BYTES);
            pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
            drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
            pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
            drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
            drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate), NULL);
            drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime), NULL);
            drwav_buffer_reader_read_u32(&reader, &timeReferenceLow);
            drwav_buffer_reader_read_u32(&reader, &timeReferenceHigh);
            pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

                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")) {
            return DRWAV_FALSE;
        }
    } else {
        drwav_uint8 chunkSizeBytes[8];
        drwav_uint8 wave[16];
        if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
            return DRWAV_FALSE;
        }
        if (drwav_bytes_to_u64(chunkSizeBytes) < 80) {
            return DRWAV_FALSE;
        }
        if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
            return DRWAV_FALSE;
        }
        if (!drwav_guid_equal(wave, drwavGUID_W64_WAVE)) {
            return DRWAV_FALSE;
        }
    }
    if (pWav->container == drwav_container_rf64) {
        drwav_uint8 sizeBytes[8];
        drwav_uint64 bytesRemainingInChunk;
        drwav_chunk_header header;
        drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
        if (result != DRWAV_SUCCESS) {
            return DRWAV_FALSE;
        }
        if (!drwav_fourcc_equal(header.id.fourcc, "ds64")) {
            return DRWAV_FALSE;
        }
        bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
        if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
            return DRWAV_FALSE;
        }
        bytesRemainingInChunk -= 8;
        cursor += 8;
        if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
            return DRWAV_FALSE;
        }
        bytesRemainingInChunk -= 8;
        dataChunkSize = drwav_bytes_to_u64(sizeBytes);
        if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
            return DRWAV_FALSE;
        }
        bytesRemainingInChunk -= 8;
        sampleCountFromFactChunk = drwav_bytes_to_u64(sizeBytes);
        if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
            return DRWAV_FALSE;
        }
        cursor += bytesRemainingInChunk;
    }
    if (!drwav__read_fmt(pWav->onRead, pWav->onSeek, pWav->pUserData, pWav->container, &cursor, &fmt)) {
        return DRWAV_FALSE;
    }
    if ((fmt.sampleRate    == 0 || fmt.sampleRate    > DRWAV_MAX_SAMPLE_RATE)     ||
        (fmt.channels      == 0 || fmt.channels      > DRWAV_MAX_CHANNELS)        ||
        (fmt.bitsPerSample == 0 || fmt.bitsPerSample > DRWAV_MAX_BITS_PER_SAMPLE) ||
        fmt.blockAlign == 0) {
        return DRWAV_FALSE;
    }
    translatedFormatTag = fmt.formatTag;
    if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
        translatedFormatTag = drwav_bytes_to_u16(fmt.subFormat + 0);
    }
    DRWAV_ZERO_MEMORY(&metadataParser, sizeof(metadataParser));
    if (!sequential && pWav->allowedMetadataTypes != drwav_metadata_type_none && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64)) {
        drwav_uint64 cursorForMetadata = cursor;
        metadataParser.onRead = pWav->onRead;
        metadataParser.onSeek = pWav->onSeek;
        metadataParser.pReadSeekUserData = pWav->pUserData;
        metadataParser.stage = drwav__metadata_parser_stage_count;
        for (;;) {
            drwav_result result;
            drwav_uint64 bytesRead;
            drwav_uint64 remainingBytes;
            drwav_chunk_header header;
            result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursorForMetadata, &header);
            if (result != DRWAV_SUCCESS) {
                break;
            }
            bytesRead = drwav__metadata_process_chunk(&metadataParser, &header, pWav->allowedMetadataTypes);
            DRWAV_ASSERT(bytesRead <= header.sizeInBytes);
            remainingBytes = header.sizeInBytes - bytesRead + header.paddingSize;
            if (!drwav__seek_forward(pWav->onSeek, remainingBytes, pWav->pUserData)) {
                break;
            }
            cursorForMetadata += remainingBytes;
        }
        if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
            return DRWAV_FALSE;
        }
        drwav__metadata_alloc(&metadataParser, &pWav->allocationCallbacks);
        metadataParser.stage = drwav__metadata_parser_stage_read;
    }
    foundDataChunk = DRWAV_FALSE;
    for (;;) {
        drwav_chunk_header header;
        drwav_result result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
        if (result != DRWAV_SUCCESS) {
            if (!foundDataChunk) {
                return DRWAV_FALSE;
            } else {
                break;
            }
        }
        if (!sequential && onChunk != NULL) {
            drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
            if (callbackBytesRead > 0) {
                if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
                    return DRWAV_FALSE;
                }
            }
        }
        if (!sequential && pWav->allowedMetadataTypes != drwav_metadata_type_none && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64)) {
            drwav_uint64 bytesRead = drwav__metadata_process_chunk(&metadataParser, &header, pWav->allowedMetadataTypes);
            if (bytesRead > 0) {
                if (!drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData)) {
                    return DRWAV_FALSE;
                }
            }
        }
        if (!foundDataChunk) {
            pWav->dataChunkDataPos = cursor;
        }
        chunkSize = header.sizeInBytes;
        if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
            if (drwav_fourcc_equal(header.id.fourcc, "data")) {
                foundDataChunk = DRWAV_TRUE;
                if (pWav->container != drwav_container_rf64) {
                    dataChunkSize = chunkSize;
                }
            }
        } else {
            if (drwav_guid_equal(header.id.guid, drwavGUID_W64_DATA)) {
                foundDataChunk = DRWAV_TRUE;
                dataChunkSize = chunkSize;
            }
        }
        if (foundDataChunk && sequential) {
            break;
        }
        if (pWav->container == drwav_container_riff) {
            if (drwav_fourcc_equal(header.id.fourcc, "fact")) {
                drwav_uint32 sampleCount;
                if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
                    return DRWAV_FALSE;
                }
                chunkSize -= 4;
                if (!foundDataChunk) {
                    pWav->dataChunkDataPos = cursor;
                }
                if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
                    sampleCountFromFactChunk = sampleCount;
                } else {
                    sampleCountFromFactChunk = 0;
                }
            }
        } else if (pWav->container == drwav_container_w64) {
            if (drwav_guid_equal(header.id.guid, drwavGUID_W64_FACT)) {
                if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
                    return DRWAV_FALSE;
                }
                chunkSize -= 8;
                if (!foundDataChunk) {
                    pWav->dataChunkDataPos = cursor;
                }
            }
        } else if (pWav->container == drwav_container_rf64) {
        }
        chunkSize += header.paddingSize;
        if (!drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData)) {
            break;
        }
        cursor += chunkSize;
        if (!foundDataChunk) {
            pWav->dataChunkDataPos = cursor;
        }
    }
    pWav->pMetadata     = metadataParser.pMetadata;
    pWav->metadataCount = metadataParser.metadataCount;
    if (!foundDataChunk) {
        return DRWAV_FALSE;
    }
    if (!sequential) {
        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);
}

share/public_html/static/music_worklet_inprogress/decoder/deps/miniaudio/miniaudio.h  view on Meta::CPAN

            if (!drwav_seek_to_first_pcm_frame(pWav)) {
                return DRWAV_FALSE;
            }
        }
        if (targetFrameIndex > pWav->readCursorInPCMFrames) {
            drwav_uint64 offsetInFrames = targetFrameIndex - pWav->readCursorInPCMFrames;
            drwav_int16 devnull[2048];
            while (offsetInFrames > 0) {
                drwav_uint64 framesRead = 0;
                drwav_uint64 framesToRead = offsetInFrames;
                if (framesToRead > drwav_countof(devnull)/pWav->channels) {
                    framesToRead = drwav_countof(devnull)/pWav->channels;
                }
                if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
                    framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
                } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
                    framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
                } else {
                    DRWAV_ASSERT(DRWAV_FALSE);
                }
                if (framesRead != framesToRead) {
                    return DRWAV_FALSE;
                }
                offsetInFrames -= framesRead;
            }
        }
    } else {
        drwav_uint64 totalSizeInBytes;
        drwav_uint64 currentBytePos;
        drwav_uint64 targetBytePos;
        drwav_uint64 offset;
        drwav_uint32 bytesPerFrame;
        bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
        if (bytesPerFrame == 0) {
            return DRWAV_FALSE;
        }
        totalSizeInBytes = pWav->totalPCMFrameCount * bytesPerFrame;
        DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);
        currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
        targetBytePos  = targetFrameIndex * bytesPerFrame;
        if (currentBytePos < targetBytePos) {
            offset = (targetBytePos - currentBytePos);
        } else {
            if (!drwav_seek_to_first_pcm_frame(pWav)) {
                return DRWAV_FALSE;
            }
            offset = targetBytePos;
        }
        while (offset > 0) {
            int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
            if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
                return DRWAV_FALSE;
            }
            pWav->readCursorInPCMFrames += offset32 / bytesPerFrame;
            pWav->bytesRemaining        -= offset32;
            offset                      -= offset32;
        }
    }
    return DRWAV_TRUE;
}
DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(drwav* pWav, drwav_uint64* pCursor)
{
    if (pCursor == NULL) {
        return DRWAV_INVALID_ARGS;
    }
    *pCursor = 0;
    if (pWav == NULL) {
        return DRWAV_INVALID_ARGS;
    }
    *pCursor = pWav->readCursorInPCMFrames;
    return DRWAV_SUCCESS;
}
DRWAV_API drwav_result drwav_get_length_in_pcm_frames(drwav* pWav, drwav_uint64* pLength)
{
    if (pLength == NULL) {
        return DRWAV_INVALID_ARGS;
    }
    *pLength = 0;
    if (pWav == NULL) {
        return DRWAV_INVALID_ARGS;
    }
    *pLength = pWav->totalPCMFrameCount;
    return DRWAV_SUCCESS;
}
DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData)
{
    size_t bytesWritten;
    if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
        return 0;
    }
    bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
    pWav->dataChunkDataSize += bytesWritten;
    return bytesWritten;
}
DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
{
    drwav_uint64 bytesToWrite;
    drwav_uint64 bytesWritten;
    const drwav_uint8* pRunningData;
    if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
        return 0;
    }
    bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
    if (bytesToWrite > DRWAV_SIZE_MAX) {
        return 0;
    }
    bytesWritten = 0;
    pRunningData = (const drwav_uint8*)pData;
    while (bytesToWrite > 0) {
        size_t bytesJustWritten;
        drwav_uint64 bytesToWriteThisIteration;
        bytesToWriteThisIteration = bytesToWrite;
        DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX);
        bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
        if (bytesJustWritten == 0) {
            break;
        }
        bytesToWrite -= bytesJustWritten;
        bytesWritten += bytesJustWritten;
        pRunningData += bytesJustWritten;
    }



( run in 1.789 second using v1.01-cache-2.11-cpan-39bf76dae61 )