App-MHFS

 view release on metacpan or  search on metacpan

share/public_html/static/hls.js  view on Meta::CPAN

function task_loop__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function task_loop__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.cre...



/**
 * Sub-class specialization of EventHandler base class.
 *
 * TaskLoop allows to schedule a task function being called (optionnaly repeatedly) on the main loop,
 * scheduled asynchroneously, avoiding recursive calls in the same tick.
 *
 * The task itself is implemented in `doTick`. It can be requested and called for single execution
 * using the `tick` method.
 *
 * It will be assured that the task execution method (`tick`) only gets called once per main loop "tick",
 * no matter how often it gets requested for execution. Execution in further ticks will be scheduled accordingly.
 *
 * If further execution requests have already been scheduled on the next tick, it can be checked with `hasNextTick`,
 * and cancelled with `clearNextTick`.
 *
 * The task can be scheduled as an interval repeatedly with a period as parameter (see `setInterval`, `clearInterval`).
 *
 * Sub-classes need to implement the `doTick` method which will effectively have the task execution routine.
 *
 * Further explanations:
 *
 * The baseclass has a `tick` method that will schedule the doTick call. It may be called synchroneously
 * only for a stack-depth of one. On re-entrant calls, sub-sequent calls are scheduled for next main loop ticks.
 *
 * When the task execution (`tick` method) is called in re-entrant way this is detected and
 * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
 * task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
 */

var TaskLoop = function (_EventHandler) {
  task_loop__inherits(TaskLoop, _EventHandler);

share/public_html/static/hls.js  view on Meta::CPAN

    // level 1 loaded [182580164,182580171]
    //
    // don't return null in case media not loaded yet (readystate === 0)
    if (levelDetails.PTSKnown && bufferEnd > end && media && media.readyState) {
      return null;
    }

    if (this.startFragRequested && !levelDetails.PTSKnown) {
      /* we are switching level on live playlist, but we don't have any PTS info for that quality level ...
         try to load frag matching with next SN.
         even if SN are not synchronized between playlists, loading this frag will help us
         compute playlist sliding and find the right one after in case it was not the right consecutive one */
      if (fragPrevious) {
        if (!levelDetails.programDateTime) {
          // Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE)
          var targetSN = fragPrevious.sn + 1;
          if (targetSN >= levelDetails.startSN && targetSN <= levelDetails.endSN) {
            var fragNext = fragments[targetSN - levelDetails.startSN];
            if (fragPrevious.cc === fragNext.cc) {
              frag = fragNext;
              logger["b" /* logger */].log('live playlist, switching playlist, load frag with next SN: ' + frag.sn);

share/public_html/static/hls.js  view on Meta::CPAN

          // Only reset the backtracked flag if we've loaded the frag without any dropped frames
          frag.backtracked = false;
        }
      }

      var drift = updateFragPTSDTS(level.details, frag, data.startPTS, data.endPTS, data.startDTS, data.endDTS),
          hls = this.hls;
      hls.trigger(events["a" /* default */].LEVEL_PTS_UPDATED, { details: level.details, level: this.level, drift: drift, type: data.type, start: data.startPTS, end: data.endPTS });
      // has remuxer dropped video frames located before first keyframe ?
      [data.data1, data.data2].forEach(function (buffer) {
        // only append in PARSING state (rationale is that an appending error could happen synchronously on first segment appending)
        // in that case it is useless to append following segments
        if (buffer && buffer.length && _this2.state === State.PARSING) {
          _this2.appended = true;
          // arm pending Buffering flag before appending a segment
          _this2.pendingBuffering = true;
          hls.trigger(events["a" /* default */].BUFFER_APPENDING, { type: data.type, data: buffer, parent: 'main', content: 'data' });
        }
      });
      // trigger handler right now
      this.tick();

share/public_html/static/hls.js  view on Meta::CPAN

            hls.trigger(events["a" /* default */].ERROR, event);
          }
        }
      }
    }
  };

  /*
    flush specified buffered range,
    return true once range has been flushed.
    as sourceBuffer.remove() is asynchronous, flushBuffer will be retriggered on sourceBuffer update end
  */


  BufferController.prototype.flushBuffer = function flushBuffer(startOffset, endOffset, typeIn) {
    var sb = void 0,
        i = void 0,
        bufStart = void 0,
        bufEnd = void 0,
        flushStart = void 0,
        flushEnd = void 0,

share/public_html/static/hls.js  view on Meta::CPAN

      }

      if (!this.audioSwitch) {
        [data.data1, data.data2].forEach(function (buffer) {
          if (buffer && buffer.length) {
            pendingData.push({ type: data.type, data: buffer, parent: 'audio', content: 'data' });
          }
        });
        if (!appendOnBufferFlush && pendingData.length) {
          pendingData.forEach(function (appendObj) {
            // only append in PARSING state (rationale is that an appending error could happen synchronously on first segment appending)
            // in that case it is useless to append following segments
            if (_this2.state === audio_stream_controller_State.PARSING) {
              // arm pending Buffering flag before appending a segment
              _this2.pendingBuffering = true;
              _this2.hls.trigger(events["a" /* default */].BUFFER_APPENDING, appendObj);
            }
          });
          this.pendingData = [];
          this.appended = true;
        }

share/public_html/static/hls.js  view on Meta::CPAN

        }
      }
    }
    if (!merged) {
      ranges.push([startTime, endTime]);
    }

    this.Cues.newCue(this.captionsTracks[trackName], startTime, endTime, screen);
  };

  // Triggered when an initial PTS is found; used for synchronisation of WebVTT.


  TimelineController.prototype.onInitPtsFound = function onInitPtsFound(data) {
    var _this2 = this;

    if (typeof this.initPTS === 'undefined') {
      this.initPTS = data.initPTS;
    }

    // Due to asynchrony, initial PTS may arrive later than the first VTT fragments are loaded.
    // Parse any unparsed fragments upon receiving the initial PTS.
    if (this.unparsedVttFrags.length) {
      this.unparsedVttFrags.forEach(function (frag) {
        _this2.onFragLoaded(frag);
      });
      this.unparsedVttFrags = [];
    }
  };

  TimelineController.prototype.getExistingTrack = function getExistingTrack(trackName) {

share/public_html/static/hls.js  view on Meta::CPAN

        var cea608Parser = this.cea608Parser;
        if (cea608Parser) {
          cea608Parser.reset();
        }
      }
      this.lastSn = sn;
    } // eslint-disable-line brace-style
    // If fragment is subtitle type, parse as WebVTT.
    else if (frag.type === 'subtitle') {
        if (payload.byteLength) {
          // We need an initial synchronisation PTS. Store fragments as long as none has arrived.
          if (typeof this.initPTS === 'undefined') {
            this.unparsedVttFrags.push(data);
            return;
          }

          var decryptData = frag.decryptdata;
          // If the subtitles are not encrypted, parse VTTs now. Otherwise, we need to wait.
          if (decryptData == null || decryptData.key == null || decryptData.method !== 'AES-128') {
            this._parseVTTs(frag, payload);
          }

share/public_html/static/music_inc/drflac.js  view on Meta::CPAN


var Module = (() => {
  var _scriptName = import.meta.url;
  
  return (
async function(moduleArg = {}) {
  var moduleRtn;

var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});["_network_drflac_open_mem","_network_drflac_read_pcm_frames_f32_mem","_network_dr...


  return moduleRtn;
}
);
})();
export default Module;

share/public_html/static/music_inc/src/dr_flac.h  view on Meta::CPAN

  be used if available. Otherwise the seek will be performed using brute force.

#define DR_FLAC_NO_SIMD
  Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having compatibility issues with your compiler.



Notes
=====
- dr_flac does not support changing the sample rate nor channel count mid stream.
- dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
- When using Ogg encapsulation, a corrupted metadata block will result in `drflac_open_with_metadata()` and `drflac_open()` returning inconsistent samples due
  to differences in corrupted stream recorvery logic between the two APIs.
*/

#ifndef dr_flac_h
#define dr_flac_h

#ifdef __cplusplus
extern "C" {
#endif

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

miniaudio is a single file library for audio playback and capture. To use it, do the following in one .c file:

    ```c
    #define MINIAUDIO_IMPLEMENTATION
    #include "miniaudio.h"
    ```

You can do `#include "miniaudio.h"` in other parts of the program just like any other header.

miniaudio uses the concept of a "device" as the abstraction for physical devices. The idea is that you choose a physical device to emit or capture audio from,
and then move data to/from the device when miniaudio tells you to. Data is delivered to and from devices asynchronously via a callback which you specify when
initializing the device.

When initializing the device you first need to configure it. The device configuration allows you to specify things like the format of the data delivered via
the callback, the size of the internal buffer and the ID of the device you want to emit or capture audio from.

Once you have the device configuration set up you can initialize the device. When initializing a device you need to allocate memory for the device object
beforehand. This gives the application complete control over how the memory is allocated. In the example below we initialize a playback device on the stack,
but you could allocate it on the heap if that suits your situation better.

    ```c

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    ma_thread_priority threadPriority;
    size_t threadStackSize;
    void* pUserData;
    ma_allocation_callbacks allocationCallbacks;
    ma_mutex deviceEnumLock;               /* Used to make ma_context_get_devices() thread safe. */
    ma_mutex deviceInfoLock;               /* Used to make ma_context_get_device_info() thread safe. */
    ma_uint32 deviceInfoCapacity;          /* Total capacity of pDeviceInfos. */
    ma_uint32 playbackDeviceInfoCount;
    ma_uint32 captureDeviceInfoCount;
    ma_device_info* pDeviceInfos;          /* Playback devices first, then capture. */
    ma_bool32 isBackendAsynchronous : 1;   /* Set when the context is initialized. Set to 1 for asynchronous backends such as Core Audio and JACK. Do not modify. */

    ma_result (* onUninit        )(ma_context* pContext);
    ma_bool32 (* onDeviceIDEqual )(ma_context* pContext, const ma_device_id* pID0, const ma_device_id* pID1);
    ma_result (* onEnumDevices   )(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData);    /* Return false from the callback to stop enumeration. */
    ma_result (* onGetDeviceInfo )(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_share_mode shareMode, ma_device_info* pDeviceInfo);
    ma_result (* onDeviceInit    )(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice);
    void      (* onDeviceUninit  )(ma_device* pDevice);
    ma_result (* onDeviceStart   )(ma_device* pDevice);
    ma_result (* onDeviceStop    )(ma_device* pDevice);
    ma_result (* onDeviceMainLoop)(ma_device* pDevice);

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN



Return Value
------------
MA_SUCCESS if successful; any other error code otherwise.


Thread Safety
-------------
Unsafe. Since each call to this function invalidates the pointers from the previous call, you should not be calling this simultaneously across multiple
threads. Instead, you need to make a copy of the returned data with your own higher level synchronization.


Remarks
-------
It is _not_ safe to assume the first device in the list is the default device.

You can pass in NULL for the playback or capture lists in which case they'll be ignored.

The returned pointers will become invalid upon the next call this this function, or when the context is uninitialized. Do not free the returned pointers.

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    ma_resource_format_wav
} ma_resource_format;
#endif

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

Decoding
========

Decoders are independent of the main device API. Decoding APIs can be called freely inside the device's data callback, but they are not thread safe unless
you do your own synchronization.

************************************************************************************************************************************************************/
#ifndef MA_NO_DECODING
typedef struct ma_decoder ma_decoder;

typedef size_t    (* ma_decoder_read_proc)                    (ma_decoder* pDecoder, void* pBufferOut, size_t bytesToRead);     /* Returns the number of bytes read. */
typedef ma_bool32 (* ma_decoder_seek_proc)                    (ma_decoder* pDecoder, int byteOffset, ma_seek_origin origin);    /* Origin will never be ma_seek_origin_end. */
typedef ma_uint64 (* ma_decoder_read_pcm_frames_proc)         (ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount);   /* Returns the number of frames read. Output data is in internal format. */
typedef ma_result (* ma_decoder_seek_to_pcm_frame_proc)       (ma_decoder* pDecoder, ma_uint64 frameIndex);
typedef ma_result (* ma_decoder_uninit_proc)                  (ma_decoder* pDecoder);

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN


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_uint64 ma_decoder_get_length_in_pcm_frames(ma_decoder* pDecoder);

/*
Reads PCM frames from the given decoder.

This is not thread safe without your own synchronization.
*/
MA_API ma_uint64 ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesOut, ma_uint64 frameCount);

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

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    #define c89atomic_compare_and_swap_32(dst, expected, desired)   __sync_val_compare_and_swap(dst, expected, desired)
    #define c89atomic_compare_and_swap_64(dst, expected, desired)   __sync_val_compare_and_swap(dst, expected, desired)
#else
    #define c89atomic_memory_order_relaxed  1
    #define c89atomic_memory_order_consume  2
    #define c89atomic_memory_order_acquire  3
    #define c89atomic_memory_order_release  4
    #define c89atomic_memory_order_acq_rel  5
    #define c89atomic_memory_order_seq_cst  6
    #define c89atomic_compiler_fence()      __asm__ __volatile__("":::"memory")
    #define c89atomic_thread_fence(order)   __sync_synchronize()
    #define c89atomic_signal_fence(order)   c89atomic_thread_fence(order)
    static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_exchange_explicit_8(volatile c89atomic_uint8* dst, c89atomic_uint8 src, c89atomic_memory_order order)
    {
        if (order > c89atomic_memory_order_acquire) {
            __sync_synchronize();
        }
        return __sync_lock_test_and_set(dst, src);
    }
    static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_exchange_explicit_16(volatile c89atomic_uint16* dst, c89atomic_uint16 src, c89atomic_memory_order order)
    {
        volatile c89atomic_uint16 oldValue;
        do {
            oldValue = *dst;
        } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
        (void)order;

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

            totalClientFramesProcessed  += clientFramesProcessedThisIteration;

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


/* We only want to expose ma_device__handle_duplex_callback_capture() and ma_device__handle_duplex_callback_playback() if we have an asynchronous backend enabled. */
#if defined(MA_HAS_JACK)      || \
    defined(MA_HAS_COREAUDIO) || \
    defined(MA_HAS_AAUDIO)    || \
    defined(MA_HAS_OPENSL)    || \
    defined(MA_HAS_WEBAUDIO)
static ma_result ma_device__handle_duplex_callback_capture(ma_device* pDevice, ma_uint32 frameCountInDeviceFormat, const void* pFramesInDeviceFormat, ma_pcm_rb* pRB)
{
    ma_result result;
    ma_uint32 totalDeviceFramesProcessed = 0;
    const void* pRunningFramesInDeviceFormat = pFramesInDeviceFormat;

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

            ma_data_converter_process_pcm_frames(&pDevice->playback.converter, playbackFramesInExternalFormat, &framesConvertedIn, pFramesInInternalFormat, &framesConvertedOut);

            totalFramesReadFromClient += (ma_uint32)framesConvertedIn;  /* Safe cast. */
            totalFramesReadOut        += (ma_uint32)framesConvertedOut; /* Safe cast. */
            pFramesInInternalFormat    = ma_offset_ptr(pFramesInInternalFormat, framesConvertedOut * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
        }
    }

    return MA_SUCCESS;
}
#endif  /* Asynchronous backends. */

/* A helper for changing the state of the device. */
static MA_INLINE void ma_device__set_state(ma_device* pDevice, ma_uint32 newState)
{
    c89atomic_exchange_32(&pDevice->state, newState);
}

/* A helper for getting the state of the device. */
static MA_INLINE ma_uint32 ma_device__get_state(ma_device* pDevice)
{

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    MA_ASSERT(pContext != NULL);

    (void)pConfig;

    pContext->onUninit         = ma_context_uninit__null;
    pContext->onDeviceIDEqual  = ma_context_is_device_id_equal__null;
    pContext->onEnumDevices    = ma_context_enumerate_devices__null;
    pContext->onGetDeviceInfo  = ma_context_get_device_info__null;
    pContext->onDeviceInit     = ma_device_init__null;
    pContext->onDeviceUninit   = ma_device_uninit__null;
    pContext->onDeviceStart    = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceStop     = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceMainLoop = ma_device_main_loop__null;

    /* The null backend always works. */
    return MA_SUCCESS;
}
#endif



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

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    Not currently supporting automatic stream routing in exclusive mode. This is not working correctly on my machine due to
    AUDCLNT_E_DEVICE_IN_USE errors when reinitializing the device. If this is a bug in miniaudio, we can try re-enabling this once
    it's fixed.
    */
    if ((dataFlow == ma_eRender  && pThis->pDevice->playback.shareMode == ma_share_mode_exclusive) ||
        (dataFlow == ma_eCapture && pThis->pDevice->capture.shareMode  == ma_share_mode_exclusive)) {
        return S_OK;
    }

    /*
    We don't change the device here - we change it in the worker thread to keep synchronization simple. To do this I'm just setting a flag to
    indicate that the default device has changed. Loopback devices are treated as capture devices so we need to do a bit of a dance to handle
    that properly.
    */
    if (dataFlow == ma_eRender  && pThis->pDevice->type != ma_device_type_loopback) {
        c89atomic_exchange_32(&pThis->pDevice->wasapi.hasDefaultPlaybackDeviceChanged, MA_TRUE);
    }
    if (dataFlow == ma_eCapture || pThis->pDevice->type == ma_device_type_loopback) {
        c89atomic_exchange_32(&pThis->pDevice->wasapi.hasDefaultCaptureDeviceChanged,  MA_TRUE);
    }

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    pContext->winmm.waveInAddBuffer        = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInAddBuffer");
    pContext->winmm.waveInStart            = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInStart");
    pContext->winmm.waveInReset            = ma_dlsym(pContext, pContext->winmm.hWinMM, "waveInReset");

    pContext->onUninit         = ma_context_uninit__winmm;
    pContext->onDeviceIDEqual  = ma_context_is_device_id_equal__winmm;
    pContext->onEnumDevices    = ma_context_enumerate_devices__winmm;
    pContext->onGetDeviceInfo  = ma_context_get_device_info__winmm;
    pContext->onDeviceInit     = ma_device_init__winmm;
    pContext->onDeviceUninit   = ma_device_uninit__winmm;
    pContext->onDeviceStart    = NULL; /* Not used with synchronous backends. */
    pContext->onDeviceStop     = NULL; /* Not used with synchronous backends. */
    pContext->onDeviceMainLoop = ma_device_main_loop__winmm;

    return MA_SUCCESS;
}
#endif




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

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    pContext->jack.jack_get_ports                = (ma_proc)_jack_get_ports;
    pContext->jack.jack_activate                 = (ma_proc)_jack_activate;
    pContext->jack.jack_deactivate               = (ma_proc)_jack_deactivate;
    pContext->jack.jack_connect                  = (ma_proc)_jack_connect;
    pContext->jack.jack_port_register            = (ma_proc)_jack_port_register;
    pContext->jack.jack_port_name                = (ma_proc)_jack_port_name;
    pContext->jack.jack_port_get_buffer          = (ma_proc)_jack_port_get_buffer;
    pContext->jack.jack_free                     = (ma_proc)_jack_free;
#endif

    pContext->isBackendAsynchronous = MA_TRUE;

    pContext->onUninit        = ma_context_uninit__jack;
    pContext->onDeviceIDEqual = ma_context_is_device_id_equal__jack;
    pContext->onEnumDevices   = ma_context_enumerate_devices__jack;
    pContext->onGetDeviceInfo = ma_context_get_device_info__jack;
    pContext->onDeviceInit    = ma_device_init__jack;
    pContext->onDeviceUninit  = ma_device_uninit__jack;
    pContext->onDeviceStart   = ma_device_start__jack;
    pContext->onDeviceStop    = ma_device_stop__jack;

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    pContext->coreaudio.AudioOutputUnitStart              = (ma_proc)AudioOutputUnitStart;
    pContext->coreaudio.AudioOutputUnitStop               = (ma_proc)AudioOutputUnitStop;
    pContext->coreaudio.AudioUnitAddPropertyListener      = (ma_proc)AudioUnitAddPropertyListener;
    pContext->coreaudio.AudioUnitGetPropertyInfo          = (ma_proc)AudioUnitGetPropertyInfo;
    pContext->coreaudio.AudioUnitGetProperty              = (ma_proc)AudioUnitGetProperty;
    pContext->coreaudio.AudioUnitSetProperty              = (ma_proc)AudioUnitSetProperty;
    pContext->coreaudio.AudioUnitInitialize               = (ma_proc)AudioUnitInitialize;
    pContext->coreaudio.AudioUnitRender                   = (ma_proc)AudioUnitRender;
#endif

    pContext->isBackendAsynchronous = MA_TRUE;
    
    pContext->onUninit        = ma_context_uninit__coreaudio;
    pContext->onDeviceIDEqual = ma_context_is_device_id_equal__coreaudio;
    pContext->onEnumDevices   = ma_context_enumerate_devices__coreaudio;
    pContext->onGetDeviceInfo = ma_context_get_device_info__coreaudio;
    pContext->onDeviceInit    = ma_device_init__coreaudio;
    pContext->onDeviceUninit  = ma_device_uninit__coreaudio;
    pContext->onDeviceStart   = ma_device_start__coreaudio;
    pContext->onDeviceStop    = ma_device_stop__coreaudio;
    

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    pContext->sndio.sio_stop    = sio_stop;
    pContext->sndio.sio_initpar = sio_initpar;
#endif

    pContext->onUninit         = ma_context_uninit__sndio;
    pContext->onDeviceIDEqual  = ma_context_is_device_id_equal__sndio;
    pContext->onEnumDevices    = ma_context_enumerate_devices__sndio;
    pContext->onGetDeviceInfo  = ma_context_get_device_info__sndio;
    pContext->onDeviceInit     = ma_device_init__sndio;
    pContext->onDeviceUninit   = ma_device_uninit__sndio;
    pContext->onDeviceStart    = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceStop     = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceMainLoop = ma_device_main_loop__sndio;

    (void)pConfig;
    return MA_SUCCESS;
}
#endif  /* sndio */



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

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    MA_ASSERT(pContext != NULL);

    (void)pConfig;

    pContext->onUninit         = ma_context_uninit__audio4;
    pContext->onDeviceIDEqual  = ma_context_is_device_id_equal__audio4;
    pContext->onEnumDevices    = ma_context_enumerate_devices__audio4;
    pContext->onGetDeviceInfo  = ma_context_get_device_info__audio4;
    pContext->onDeviceInit     = ma_device_init__audio4;
    pContext->onDeviceUninit   = ma_device_uninit__audio4;
    pContext->onDeviceStart    = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceStop     = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceMainLoop = ma_device_main_loop__audio4;

    return MA_SUCCESS;
}
#endif  /* audio4 */


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

OSS Backend

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN


    pContext->oss.versionMajor = ((ossVersion & 0xFF0000) >> 16);
    pContext->oss.versionMinor = ((ossVersion & 0x00FF00) >> 8);

    pContext->onUninit         = ma_context_uninit__oss;
    pContext->onDeviceIDEqual  = ma_context_is_device_id_equal__oss;
    pContext->onEnumDevices    = ma_context_enumerate_devices__oss;
    pContext->onGetDeviceInfo  = ma_context_get_device_info__oss;
    pContext->onDeviceInit     = ma_device_init__oss;
    pContext->onDeviceUninit   = ma_device_uninit__oss;
    pContext->onDeviceStart    = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceStop     = NULL; /* Not required for synchronous backends. */
    pContext->onDeviceMainLoop = ma_device_main_loop__oss;

    close(fd);
    return MA_SUCCESS;
}
#endif  /* OSS */


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

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    pContext->aaudio.AAudioStream_waitForStateChange               = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_waitForStateChange");
    pContext->aaudio.AAudioStream_getFormat                        = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFormat");
    pContext->aaudio.AAudioStream_getChannelCount                  = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getChannelCount");
    pContext->aaudio.AAudioStream_getSampleRate                    = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getSampleRate");
    pContext->aaudio.AAudioStream_getBufferCapacityInFrames        = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getBufferCapacityInFrames");
    pContext->aaudio.AAudioStream_getFramesPerDataCallback         = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerDataCallback");
    pContext->aaudio.AAudioStream_getFramesPerBurst                = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_getFramesPerBurst");
    pContext->aaudio.AAudioStream_requestStart                     = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStart");
    pContext->aaudio.AAudioStream_requestStop                      = (ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio, "AAudioStream_requestStop");

    pContext->isBackendAsynchronous = MA_TRUE;

    pContext->onUninit        = ma_context_uninit__aaudio;
    pContext->onDeviceIDEqual = ma_context_is_device_id_equal__aaudio;
    pContext->onEnumDevices   = ma_context_enumerate_devices__aaudio;
    pContext->onGetDeviceInfo = ma_context_get_device_info__aaudio;
    pContext->onDeviceInit    = ma_device_init__aaudio;
    pContext->onDeviceUninit  = ma_device_uninit__aaudio;
    pContext->onDeviceStart   = ma_device_start__aaudio;
    pContext->onDeviceStop    = ma_device_stop__aaudio;

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    {
        result = ma_context_init_engine_nolock__opensl(pContext);
    }
    ma_spinlock_unlock(&g_maOpenSLSpinlock);

    if (result != MA_SUCCESS) {
        return result;  /* Failed to initialize the OpenSL engine. */
    }


    pContext->isBackendAsynchronous = MA_TRUE;

    pContext->onUninit        = ma_context_uninit__opensl;
    pContext->onDeviceIDEqual = ma_context_is_device_id_equal__opensl;
    pContext->onEnumDevices   = ma_context_enumerate_devices__opensl;
    pContext->onGetDeviceInfo = ma_context_get_device_info__opensl;
    pContext->onDeviceInit    = ma_device_init__opensl;
    pContext->onDeviceUninit  = ma_device_uninit__opensl;
    pContext->onDeviceStart   = ma_device_start__opensl;
    pContext->onDeviceStop    = ma_device_stop__opensl;

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

        }
                
        return 1;
    }, 0);  /* Must pass in a dummy argument for C99 compatibility. */

    if (resultFromJS != 1) {
        return MA_FAILED_TO_INIT_BACKEND;
    }


    pContext->isBackendAsynchronous = MA_TRUE;

    pContext->onUninit              = ma_context_uninit__webaudio;
    pContext->onDeviceIDEqual       = ma_context_is_device_id_equal__webaudio;
    pContext->onEnumDevices         = ma_context_enumerate_devices__webaudio;
    pContext->onGetDeviceInfo       = ma_context_get_device_info__webaudio;
    pContext->onDeviceInit          = ma_device_init__webaudio;
    pContext->onDeviceUninit        = ma_device_uninit__webaudio;
    pContext->onDeviceStart         = ma_device_start__webaudio;
    pContext->onDeviceStop          = ma_device_stop__webaudio;

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

#ifdef MA_WIN32
    result = ma_context_uninit_backend_apis__win32(pContext);
#else
    result = ma_context_uninit_backend_apis__nix(pContext);
#endif

    return result;
}


static ma_bool32 ma_context_is_backend_asynchronous(ma_context* pContext)
{
    return pContext->isBackendAsynchronous;
}


MA_API ma_context_config ma_context_config_init()
{
    ma_context_config config;
    MA_ZERO_OBJECT(&config);

    return config;
}

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
        if (pDevice->playback.name[0] == '\0') {
            if (ma_context__try_get_device_name_by_id(pContext, ma_device_type_playback, config.playback.pDeviceID, pDevice->playback.name, sizeof(pDevice->playback.name)) != MA_SUCCESS) {
                ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), (config.playback.pDeviceID == NULL)  ? MA_DEFAULT_PLAYBACK_DEVICE_NAME : "Playback Device", (size_t)-1);
            }
        }
    }


    /* Some backends don't require the worker thread. */
    if (!ma_context_is_backend_asynchronous(pContext)) {
        /* The worker thread. */
        result = ma_thread_create(&pDevice->thread, pContext->threadPriority, pContext->threadStackSize, ma_worker_thread, pDevice);
        if (result != MA_SUCCESS) {
            ma_device_uninit(pDevice);
            return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create worker thread.", result);
        }

        /* Wait for the worker thread to put the device into it's stopped state for real. */
        ma_event_wait(&pDevice->stopEvent);
    } else {

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN


    /* Make sure the device is stopped first. The backends will probably handle this naturally, but I like to do it explicitly for my own sanity. */
    if (ma_device_is_started(pDevice)) {
        ma_device_stop(pDevice);
    }

    /* Putting the device into an uninitialized state will make the worker thread return. */
    ma_device__set_state(pDevice, MA_STATE_UNINITIALIZED);

    /* Wake up the worker thread and wait for it to properly terminate. */
    if (!ma_context_is_backend_asynchronous(pDevice->pContext)) {
        ma_event_signal(&pDevice->wakeupEvent);
        ma_thread_wait(&pDevice->thread);
    }

    pDevice->pContext->onDeviceUninit(pDevice);

    ma_event_uninit(&pDevice->stopEvent);
    ma_event_uninit(&pDevice->startEvent);
    ma_event_uninit(&pDevice->wakeupEvent);
    ma_mutex_uninit(&pDevice->lock);

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN

    }

    result = MA_ERROR;
    ma_mutex_lock(&pDevice->lock);
    {
        /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
        MA_ASSERT(ma_device__get_state(pDevice) == MA_STATE_STOPPED);

        ma_device__set_state(pDevice, MA_STATE_STARTING);

        /* Asynchronous backends need to be handled differently. */
        if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
            result = pDevice->pContext->onDeviceStart(pDevice);
            if (result == MA_SUCCESS) {
                ma_device__set_state(pDevice, MA_STATE_STARTED);
            }
        } else {
            /*
            Synchronous backends are started by signaling an event that's being waited on in the worker thread. We first wake up the
            thread and then wait for the start event.
            */
            ma_event_signal(&pDevice->wakeupEvent);

share/public_html/static/music_inc/src/miniaudio.h  view on Meta::CPAN


        ma_device__set_state(pDevice, MA_STATE_STOPPING);

        /* There's no need to wake up the thread like we do when starting. */
        if (pDevice->pContext->onDeviceStop) {
            result = pDevice->pContext->onDeviceStop(pDevice);
        } else {
            result = MA_SUCCESS;
        }

        /* Asynchronous backends need to be handled differently. */
        if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
            ma_device__set_state(pDevice, MA_STATE_STOPPED);
        } else {
            /* Synchronous backends. */

            /*
            We need to wait for the worker thread to become available for work before returning. Note that the worker thread will be
            the one who puts the device into the stopped state. Don't call ma_device__set_state() here.
            */
            ma_event_wait(&pDevice->stopEvent);
            result = MA_SUCCESS;

share/public_html/static/music_worklet_inprogress/decoder/bin/_mhfscl.js  view on Meta::CPAN


var Module = (() => {
  var _scriptName = import.meta.url;
  
  return (
async function(moduleArg = {}) {
  var moduleRtn;

var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof im...


  return moduleRtn;
}
);
})();
export default Module;

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

  be used if available. Otherwise the seek will be performed using brute force.

#define DR_FLAC_NO_SIMD
  Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having compatibility issues with your compiler.



Notes
=====
- dr_flac does not support changing the sample rate nor channel count mid stream.
- dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
- When using Ogg encapsulation, a corrupted metadata block will result in `drflac_open_with_metadata()` and `drflac_open()` returning inconsistent samples due
  to differences in corrupted stream recorvery logic between the two APIs.
*/

#ifndef dr_flac_h
#define dr_flac_h

#ifdef __cplusplus
extern "C" {
#endif

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



1.1. Low Level API
------------------
The low level API gives you access to the raw audio data of an audio device. It supports playback,
capture, full-duplex and loopback (WASAPI only). You can enumerate over devices to determine which
physical device(s) you want to connect to.

The low level API uses the concept of a "device" as the abstraction for physical devices. The idea
is that you choose a physical device to emit or capture audio from, and then move data to/from the
device when miniaudio tells you to. Data is delivered to and from devices asynchronously via a
callback which you specify when initializing the device.

When initializing the device you first need to configure it. The device configuration allows you to
specify things like the format of the data delivered via the callback, the size of the internal
buffer and the ID of the device you want to emit or capture audio from.

Once you have the device configuration set up you can initialize the device. When initializing a
device you need to allocate memory for the device object beforehand. This gives the application
complete control over how the memory is allocated. In the example below we initialize a playback
device on the stack, but you could allocate it on the heap if that suits your situation better.

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


    ```c
    ma_sound_set_start_time_in_pcm_frames()
    ma_sound_set_start_time_in_milliseconds()
    ma_sound_set_stop_time_in_pcm_frames()
    ma_sound_set_stop_time_in_milliseconds()
    ```

The start/stop time needs to be specified based on the absolute timer which is controlled by the
engine. The current global time time in PCM frames can be retrieved with `ma_engine_get_time()`.
The engine's global time can be changed with `ma_engine_set_time()` for synchronization purposes if
required. Note that scheduling a start time still requires an explicit call to `ma_sound_start()`
before anything will play:

    ```c
    ma_sound_set_start_time_in_pcm_frames(&sound, ma_engine_get_time(&engine) + (ma_engine_get_sample_rate(&engine) * 2);
    ma_sound_start(&sound);
    ```

The third parameter of `ma_sound_init_from_file()` is a set of flags that control how the sound be
loaded and a few options on which features should be enabled for that sound. By default, the sound
is synchronously loaded fully into memory straight from the file system without any kind of
decoding. If you want to decode the sound before storing it in memory, you need to specify the
`MA_SOUND_FLAG_DECODE` flag. This is useful if you want to incur the cost of decoding at an earlier
stage, such as a loading stage. Without this option, decoding will happen dynamically at mixing
time which might be too expensive on the audio thread.

If you want to load the sound asynchronously, you can specify the `MA_SOUND_FLAG_ASYNC` flag. This
will result in `ma_sound_init_from_file()` returning quickly, but the sound will not start playing
until the sound has had some audio decoded.

The fourth parameter is a pointer to sound group. A sound group is used as a mechanism to organise
sounds into groups which have their own effect processing and volume control. An example is a game
which might have separate groups for sfx, voice and music. Each of these groups have their own
independent volume control. Use `ma_sound_group_init()` or `ma_sound_group_init_ex()` to initialize
a sound group.

Sounds and sound groups are nodes in the engine's node graph and can be plugged into any `ma_node`

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

features are enabled for that sound. When no flags are set, the sound will be fully loaded into
memory in exactly the same format as how it's stored on the file system. The resource manager will
allocate a block of memory and then load the file directly into it. When reading audio data, it
will be decoded dynamically on the fly. In order to save processing time on the audio thread, it
might be beneficial to pre-decode the sound. You can do this with the `MA_SOUND_FLAG_DECODE` flag:

    ```c
    ma_sound_init_from_file(&engine, "my_sound.wav", MA_SOUND_FLAG_DECODE, pGroup, NULL, &sound);
    ```

By default, sounds will be loaded synchronously, meaning `ma_sound_init_*()` will not return until
the sound has been fully loaded. If this is prohibitive you can instead load sounds asynchronously
by specificying the `MA_SOUND_FLAG_ASYNC` flag:

    ```c
    ma_sound_init_from_file(&engine, "my_sound.wav", MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, pGroup, NULL, &sound);
    ```

This will result in `ma_sound_init_*()` returning quickly, but the sound won't yet have been fully
loaded. When you start the sound, it won't output anything until some sound is available. The sound
will start outputting audio before the sound has been fully decoded when the `MA_SOUND_FLAG_DECODE`
is specified.

If you need to wait for an asynchronously loaded sound to be fully loaded, you can use a fence. A
fence in miniaudio is a simple synchronization mechanism which simply blocks until it's internal
counter hit's zero. You can specify a fence like so:

    ```c
    ma_result result;
    ma_fence fence;
    ma_sound sounds[4];

    result = ma_fence_init(&fence);
    if (result != MA_SUCCES) {
        return result;
    }

    // Load some sounds asynchronously.
    for (int iSound = 0; iSound < 4; iSound += 1) {
        ma_sound_init_from_file(&engine, mySoundFilesPaths[iSound], MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, pGroup, &fence, &sounds[iSound]);
    }

    // ... do some other stuff here in the mean time ...

    // Wait for all sounds to finish loading.
    ma_fence_wait(&fence);
    ```

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

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

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

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

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


    resourceManagerConfig.ppCustomDecodingBackendVTables = pCustomBackendVTables;
    resourceManagerConfig.customDecodingBackendCount     = sizeof(pCustomBackendVTables) / sizeof(pCustomBackendVTables[0]);
    resourceManagerConfig.pCustomDecodingBackendUserData = NULL;
    ```

This system can allow you to support any kind of file format. See the "Decoding" section for
details on how to implement custom decoders. The miniaudio repository includes examples for Opus
via libopus and libopusfile and Vorbis via libvorbis and libvorbisfile.

Asynchronicity is achieved via a job system. When an operation needs to be performed, such as the
decoding of a page, a job will be posted to a queue which will then be processed by a job thread.
By default there will be only one job thread running, but this can be configured, like so:

    ```c
    config = ma_resource_manager_config_init();
    config.jobThreadCount = MY_JOB_THREAD_COUNT;
    ```

By default job threads are managed internally by the resource manager, however you can also self
manage your job threads if, for example, you want to integrate the job processing into your

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

    config = ma_resource_manager_config_init();
    config.pVFS = &vfs;
    ```

This is particularly useful in programs like games where you want to read straight from an archive
rather than the normal file system. If you do not specify a custom VFS, the resource manager will
use the operating system's normal file operations. This is default.

To load a sound file and create a data source, call `ma_resource_manager_data_source_init()`. When
loading a sound you need to specify the file path and options for how the sounds should be loaded.
By default a sound will be loaded synchronously. The returned data source is owned by the caller
which means the caller is responsible for the allocation and freeing of the data source. Below is
an example for initializing a data source:

    ```c
    ma_resource_manager_data_source dataSource;
    ma_result result = ma_resource_manager_data_source_init(pResourceManager, pFilePath, flags, &dataSource);
    if (result != MA_SUCCESS) {
        // Error.
    }

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

    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT
    ```

When no flags are specified (set to 0), the sound will be fully loaded into memory, but not
decoded, meaning the raw file data will be stored in memory, and then dynamically decoded when
`ma_data_source_read_pcm_frames()` is called. To instead decode the audio data before storing it in
memory, use the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE` flag. By default, the sound file will
be loaded synchronously, meaning `ma_resource_manager_data_source_init()` will only return after
the entire file has been loaded. This is good for simplicity, but can be prohibitively slow. You
can instead load the sound asynchronously using the `MA_RESOURCE_MANAGER_DATA_SOURCE_ASYNC` flag.
This will result in `ma_resource_manager_data_source_init()` returning quickly, but no data will be
returned by `ma_data_source_read_pcm_frames()` until some data is available. When no data is
available because the asynchronous decoding hasn't caught up, `MA_BUSY` will be returned by
`ma_data_source_read_pcm_frames()`.

For large sounds, it's often prohibitive to store the entire file in memory. To mitigate this, you
can instead stream audio data which you can do by specifying the
`MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` flag. When streaming, data will be decoded in 1
second pages. When a new page needs to be decoded, a job will be posted to the job queue and then
subsequently processed in a job thread.

For in-memory sounds, reference counting is used to ensure the data is loaded only once. This means
multiple calls to `ma_resource_manager_data_source_init()` with the same file path will result in

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

`MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` flag), the resource manager will look for these
explicitly registered data buffers and, if found, will use it as the backing data for the data
source. Note that the resource manager does *not* make a copy of this data so it is up to the
caller to ensure the pointer stays valid for it's lifetime. Use
`ma_resource_manager_unregister_data()` to unregister the self-managed data. You can also use
`ma_resource_manager_register_file()` and `ma_resource_manager_unregister_file()` to register and
unregister a file. It does not make sense to use the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM`
flag with a self-managed data pointer.


6.1. Asynchronous Loading and Synchronization
---------------------------------------------
When loading asynchronously, it can be useful to poll whether or not loading has finished. Use
`ma_resource_manager_data_source_result()` to determine this. For in-memory sounds, this will
return `MA_SUCCESS` when the file has been *entirely* decoded. If the sound is still being decoded,
`MA_BUSY` will be returned. Otherwise, some other error code will be returned if the sound failed
to load. For streaming data sources, `MA_SUCCESS` will be returned when the first page has been
decoded and the sound is ready to be played. If the first page is still being decoded, `MA_BUSY`
will be returned. Otherwise, some other error code will be returned if the sound failed to load.

In addition to polling, you can also use a simple synchronization object called a "fence" to wait
for asynchronously loaded sounds to finish. This is called `ma_fence`. The advantage to using a
fence is that it can be used to wait for a group of sounds to finish loading rather than waiting
for sounds on an individual basis. There are two stages to loading a sound:

  * Initialization of the internal decoder; and
  * Completion of decoding of the file (the file is fully decoded)

You can specify separate fences for each of the different stages. Waiting for the initialization
of the internal decoder is important for when you need to know the sample format, channels and
sample rate of the file.

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

  * By storing the entire sound inside an in-memory buffer (referred to as a data buffer)
  * By streaming audio data on the fly (referred to as a data stream)

A resource managed data source (`ma_resource_manager_data_source`) encapsulates a data buffer or
data stream, depending on whether or not the data source was initialized with the
`MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM` flag. If so, it will make use of a
`ma_resource_manager_data_stream` object. Otherwise it will use a `ma_resource_manager_data_buffer`
object. Both of these objects are data sources which means they can be used with any
`ma_data_source_*()` API.

Another major feature of the resource manager is the ability to asynchronously decode audio files.
This relieves the audio thread of time-consuming decoding which can negatively affect scalability
due to the audio thread needing to complete it's work extremely quickly to avoid glitching.
Asynchronous decoding is achieved through a job system. There is a central multi-producer,
multi-consumer, fixed-capacity job queue. When some asynchronous work needs to be done, a job is
posted to the queue which is then read by a job thread. The number of job threads can be
configured for improved scalability, and job threads can all run in parallel without needing to
worry about the order of execution (how this is achieved is explained below).

When a sound is being loaded asynchronously, playback can begin before the sound has been fully
decoded. This enables the application to start playback of the sound quickly, while at the same
time allowing to resource manager to keep loading in the background. Since there may be less
threads than the number of sounds being loaded at a given time, a simple scheduling system is used
to keep decoding time balanced and fair. The resource manager solves this by splitting decoding
into chunks called pages. By default, each page is 1 second long. When a page has been decoded, a
new job will be posted to start decoding the next page. By dividing up decoding into pages, an
individual sound shouldn't ever delay every other sound from having their first page decoded. Of
course, when loading many sounds at the same time, there will always be an amount of time required
to process jobs in the queue so in heavy load situations there will still be some delay. To
determine if a data source is ready to have some frames read, use

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


A binary search tree (BST) is used for storing data buffers as it has good balance between
efficiency and simplicity. The key of the BST is a 64-bit hash of the file path that was passed
into `ma_resource_manager_data_source_init()`. The advantage of using a hash is that it saves
memory over storing the entire path, has faster comparisons, and results in a mostly balanced BST
due to the random nature of the hash. The disadvantage is that file names are case-sensitive. If
this is an issue, you should normalize your file names to upper- or lower-case before initializing
your data sources.

When a sound file has not already been loaded and the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC`
flag is excluded, the file will be decoded synchronously by the calling thread. There are two
options for controlling how the audio is stored in the data buffer - encoded or decoded. When the
`MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE` option is excluded, the raw file data will be stored
in memory. Otherwise the sound will be decoded before storing it in memory. Synchronous loading is
a very simple and standard process of simply adding an item to the BST, allocating a block of
memory and then decoding (if `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE` is specified).

When the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC` flag is specified, loading of the data buffer
is done asynchronously. In this case, a job is posted to the queue to start loading and then the
function immediately returns, setting an internal result code to `MA_BUSY`. This result code is
returned when the program calls `ma_resource_manager_data_source_result()`. When decoding has fully
completed `MA_SUCCESS` will be returned. This can be used to know if loading has fully completed.

When loading asynchronously, a single job is posted to the queue of the type
`MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER_NODE`. This involves making a copy of the file path and
associating it with job. When the job is processed by the job thread, it will first load the file
using the VFS associated with the resource manager. When using a custom VFS, it's important that it
be completely thread-safe because it will be used from one or more job threads at the same time.
Individual files should only ever be accessed by one thread at a time, however. After opening the
file via the VFS, the job will determine whether or not the file is being decoded. If not, it
simply allocates a block of memory and loads the raw file contents into it and returns. On the
other hand, when the file is being decoded, it will first allocate a decoder on the heap and
initialize it. Then it will check if the length of the file is known. If so it will allocate a
block of memory to store the decoded output and initialize it to silence. If the size is unknown,

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

which is done from the VFS.

For data streams, the `MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC` flag will determine whether or
not initialization of the data source waits until the two pages have been decoded. When unset,
`ma_resource_manager_data_source_init()` will wait until the two pages have been loaded, otherwise
it will return immediately.

When frames are read from a data stream using `ma_resource_manager_data_source_read_pcm_frames()`,
`MA_BUSY` will be returned if there are no frames available. If there are some frames available,
but less than the number requested, `MA_SUCCESS` will be returned, but the actual number of frames
read will be less than the number requested. Due to the asynchronous nature of data streams,
seeking is also asynchronous. If the data stream is in the middle of a seek, `MA_BUSY` will be
returned when trying to read frames.

When `ma_resource_manager_data_source_read_pcm_frames()` results in a page getting fully consumed
a job is posted to load the next page. This will be posted from the same thread that called
`ma_resource_manager_data_source_read_pcm_frames()`.

Data streams are uninitialized by posting a job to the queue, but the function won't return until
that job has been processed. The reason for this is that the caller owns the data stream object and
therefore miniaudio needs to ensure everything completes before handing back control to the caller.
Also, if the data stream is uninitialized while pages are in the middle of decoding, they must

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

includes the cost of recursively processing it's inputs. This is the biggest compromise made with
the approach taken by miniaudio for it's lock-free processing system. The cost of detaching nodes
earlier in the pipeline (data sources, for example) will be cheaper than the cost of detaching
higher level nodes, such as some kind of final post-processing endpoint. If you need to do mass
detachments, detach starting from the lowest level nodes and work your way towards the final
endpoint node (but don't try detaching the node graph's endpoint). If the audio thread is not
running, detachment will be fast and detachment in any order will be the same. The reason nodes
need to wait for their input attachments to complete is due to the potential for desyncs between
data sources. If the node was to terminate processing mid way through processing it's inputs,
there's a chance that some of the underlying data sources will have been read, but then others not.
That will then result in a potential desynchronization when detaching and reattaching higher-level
nodes. A possible solution to this is to have an option when detaching to terminate processing
before processing all input attachments which should be fairly simple.

Another compromise, albeit less significant, is locking when attaching and detaching nodes. This
locking is achieved by means of a spinlock in order to reduce memory overhead. A lock is present
for each input bus and output bus. When an output bus is connected to an input bus, both the output
bus and input bus is locked. This locking is specifically for attaching and detaching across
different threads and does not affect `ma_node_graph_read_pcm_frames()` in any way. The locking and
unlocking is mostly self-explanatory, but a slightly less intuitive aspect comes into it when
considering that iterating over attachments must not break as a result of attaching or detaching a

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

MA_API ma_int32 ma_pcm_rb_pointer_distance(ma_pcm_rb* pRB); /* Return value is in frames. */
MA_API ma_uint32 ma_pcm_rb_available_read(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_available_write(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_size(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_stride(ma_pcm_rb* pRB);
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_offset(ma_pcm_rb* pRB, ma_uint32 subbufferIndex);
MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferIndex, void* pBuffer);


/*
The idea of the duplex ring buffer is to act as the intermediary buffer when running two asynchronous devices in a duplex set up. The
capture device writes to it, and then a playback device reads from it.

At the moment this is just a simple naive implementation, but in the future I want to implement some dynamic resampling to seamlessly
handle desyncs. Note that the API is work in progress and may change at any time in any version.

The size of the buffer is based on the capture side since that's what'll be written to the buffer. It is based on the capture period size
in frames. The internal sample rate of the capture device is also needed in order to calculate the size.
*/
typedef struct
{

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


MA_API ma_result ma_fence_init(ma_fence* pFence);
MA_API void ma_fence_uninit(ma_fence* pFence);
MA_API ma_result ma_fence_acquire(ma_fence* pFence);    /* Increment counter. */
MA_API ma_result ma_fence_release(ma_fence* pFence);    /* Decrement counter. */
MA_API ma_result ma_fence_wait(ma_fence* pFence);       /* Wait for counter to reach 0. */



/*
Notification callback for asynchronous operations.
*/
typedef void ma_async_notification;

typedef struct
{
    void (* onSignal)(ma_async_notification* pNotification);
} ma_async_notification_callbacks;

MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification);

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

    ma_backend_opensl,
    ma_backend_webaudio,
    ma_backend_custom,  /* <-- Custom backend, with callbacks defined by the context config. */
    ma_backend_null     /* <-- Must always be the last item. Lowest priority, and used as the terminator for backend enumeration. */
} ma_backend;

#define MA_BACKEND_COUNT (ma_backend_null+1)


/*
Device job thread. This is used by backends that require asynchronous processing of certain
operations. It is not used by all backends.

The device job thread is made up of a thread and a job queue. You can post a job to the thread with
ma_device_job_thread_post(). The thread will do the processing of the job.
*/
typedef struct
{
    ma_bool32 noThread; /* Set this to true if you want to process jobs yourself. */
    ma_uint32 jobQueueCapacity;
    ma_uint32 jobQueueFlags;

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

On input, if the sample format is set to `ma_format_unknown`, the backend is free to use whatever sample format it desires, so long as it's
supported by miniaudio. When the channel count is set to 0, the backend should use the device's native channel count. The same applies for
sample rate. For the channel map, the default should be used when `ma_channel_map_is_blank()` returns true (all channels set to
`MA_CHANNEL_NONE`). On input, the `periodSizeInFrames` or `periodSizeInMilliseconds` option should always be set. The backend should
inspect both of these variables. If `periodSizeInFrames` is set, it should take priority, otherwise it needs to be derived from the period
size in milliseconds (`periodSizeInMilliseconds`) and the sample rate, keeping in mind that the sample rate may be 0, in which case the
sample rate will need to be determined before calculating the period size in frames. On output, all members of the `ma_device_data_format`
object should be set to a valid value, except for `periodSizeInMilliseconds` which is optional (`periodSizeInFrames` *must* be set).

Starting and stopping of the device is done with `onDeviceStart()` and `onDeviceStop()` and should be self-explanatory. If the backend uses
asynchronous reading and writing, `onDeviceStart()` and `onDeviceStop()` should always be implemented.

The handling of data delivery between the application and the device is the most complicated part of the process. To make this a bit
easier, some helper callbacks are available. If the backend uses a blocking read/write style of API, the `onDeviceRead()` and
`onDeviceWrite()` callbacks can optionally be implemented. These are blocking and work just like reading and writing from a file. If the
backend uses a callback for data delivery, that callback must call `ma_device_handle_backend_data_callback()` from within it's callback.
This allows miniaudio to then process any necessary data conversion and then pass it to the miniaudio data callback.

If the backend requires absolute flexibility with it's data delivery, it can optionally implement the `onDeviceDataLoop()` callback
which will allow it to implement the logic that will run on the audio thread. This is much more advanced and is completely optional.

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

    ma_event startEvent;
    ma_event stopEvent;
    ma_thread thread;
    ma_result workResult;                       /* This is set by the worker thread after it's finished doing a job. */
    ma_bool8 isOwnerOfContext;                  /* When set to true, uninitializing the device will also uninitialize the context. Set to true when NULL is passed into ma_device_init(). */
    ma_bool8 noPreSilencedOutputBuffer;
    ma_bool8 noClip;
    ma_bool8 noDisableDenormals;
    ma_bool8 noFixedSizedCallback;
    MA_ATOMIC(4, float) masterVolumeFactor;     /* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
    ma_duplex_rb duplexRB;                      /* Intermediary buffer for duplex device on asynchronous backends. */
    struct
    {
        ma_resample_algorithm algorithm;
        ma_resampling_backend_vtable* pBackendVTable;
        void* pBackendUserData;
        struct
        {
            ma_uint32 lpfOrder;
        } linear;
    } resampling;

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



Return Value
------------
MA_SUCCESS if successful; any other error code otherwise.


Thread Safety
-------------
Unsafe. Since each call to this function invalidates the pointers from the previous call, you should not be calling this simultaneously across multiple
threads. Instead, you need to make a copy of the returned data with your own higher level synchronization.


Remarks
-------
It is _not_ safe to assume the first device in the list is the default device.

You can pass in NULL for the playback or capture lists in which case they'll be ignored.

The returned pointers will become invalid upon the next call this this function, or when the context is uninitialized. Do not free the returned pointers.

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

The general flow of a devices state goes like this:

    ```
    ma_device_init()  -> ma_device_state_uninitialized -> ma_device_state_stopped
    ma_device_start() -> ma_device_state_starting      -> ma_device_state_started
    ma_device_stop()  -> ma_device_state_stopping      -> ma_device_state_stopped
    ```

When the state of the device is changed with `ma_device_start()` or `ma_device_stop()` at this same time as this function is called, the
value returned by this function could potentially be out of sync. If this is significant to your program you need to implement your own
synchronization.
*/
MA_API ma_device_state ma_device_get_state(const ma_device* pDevice);


/*
Performs post backend initialization routines for setting up internal data conversion.

This should be called whenever the backend is initialized. The only time this should be called from
outside of miniaudio is if you're implementing a custom backend, and you would only do it if you
are reinitializing the backend due to rerouting or reinitializing for some reason.

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

See Also
--------
ma_device_set_master_volume_db()
ma_device_set_master_volume()
ma_device_get_master_volume()
*/
MA_API ma_result ma_device_get_master_volume_db(ma_device* pDevice, float* pGainDB);


/*
Called from the data callback of asynchronous backends to allow miniaudio to process the data and fire the miniaudio data callback.


Parameters
----------
pDevice (in)
    A pointer to device whose processing the data callback.

pOutput (out)
    A pointer to the buffer that will receive the output PCM frame data. On a playback device this must not be NULL. On a duplex device
    this can be NULL, in which case pInput must not be NULL.

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

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;

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

    ma_encoding_format_vorbis
} ma_encoding_format;
#endif

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

Decoding
========

Decoders are independent of the main device API. Decoding APIs can be called freely inside the device's data callback, but they are not thread safe unless
you do your own synchronization.

************************************************************************************************************************************************************/
#ifndef MA_NO_DECODING
typedef struct ma_decoder ma_decoder;


typedef struct
{
    ma_format preferredFormat;
    ma_uint32 seekPointCount;   /* Set to > 0 to generate a seektable if the decoding backend supports it. */

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

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.

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


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

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

typedef struct ma_resource_manager                  ma_resource_manager;
typedef struct ma_resource_manager_data_buffer_node ma_resource_manager_data_buffer_node;
typedef struct ma_resource_manager_data_buffer      ma_resource_manager_data_buffer;
typedef struct ma_resource_manager_data_stream      ma_resource_manager_data_stream;
typedef struct ma_resource_manager_data_source      ma_resource_manager_data_source;

typedef enum
{
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM         = 0x00000001,   /* When set, does not load the entire data source in memory. Disk I/O will happen on job threads. */
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE         = 0x00000002,   /* Decode data before storing in memory. When set, decoding is done at the resource manager level rather than the mixing thread. Results in faster mixing, but higher memory usage...
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC          = 0x00000004,   /* When set, the resource manager will load the data source asynchronously. */
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT      = 0x00000008,   /* When set, waits for initialization of the underlying data source before returning from ma_resource_manager_data_source_init(). */
    MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH = 0x00000010    /* Gives the resource manager a hint that the length of the data source is unknown and calling `ma_data_source_get_length_in_pcm_frames()` should be avoided. */
} ma_resource_manager_data_source_flags;


/*
Pipeline notifications used by the resource manager. Made up of both an async notification and a fence, both of which are optional.
*/
typedef struct
{

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

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

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

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

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

#if !defined(MA_NO_DEVICE_IO)
    ma_device* pDevice;                     /* Optionally set via the config, otherwise allocated by the engine in ma_engine_init(). */
#endif
    ma_log* pLog;
    ma_uint32 sampleRate;
    ma_uint32 listenerCount;
    ma_spatializer_listener listeners[MA_ENGINE_MAX_LISTENERS];
    ma_allocation_callbacks allocationCallbacks;
    ma_bool8 ownsResourceManager;
    ma_bool8 ownsDevice;
    ma_spinlock inlinedSoundLock;               /* For synchronizing access so the inlined sound list. */
    ma_sound_inlined* pInlinedSoundHead;        /* The first inlined sound. Inlined sounds are tracked in a linked list. */
    MA_ATOMIC(4, ma_uint32) inlinedSoundCount;  /* The total number of allocated inlined sound objects. Used for debugging. */
    ma_uint32 gainSmoothTimeInFrames;           /* The number of frames to interpolate the gain of spatialized sounds across. */
    ma_mono_expansion_mode monoExpansionMode;
};

MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEngine);
MA_API void ma_engine_uninit(ma_engine* pEngine);
MA_API ma_result ma_engine_read_pcm_frames(ma_engine* pEngine, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_node_graph* ma_engine_get_node_graph(ma_engine* pEngine);

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

    #define c89atoimc_flag_load_explicit(ptr, order)                c89atomic_load_explicit_8(ptr, order)
#else
    #define c89atomic_memory_order_relaxed  1
    #define c89atomic_memory_order_consume  2
    #define c89atomic_memory_order_acquire  3
    #define c89atomic_memory_order_release  4
    #define c89atomic_memory_order_acq_rel  5
    #define c89atomic_memory_order_seq_cst  6
    #define c89atomic_compiler_fence() __asm__ __volatile__("":::"memory")
    #if defined(__GNUC__)
        #define c89atomic_thread_fence(order) __sync_synchronize(), (void)order
        static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_exchange_explicit_8(volatile c89atomic_uint8* dst, c89atomic_uint8 src, c89atomic_memory_order order)
        {
            if (order > c89atomic_memory_order_acquire) {
                __sync_synchronize();
            }
            return __sync_lock_test_and_set(dst, src);
        }
        static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_exchange_explicit_16(volatile c89atomic_uint16* dst, c89atomic_uint16 src, c89atomic_memory_order order)
        {
            c89atomic_uint16 oldValue;
            do {
                oldValue = *dst;
            } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
            (void)order;

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

                }
            }
        }
        ma_job_queue_cas(&pQueue->tail, tail, slot);
    }
    #ifndef MA_USE_EXPERIMENTAL_LOCK_FREE_JOB_QUEUE
    ma_spinlock_unlock(&pQueue->lock);
    #endif


    /* Signal the semaphore as the last step if we're using synchronous mode. */
    if ((pQueue->flags & MA_JOB_QUEUE_FLAG_NON_BLOCKING) == 0) {
        #ifndef MA_NO_THREADING
        {
            ma_semaphore_release(&pQueue->sem);
        }
        #else
        {
            MA_ASSERT(MA_FALSE);    /* Should never get here. Should have been checked at initialization time. */
        }
        #endif

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

MA_API ma_result ma_job_queue_next(ma_job_queue* pQueue, ma_job* pJob)
{
    ma_uint64 head;
    ma_uint64 tail;
    ma_uint64 next;

    if (pQueue == NULL || pJob == NULL) {
        return MA_INVALID_ARGS;
    }

    /* If we're running in synchronous mode we'll need to wait on a semaphore. */
    if ((pQueue->flags & MA_JOB_QUEUE_FLAG_NON_BLOCKING) == 0) {
        #ifndef MA_NO_THREADING
        {
            ma_semaphore_wait(&pQueue->sem);
        }
        #else
        {
            MA_ASSERT(MA_FALSE);    /* Should never get here. Should have been checked at initialization time. */
        }
        #endif

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

    return (ma_thread_result)0;
}

static ma_result ma_device_do_operation__null(ma_device* pDevice, ma_uint32 operation)
{
    ma_result result;

    /*
    TODO: Need to review this and consider just using mutual exclusion. I think the original motivation
    for this was to just post the event to a queue and return immediately, but that has since changed
    and now this function is synchronous. I think this can be simplified to just use a mutex.
    */

    /*
    The first thing to do is wait for an operation slot to become available. We only have a single slot for this, but we could extend this later
    to support queing of operations.
    */
    result = ma_semaphore_wait(&pDevice->null_device.operationSemaphore);
    if (result != MA_SUCCESS) {
        return result;  /* Failed to wait for the event. */
    }

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

    When we get here it means the background thread is not referencing the operation code and it can be changed. After changing this we need to
    signal an event to the worker thread to let it know that it can start work.
    */
    pDevice->null_device.operation = operation;

    /* Once the operation code has been set, the worker thread can start work. */
    if (ma_event_signal(&pDevice->null_device.operationEvent) != MA_SUCCESS) {
        return MA_ERROR;
    }

    /* We want everything to be synchronous so we're going to wait for the worker thread to complete it's operation. */
    if (ma_event_wait(&pDevice->null_device.operationCompletionEvent) != MA_SUCCESS) {
        return MA_ERROR;
    }

    return pDevice->null_device.operationResult;
}

static ma_uint64 ma_device_get_total_run_time_in_frames__null(ma_device* pDevice)
{
    ma_uint32 internalSampleRate;

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

    pCallbacks->onContextInit             = ma_context_init__null;
    pCallbacks->onContextUninit           = ma_context_uninit__null;
    pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__null;
    pCallbacks->onContextGetDeviceInfo    = ma_context_get_device_info__null;
    pCallbacks->onDeviceInit              = ma_device_init__null;
    pCallbacks->onDeviceUninit            = ma_device_uninit__null;
    pCallbacks->onDeviceStart             = ma_device_start__null;
    pCallbacks->onDeviceStop              = ma_device_stop__null;
    pCallbacks->onDeviceRead              = ma_device_read__null;
    pCallbacks->onDeviceWrite             = ma_device_write__null;
    pCallbacks->onDeviceDataLoop          = NULL;   /* Our backend is asynchronous with a blocking read-write API which means we can get miniaudio to deal with the audio thread. */

    /* The null backend always works. */
    return MA_SUCCESS;
}
#endif



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

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

    ma_context_command__wasapi cmd;

    MA_ZERO_OBJECT(&cmd);
    cmd.code = code;

    return cmd;
}

static ma_result ma_context_post_command__wasapi(ma_context* pContext, const ma_context_command__wasapi* pCmd)
{
    /* For now we are doing everything synchronously, but I might relax this later if the need arises. */
    ma_result result;
    ma_bool32 isUsingLocalEvent = MA_FALSE;
    ma_event localEvent;

    MA_ASSERT(pContext != NULL);
    MA_ASSERT(pCmd     != NULL);

    if (pCmd->pEvent == NULL) {
        isUsingLocalEvent = MA_TRUE;

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

The PulseAudio API, along with Apple's Core Audio, is the worst of the maintream audio APIs. This is a brief description of what's going on
in the PulseAudio backend. I apologize if this gets a bit ranty for your liking - you might want to skip this discussion.

PulseAudio has something they call the "Simple API", which unfortunately isn't suitable for miniaudio. I've not seen anywhere where it
allows you to enumerate over devices, nor does it seem to support the ability to stop and start streams. Looking at the documentation, it
appears as though the stream is constantly running and you prevent sound from being emitted or captured by simply not calling the read or
write functions. This is not a professional solution as it would be much better to *actually* stop the underlying stream. Perhaps the
simple API has some smarts to do this automatically, but I'm not sure. Another limitation with the simple API is that it seems inefficient
when you want to have multiple streams to a single context. For these reasons, miniaudio is not using the simple API.

Since we're not using the simple API, we're left with the asynchronous API as our only other option. And boy, is this where it starts to
get fun, and I don't mean that in a good way...

The problems start with the very name of the API - "asynchronous". Yes, this is an asynchronous oriented API which means your commands
don't immediately take effect. You instead need to issue your commands, and then wait for them to complete. The waiting mechanism is
enabled through the use of a "main loop". In the asychronous API you cannot get away from the main loop, and the main loop is where almost
all of PulseAudio's problems stem from.

When you first initialize PulseAudio you need an object referred to as "main loop". You can implement this yourself by defining your own
vtable, but it's much easier to just use one of the built-in main loop implementations. There's two generic implementations called
pa_mainloop and pa_threaded_mainloop, and another implementation specific to GLib called pa_glib_mainloop. We're using pa_threaded_mainloop
because it simplifies management of the worker thread. The idea of the main loop object is pretty self explanatory - you're supposed to use
it to implement a worker thread which runs in a loop. The main loop is where operations are actually executed.

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

main loop object entirely and just implement `pa_mainloop_api` directly, but there's no need for it unless you're doing something extremely
specialized such as if you want to integrate it into your application's existing main loop infrastructure.

(EDIT 2021-01-26: miniaudio is no longer using `pa_threaded_mainloop` due to this issue: https://github.com/mackron/miniaudio/issues/262.
It is now using `pa_mainloop` which turns out to be a simpler solution anyway. The rest of this rant still applies, however.)

Once you have your main loop vtable (the `pa_mainloop_api` object) you can create the PulseAudio context. This is very similar to
miniaudio's context and they map to each other quite well. You have one context to many streams, which is basically the same as miniaudio's
one `ma_context` to many `ma_device`s. Here's where it starts to get annoying, however. When you first create the PulseAudio context, which
is done with `pa_context_new()`, it's not actually connected to anything. When you connect, you call `pa_context_connect()`. However, if
you remember, PulseAudio is an asynchronous API. That means you cannot just assume the context is connected after `pa_context_context()`
has returned. You instead need to wait for it to connect. To do this, you need to either wait for a callback to get fired, which you can
set with `pa_context_set_state_callback()`, or you can continuously poll the context's state. Either way, you need to run this in a loop.
All objects from here out are created from the context, and, I believe, you can't be creating these objects until the context is connected.
This waiting loop is therefore unavoidable. In order for the waiting to ever complete, however, the main loop needs to be running. Before
attempting to connect the context, the main loop needs to be started with `pa_threaded_mainloop_start()`.

The reason for this asynchronous design is to support cases where you're connecting to a remote server, say through a local network or an
internet connection. However, the *VAST* majority of cases don't involve this at all - they just connect to a local "server" running on the
host machine. The fact that this would be the default rather than making `pa_context_connect()` synchronous tends to boggle the mind.

Once the context has been created and connected you can start creating a stream. A PulseAudio stream is analogous to miniaudio's device.
The initialization of a stream is fairly standard - you configure some attributes (analogous to miniaudio's device config) and then call
`pa_stream_new()` to actually create it. Here is where we start to get into "operations". When configuring the stream, you can get
information about the source (such as sample format, sample rate, etc.), however it's not synchronous. Instead, a `pa_operation` object
is returned from `pa_context_get_source_info_by_name()` (capture) or `pa_context_get_sink_info_by_name()` (playback). Then, you need to
run a loop (again!) to wait for the operation to complete which you can determine via a callback or polling, just like we did with the
context. Then, as an added bonus, you need to decrement the reference counter of the `pa_operation` object to ensure memory is cleaned up.
All of that just to retrieve basic information about a device!

Once the basic information about the device has been retrieved, miniaudio can now create the stream with `ma_stream_new()`. Like the
context, this needs to be connected. But we need to be careful here, because we're now about to introduce one of the most horrific design
choices in PulseAudio.

PulseAudio allows you to specify a callback that is fired when data can be written to or read from a stream. The language is important here

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

This becomes a problem when stopping and then restarting the device. When the device is stopped, it's drained, which requires us to *not*
write anything to the stream. But then, since we didn't write anything to it, the write callback will *never* get called again if we just
resume the stream naively. This means that starting the stream requires us to write data to the stream from outside the callback. This
disconnect is something PulseAudio has got seriously wrong - there should only ever be a single source of data delivery, that being the
callback. (I have tried using `pa_stream_flush()` to trigger the write callback to fire, but this just doesn't work for some reason.)

Once you've created the stream, you need to connect it which involves the whole waiting procedure. This is the same process as the context,
only this time you'll poll for the state with `pa_stream_get_status()`. The starting and stopping of a streaming is referred to as
"corking" in PulseAudio. The analogy is corking a barrel. To start the stream, you uncork it, to stop it you cork it. Personally I think
it's silly - why would you not just call it "starting" and "stopping" like any other normal audio API? Anyway, the act of corking is, you
guessed it, asynchronous. This means you'll need our waiting loop as usual. Again, why this asynchronous design is the default is
absolutely beyond me. Would it really be that hard to just make it run synchronously?

Teardown is pretty simple (what?!). It's just a matter of calling the relevant `_unref()` function on each object in reverse order that
they were initialized in.

That's about it from the PulseAudio side. A bit ranty, I know, but they really need to fix that main loop and callback system. They're
embarrassingly unpractical. The main loop thing is an easy fix - have synchronous versions of all APIs. If an application wants these to
run asynchronously, they can execute them in a separate thread themselves. The desire to run these asynchronously is such a niche
requirement - it makes no sense to make it the default. The stream write callback needs to be change, or an alternative provided, that is
constantly fired, regardless of whether or not `pa_stream_write()` has been called, and it needs to take a pointer to a buffer as a
parameter which the program just writes to directly rather than having to call `pa_stream_writable_size()` and `pa_stream_write()`. These
changes alone will change PulseAudio from one of the worst audio APIs to one of the best.
*/


/*
It is assumed pulseaudio.h is available when linking at compile time. When linking at compile time, we use the declarations in the header
to check for type safety. We cannot do this when linking at run time because the header might not be available.

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

        return MA_FAILED_TO_INIT_BACKEND;
    }

    pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)((ma_pa_mainloop*)pMainLoop), pApplicationName);
    if (pPulseContext == NULL) {
        ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to create PulseAudio context.");
        ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pMainLoop));
        return MA_FAILED_TO_INIT_BACKEND;
    }

    /* Now we need to connect to the context. Everything is asynchronous so we need to wait for it to connect before returning. */
    result = ma_result_from_pulse(((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pPulseContext, pServerName, (tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN, NULL));
    if (result != MA_SUCCESS) {
        ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio context.");
        ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pMainLoop));
        return result;
    }

    /* Since ma_context_init() runs synchronously we need to wait for the PulseAudio context to connect before we return. */
    result = ma_wait_for_pa_context_to_connect__pulse(pContext, pMainLoop, pPulseContext);
    if (result != MA_SUCCESS) {
        ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[PulseAudio] Waiting for connection failed.");
        ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pMainLoop));
        return result;
    }

    *ppMainLoop     = pMainLoop;
    *ppPulseContext = pPulseContext;

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

        }

        pDescriptorPlayback->periodSizeInFrames = attr.maxlength / ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels) / pDescriptorPlayback->periodCount;
        ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[PulseAudio] Playback actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalPeriodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.min...
    }


    /*
    We need a ring buffer for handling duplex mode. We can use the main duplex ring buffer in the main
    part of the ma_device struct. We cannot, however, depend on ma_device_init() initializing this for
    us later on because that will only do it if it's a fully asynchronous backend - i.e. the
    onDeviceDataLoop callback is NULL, which is not the case for PulseAudio.
    */
    if (pConfig->deviceType == ma_device_type_duplex) {
        ma_format rbFormat     = (format != ma_format_unknown) ? format     : pDescriptorCapture->format;
        ma_uint32 rbChannels   = (channels   > 0)              ? channels   : pDescriptorCapture->channels;
        ma_uint32 rbSampleRate = (sampleRate > 0)              ? sampleRate : pDescriptorCapture->sampleRate;

        result = ma_duplex_rb_init(rbFormat, rbChannels, rbSampleRate, pDescriptorCapture->sampleRate, pDescriptorCapture->periodSizeInFrames, &pDevice->pContext->allocationCallbacks, &pDevice->duplexRB);
        if (result != MA_SUCCESS) {
            ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to initialize ring buffer. %s.\n", ma_result_description(result));

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

    result = ma_init_pa_mainloop_and_pa_context__pulse(pContext, pConfig->pulse.pApplicationName, pConfig->pulse.pServerName, pConfig->pulse.tryAutoSpawn, &pContext->pulse.pMainLoop, &pContext->pulse.pPulseContext);
    if (result != MA_SUCCESS) {
        ma_free(pContext->pulse.pServerName, &pContext->allocationCallbacks);
        ma_free(pContext->pulse.pApplicationName, &pContext->allocationCallbacks);
    #ifndef MA_NO_RUNTIME_LINKING
        ma_dlclose(pContext, pContext->pulse.pulseSO);
    #endif
        return result;
    }

    /* With pa_mainloop we run a synchronous backend, but we implement our own main loop. */
    pCallbacks->onContextInit             = ma_context_init__pulse;
    pCallbacks->onContextUninit           = ma_context_uninit__pulse;
    pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__pulse;
    pCallbacks->onContextGetDeviceInfo    = ma_context_get_device_info__pulse;
    pCallbacks->onDeviceInit              = ma_device_init__pulse;
    pCallbacks->onDeviceUninit            = ma_device_uninit__pulse;
    pCallbacks->onDeviceStart             = ma_device_start__pulse;
    pCallbacks->onDeviceStop              = ma_device_stop__pulse;
    pCallbacks->onDeviceRead              = NULL;   /* Not used because we're implementing onDeviceDataLoop. */
    pCallbacks->onDeviceWrite             = NULL;   /* Not used because we're implementing onDeviceDataLoop. */

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



    pCallbacks->onContextInit             = ma_context_init__jack;
    pCallbacks->onContextUninit           = ma_context_uninit__jack;
    pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__jack;
    pCallbacks->onContextGetDeviceInfo    = ma_context_get_device_info__jack;
    pCallbacks->onDeviceInit              = ma_device_init__jack;
    pCallbacks->onDeviceUninit            = ma_device_uninit__jack;
    pCallbacks->onDeviceStart             = ma_device_start__jack;
    pCallbacks->onDeviceStop              = ma_device_stop__jack;
    pCallbacks->onDeviceRead              = NULL;   /* Not used because JACK is asynchronous. */
    pCallbacks->onDeviceWrite             = NULL;   /* Not used because JACK is asynchronous. */
    pCallbacks->onDeviceDataLoop          = NULL;   /* Not used because JACK is asynchronous. */

    return MA_SUCCESS;
}
#endif  /* JACK */



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

Core Audio Backend

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



    pCallbacks->onContextInit             = ma_context_init__aaudio;
    pCallbacks->onContextUninit           = ma_context_uninit__aaudio;
    pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__aaudio;
    pCallbacks->onContextGetDeviceInfo    = ma_context_get_device_info__aaudio;
    pCallbacks->onDeviceInit              = ma_device_init__aaudio;
    pCallbacks->onDeviceUninit            = ma_device_uninit__aaudio;
    pCallbacks->onDeviceStart             = ma_device_start__aaudio;
    pCallbacks->onDeviceStop              = ma_device_stop__aaudio;
    pCallbacks->onDeviceRead              = NULL;   /* Not used because AAudio is asynchronous. */
    pCallbacks->onDeviceWrite             = NULL;   /* Not used because AAudio is asynchronous. */
    pCallbacks->onDeviceDataLoop          = NULL;   /* Not used because AAudio is asynchronous. */
    pCallbacks->onDeviceGetInfo           = ma_device_get_info__aaudio;


    /* We need a job thread so we can deal with rerouting. */
    {
        ma_result result;
        ma_device_job_thread_config jobThreadConfig;

        jobThreadConfig = ma_device_job_thread_config_init();

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

    }

    pCallbacks->onContextInit             = ma_context_init__opensl;
    pCallbacks->onContextUninit           = ma_context_uninit__opensl;
    pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__opensl;
    pCallbacks->onContextGetDeviceInfo    = ma_context_get_device_info__opensl;
    pCallbacks->onDeviceInit              = ma_device_init__opensl;
    pCallbacks->onDeviceUninit            = ma_device_uninit__opensl;
    pCallbacks->onDeviceStart             = ma_device_start__opensl;
    pCallbacks->onDeviceStop              = ma_device_stop__opensl;
    pCallbacks->onDeviceRead              = NULL;   /* Not needed because OpenSL|ES is asynchronous. */
    pCallbacks->onDeviceWrite             = NULL;   /* Not needed because OpenSL|ES is asynchronous. */
    pCallbacks->onDeviceDataLoop          = NULL;   /* Not needed because OpenSL|ES is asynchronous. */

    return MA_SUCCESS;
}
#endif  /* OpenSL|ES */


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

Web Audio Backend

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

    }

    pCallbacks->onContextInit             = ma_context_init__webaudio;
    pCallbacks->onContextUninit           = ma_context_uninit__webaudio;
    pCallbacks->onContextEnumerateDevices = ma_context_enumerate_devices__webaudio;
    pCallbacks->onContextGetDeviceInfo    = ma_context_get_device_info__webaudio;
    pCallbacks->onDeviceInit              = ma_device_init__webaudio;
    pCallbacks->onDeviceUninit            = ma_device_uninit__webaudio;
    pCallbacks->onDeviceStart             = ma_device_start__webaudio;
    pCallbacks->onDeviceStop              = ma_device_stop__webaudio;
    pCallbacks->onDeviceRead              = NULL;   /* Not needed because WebAudio is asynchronous. */
    pCallbacks->onDeviceWrite             = NULL;   /* Not needed because WebAudio is asynchronous. */
    pCallbacks->onDeviceDataLoop          = NULL;   /* Not needed because WebAudio is asynchronous. */

    return MA_SUCCESS;
}
#endif  /* Web Audio */



static ma_bool32 ma__is_channel_map_valid(const ma_channel* pChannelMap, ma_uint32 channels)
{
    /* A blank channel map should be allowed, in which case it should use an appropriate default which will depend on context. */

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

#ifdef MA_WIN32
    result = ma_context_uninit_backend_apis__win32(pContext);
#else
    result = ma_context_uninit_backend_apis__nix(pContext);
#endif

    return result;
}


static ma_bool32 ma_context_is_backend_asynchronous(ma_context* pContext)
{
    MA_ASSERT(pContext != NULL);

    if (pContext->callbacks.onDeviceRead == NULL && pContext->callbacks.onDeviceWrite == NULL) {
        if (pContext->callbacks.onDeviceDataLoop == NULL) {
            return MA_TRUE;
        } else {
            return MA_FALSE;
        }
    } else {

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

            /* Silence the buffer for safety. */
            ma_silence_pcm_frames(pDevice->playback.pIntermediaryBuffer, pDevice->playback.intermediaryBufferCap, pDevice->playback.format, pDevice->playback.channels);
            pDevice->playback.intermediaryBufferLen = 0;
        }
    } else {
        /* Not using a fixed sized data callback so no need for an intermediary buffer. */
    }


    /* Some backends don't require the worker thread. */
    if (!ma_context_is_backend_asynchronous(pContext)) {
        /* The worker thread. */
        result = ma_thread_create(&pDevice->thread, pContext->threadPriority, pContext->threadStackSize, ma_worker_thread, pDevice, &pContext->allocationCallbacks);
        if (result != MA_SUCCESS) {
            ma_device_uninit(pDevice);
            return result;
        }

        /* Wait for the worker thread to put the device into it's stopped state for real. */
        ma_event_wait(&pDevice->stopEvent);
        MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_stopped);
    } else {
        /*
        If the backend is asynchronous and the device is duplex, we'll need an intermediary ring buffer. Note that this needs to be done
        after ma_device__post_init_setup().
        */
        if (ma_context_is_backend_asynchronous(pContext)) {
            if (pConfig->deviceType == ma_device_type_duplex) {
                result = ma_duplex_rb_init(pDevice->capture.format, pDevice->capture.channels, pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalPeriodSizeInFrames, &pDevice->pContext->allocationCallbacks, &pDevice->d...
                if (result != MA_SUCCESS) {
                    ma_device_uninit(pDevice);
                    return result;
                }
            }
        }

        ma_device__set_state(pDevice, ma_device_state_stopped);

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


    /* Make sure the device is stopped first. The backends will probably handle this naturally, but I like to do it explicitly for my own sanity. */
    if (ma_device_is_started(pDevice)) {
        ma_device_stop(pDevice);
    }

    /* Putting the device into an uninitialized state will make the worker thread return. */
    ma_device__set_state(pDevice, ma_device_state_uninitialized);

    /* Wake up the worker thread and wait for it to properly terminate. */
    if (!ma_context_is_backend_asynchronous(pDevice->pContext)) {
        ma_event_signal(&pDevice->wakeupEvent);
        ma_thread_wait(&pDevice->thread);
    }

    if (pDevice->pContext->callbacks.onDeviceUninit != NULL) {
        pDevice->pContext->callbacks.onDeviceUninit(pDevice);
    }


    ma_event_uninit(&pDevice->stopEvent);
    ma_event_uninit(&pDevice->startEvent);
    ma_event_uninit(&pDevice->wakeupEvent);
    ma_mutex_uninit(&pDevice->startStopLock);

    if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
        if (pDevice->type == ma_device_type_duplex) {
            ma_duplex_rb_uninit(&pDevice->duplexRB);
        }
    }

    if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
        ma_data_converter_uninit(&pDevice->capture.converter, &pDevice->pContext->allocationCallbacks);
    }
    if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
        ma_data_converter_uninit(&pDevice->playback.converter, &pDevice->pContext->allocationCallbacks);

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

        return MA_SUCCESS;  /* Already started. */
    }

    ma_mutex_lock(&pDevice->startStopLock);
    {
        /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
        MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_stopped);

        ma_device__set_state(pDevice, ma_device_state_starting);

        /* Asynchronous backends need to be handled differently. */
        if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
            if (pDevice->pContext->callbacks.onDeviceStart != NULL) {
                result = pDevice->pContext->callbacks.onDeviceStart(pDevice);
            } else {
                result = MA_INVALID_OPERATION;
            }

            if (result == MA_SUCCESS) {
                ma_device__set_state(pDevice, ma_device_state_started);
                ma_device__on_notification_started(pDevice);
            }

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

        return MA_SUCCESS;  /* Already stopped. */
    }

    ma_mutex_lock(&pDevice->startStopLock);
    {
        /* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a started or paused state. */
        MA_ASSERT(ma_device_get_state(pDevice) == ma_device_state_started);

        ma_device__set_state(pDevice, ma_device_state_stopping);

        /* Asynchronous backends need to be handled differently. */
        if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
            /* Asynchronous backends must have a stop operation. */
            if (pDevice->pContext->callbacks.onDeviceStop != NULL) {
                result = pDevice->pContext->callbacks.onDeviceStop(pDevice);
            } else {
                result = MA_INVALID_OPERATION;
            }

            ma_device__set_state(pDevice, ma_device_state_stopped);
        } else {
            /*
            Synchronous backends. The stop callback is always called from the worker thread. Do not call the stop callback here. If

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

        MA_ZERO_OBJECT(pDataBufferNode);
        pDataBufferNode->hashedName32 = hashedName32;
        pDataBufferNode->refCount     = 1;        /* Always set to 1 by default (this is our first reference). */

        if (pExistingData == NULL) {
            pDataBufferNode->data.type    = ma_resource_manager_data_supply_type_unknown;    /* <-- We won't know this until we start decoding. */
            pDataBufferNode->result       = MA_BUSY;  /* Must be set to MA_BUSY before we leave the critical section, so might as well do it now. */
            pDataBufferNode->isDataOwnedByResourceManager = MA_TRUE;
        } else {
            pDataBufferNode->data         = *pExistingData;
            pDataBufferNode->result       = MA_SUCCESS;   /* Not loading asynchronously, so just set the status */
            pDataBufferNode->isDataOwnedByResourceManager = MA_FALSE;
        }

        result = ma_resource_manager_data_buffer_node_insert_at(pResourceManager, pDataBufferNode, pInsertPoint);
        if (result != MA_SUCCESS) {
            ma_free(pDataBufferNode, &pResourceManager->config.allocationCallbacks);
            return result;  /* Should never happen. Failed to insert the data buffer into the BST. */
        }

        /*
        Here is where we'll post the job, but only if we're loading asynchronously. If we're
        loading synchronously we'll defer loading to a later stage, outside of the critical
        section.
        */
        if (pDataBufferNode->isDataOwnedByResourceManager && (flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC) != 0) {
            /* Loading asynchronously. Post the job. */
            ma_job job;
            char* pFilePathCopy = NULL;
            wchar_t* pFilePathWCopy = NULL;

            /* 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 (pFilePath != NULL) {
                pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks);
            } else {
                pFilePathWCopy = ma_copy_string_w(pFilePathW, &pResourceManager->config.allocationCallbacks);
            }

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

    if (result == MA_ALREADY_EXISTS) {
        nodeAlreadyExists = MA_TRUE;
        result = MA_SUCCESS;
    } else {
        if (result != MA_SUCCESS) {
            return result;
        }
    }

    /*
    If we're loading synchronously, we'll need to load everything now. When loading asynchronously,
    a job will have been posted inside the BST critical section so that an uninitialization can be
    allocated an appropriate execution order thereby preventing it from being uninitialized before
    the node is initialized by the decoding thread(s).
    */
    if (nodeAlreadyExists == MA_FALSE) {    /* Don't need to try loading anything if the node already exists. */
        if (pFilePath == NULL && pFilePathW == NULL) {
            /*
            If this path is hit, it means a buffer is being copied (i.e. initialized from only the
            hashed name), but that node has been freed in the meantime, probably from some other
            thread. This is an invalid operation.
            */
            ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_WARNING, "Cloning data buffer node failed because the source node was released. The source node must remain valid until the cloning has completed.\n");
            result = MA_INVALID_OPERATION;
            goto done;
        }

        if (pDataBufferNode->isDataOwnedByResourceManager) {
            if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC) == 0) {
                /* Loading synchronously. Load the sound in it's entirety here. */
                if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE) == 0) {
                    /* No decoding. This is the simple case - just store the file contents in memory. */
                    result = ma_resource_manager_data_buffer_node_init_supply_encoded(pResourceManager, pDataBufferNode, pFilePath, pFilePathW);
                    if (result != MA_SUCCESS) {
                        goto done;
                    }
                } else {
                    /* Decoding. We do this the same way as we do when loading asynchronously. */
                    ma_decoder* pDecoder;
                    result = ma_resource_manager_data_buffer_node_init_supply_decoded(pResourceManager, pDataBufferNode, pFilePath, pFilePathW, flags, &pDecoder);
                    if (result != MA_SUCCESS) {
                        goto done;
                    }

                    /* We have the decoder, now decode page by page just like we do when loading asynchronously. */
                    for (;;) {
                        /* Decode next page. */
                        result = ma_resource_manager_data_buffer_node_decode_next_page(pResourceManager, pDataBufferNode, pDecoder);
                        if (result != MA_SUCCESS) {
                            break;  /* Will return MA_AT_END when the last page has been decoded. */
                        }
                    }

                    /* Reaching the end needs to be considered successful. */
                    if (result == MA_AT_END) {

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

                    At this point the data buffer is either fully decoded or some error occurred. Either
                    way, the decoder is no longer necessary.
                    */
                    ma_decoder_uninit(pDecoder);
                    ma_free(pDecoder, &pResourceManager->config.allocationCallbacks);
                }

                /* Getting here means we were successful. Make sure the status of the node is updated accordingly. */
                c89atomic_exchange_i32(&pDataBufferNode->result, result);
            } else {
                /* Loading asynchronously. We may need to wait for initialization. */
                if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
                    ma_resource_manager_inline_notification_wait(&initNotification);
                }
            }
        } else {
            /* The data is not managed by the resource manager so there's nothing else to do. */
            MA_ASSERT(pExistingData != NULL);
        }
    }

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

        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);
            goto done;
        }

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

            ma_resource_manager_data_buffer_node_unacquire(pResourceManager, pDataBufferNode, NULL, NULL);
            ma_resource_manager_pipeline_notifications_signal_all_notifications(&notifications);
            goto done;
        }

        pDataBuffer->pResourceManager = pResourceManager;
        pDataBuffer->pNode  = pDataBufferNode;
        pDataBuffer->flags  = flags;
        pDataBuffer->result = MA_BUSY;  /* Always default to MA_BUSY for safety. It'll be overwritten when loading completes or an error occurs. */

        /* If we're loading asynchronously we need to post a job to the job queue to initialize the connector. */
        if (async == MA_FALSE || ma_resource_manager_data_buffer_node_result(pDataBufferNode) == MA_SUCCESS) {
            /* Loading synchronously or the data has already been fully loaded. We can just initialize the connector from here without a job. */
            result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pConfig, NULL, NULL);
            c89atomic_exchange_i32(&pDataBuffer->result, result);

            ma_resource_manager_pipeline_notifications_signal_all_notifications(&notifications);
            goto done;
        } else {
            /* The node's data supply isn't initialized yet. The caller has requested that we load asynchronously so we need to post a job to do this. */
            ma_job job;
            ma_resource_manager_inline_notification initNotification;   /* Used when the WAIT_INIT flag is set. */

            if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
                ma_resource_manager_inline_notification_init(pResourceManager, &initNotification);
            }

            /*
            The status of the data buffer needs to be set to MA_BUSY before posting the job so that the
            worker thread is aware of it's busy state. If the LOAD_DATA_BUFFER job sees a status other

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


MA_API ma_result ma_resource_manager_data_buffer_uninit(ma_resource_manager_data_buffer* pDataBuffer)
{
    ma_result result;

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

    if (ma_resource_manager_data_buffer_result(pDataBuffer) == MA_SUCCESS) {
        /* The data buffer can be deleted synchronously. */
        return ma_resource_manager_data_buffer_uninit_internal(pDataBuffer);
    } else {
        /*
        The data buffer needs to be deleted asynchronously because it's still loading. With the status set to MA_UNAVAILABLE, no more pages will
        be loaded and the uninitialization should happen fairly quickly. Since the caller owns the data buffer, we need to wait for this event
        to get processed before returning.
        */
        ma_resource_manager_inline_notification notification;
        ma_job job;

        /*
        We need to mark the node as unavailable so we don't try reading from it anymore, but also to
        let the loading thread know that it needs to abort it's loading procedure.
        */



( run in 0.888 second using v1.01-cache-2.11-cpan-0d8aa00de5b )