App-MHFS

 view release on metacpan or  search on metacpan

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

*/
MA_API void* ma_realloc(void* p, size_t sz, const ma_allocation_callbacks* pAllocationCallbacks);

/*
free(). Calls MA_FREE().
*/
MA_API void ma_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks);

/*
Performs an aligned malloc, with the assumption that the alignment is a power of 2.
*/
MA_API void* ma_aligned_malloc(size_t sz, size_t alignment, const ma_allocation_callbacks* pAllocationCallbacks);

/*
Free's an aligned malloc'd buffer.
*/
MA_API void ma_aligned_free(void* p, const ma_allocation_callbacks* pAllocationCallbacks);

/*
Retrieves a friendly name for a format.
*/
MA_API const char* ma_get_format_name(ma_format format);

/*
Blends two frames in floating point format.
*/
MA_API void ma_blend_f32(float* pOut, float* pInA, float* pInB, float factor, ma_uint32 channels);

/*
Retrieves the size of a sample in bytes for the given format.

This API is efficient and is implemented using a lookup table.

Thread Safety: SAFE
  This API is pure.
*/
MA_API ma_uint32 ma_get_bytes_per_sample(ma_format format);
static MA_INLINE ma_uint32 ma_get_bytes_per_frame(ma_format format, ma_uint32 channels) { return ma_get_bytes_per_sample(format) * channels; }

/*
Converts a log level to a string.
*/
MA_API const char* ma_log_level_to_string(ma_uint32 logLevel);



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

DEVICE I/O
==========

This section contains the APIs for device playback and capture. Here is where you'll find ma_device_init(), etc.

*************************************************************************************************************************************************************
************************************************************************************************************************************************************/
#ifndef MA_NO_DEVICE_IO
/* Some backends are only supported on certain platforms. */
#if defined(MA_WIN32)
    #define MA_SUPPORT_WASAPI
    #if defined(MA_WIN32_DESKTOP)  /* DirectSound and WinMM backends are only supported on desktops. */
        #define MA_SUPPORT_DSOUND
        #define MA_SUPPORT_WINMM
        #define MA_SUPPORT_JACK    /* JACK is technically supported on Windows, but I don't know how many people use it in practice... */
    #endif
#endif
#if defined(MA_UNIX)
    #if defined(MA_LINUX)
        #if !defined(MA_ANDROID)   /* ALSA is not supported on Android. */
            #define MA_SUPPORT_ALSA
        #endif
    #endif
    #if !defined(MA_BSD) && !defined(MA_ANDROID) && !defined(MA_EMSCRIPTEN)
        #define MA_SUPPORT_PULSEAUDIO
        #define MA_SUPPORT_JACK
    #endif
    #if defined(MA_ANDROID)
        #define MA_SUPPORT_AAUDIO
        #define MA_SUPPORT_OPENSL
    #endif
    #if defined(__OpenBSD__)        /* <-- Change this to "#if defined(MA_BSD)" to enable sndio on all BSD flavors. */
        #define MA_SUPPORT_SNDIO    /* sndio is only supported on OpenBSD for now. May be expanded later if there's demand. */
    #endif
    #if defined(__NetBSD__) || defined(__OpenBSD__)
        #define MA_SUPPORT_AUDIO4   /* Only support audio(4) on platforms with known support. */
    #endif
    #if defined(__FreeBSD__) || defined(__DragonFly__)
        #define MA_SUPPORT_OSS      /* Only support OSS on specific platforms with known support. */
    #endif
#endif
#if defined(MA_APPLE)
    #define MA_SUPPORT_COREAUDIO
#endif
#if defined(MA_EMSCRIPTEN)
    #define MA_SUPPORT_WEBAUDIO
#endif

/* Explicitly disable the Null backend for Emscripten because it uses a background thread which is not properly supported right now. */
#if !defined(MA_EMSCRIPTEN)
#define MA_SUPPORT_NULL
#endif


#if !defined(MA_NO_WASAPI) && defined(MA_SUPPORT_WASAPI)
    #define MA_ENABLE_WASAPI
#endif
#if !defined(MA_NO_DSOUND) && defined(MA_SUPPORT_DSOUND)
    #define MA_ENABLE_DSOUND
#endif
#if !defined(MA_NO_WINMM) && defined(MA_SUPPORT_WINMM)
    #define MA_ENABLE_WINMM
#endif
#if !defined(MA_NO_ALSA) && defined(MA_SUPPORT_ALSA)
    #define MA_ENABLE_ALSA
#endif
#if !defined(MA_NO_PULSEAUDIO) && defined(MA_SUPPORT_PULSEAUDIO)
    #define MA_ENABLE_PULSEAUDIO
#endif
#if !defined(MA_NO_JACK) && defined(MA_SUPPORT_JACK)
    #define MA_ENABLE_JACK
#endif

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

    }

    result = ma_completion_handler_uwp_init(&completionHandler);
    if (result != MA_SUCCESS) {
        ma_CoTaskMemFree(pContext, iidStr);
        return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create event for waiting for ActivateAudioInterfaceAsync().", result);
    }

#if defined(__cplusplus)
    hr = ActivateAudioInterfaceAsync(iidStr, MA_IID_IAudioClient, NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
#else
    hr = ActivateAudioInterfaceAsync(iidStr, &MA_IID_IAudioClient, NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
#endif
    if (FAILED(hr)) {
        ma_completion_handler_uwp_uninit(&completionHandler);
        ma_CoTaskMemFree(pContext, iidStr);
        return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] ActivateAudioInterfaceAsync() failed.", ma_result_from_HRESULT(hr));
    }

    ma_CoTaskMemFree(pContext, iidStr);

    /* Wait for the async operation for finish. */
    ma_completion_handler_uwp_wait(&completionHandler);
    ma_completion_handler_uwp_uninit(&completionHandler);

    hr = ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(pAsyncOp, &activateResult, &pActivatedInterface);
    ma_IActivateAudioInterfaceAsyncOperation_Release(pAsyncOp);

    if (FAILED(hr) || FAILED(activateResult)) {
        return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to activate device.", FAILED(hr) ? ma_result_from_HRESULT(hr) : ma_result_from_HRESULT(activateResult));
    }

    /* Here is where we grab the IAudioClient interface. */
    hr = ma_IUnknown_QueryInterface(pActivatedInterface, &MA_IID_IAudioClient, (void**)ppAudioClient);
    if (FAILED(hr)) {
        return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to query IAudioClient interface.", ma_result_from_HRESULT(hr));
    }

    if (ppActivatedInterface) {
        *ppActivatedInterface = pActivatedInterface;
    } else {
        ma_IUnknown_Release(pActivatedInterface);
    }

    return MA_SUCCESS;
}
#endif

static ma_result ma_context_get_IAudioClient__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_IAudioClient** ppAudioClient, ma_WASAPIDeviceInterface** ppDeviceInterface)
{
#ifdef MA_WIN32_DESKTOP
    return ma_context_get_IAudioClient_Desktop__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
#else
    return ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
#endif
}


static ma_result ma_context_enumerate_devices__wasapi(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pUserData)
{
    /* Different enumeration for desktop and UWP. */
#ifdef MA_WIN32_DESKTOP
    /* Desktop */
    HRESULT hr;
    ma_IMMDeviceEnumerator* pDeviceEnumerator;

    hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
    if (FAILED(hr)) {
        return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create device enumerator.", ma_result_from_HRESULT(hr));
    }

    ma_context_enumerate_devices_by_type__wasapi(pContext, pDeviceEnumerator, ma_device_type_playback, callback, pUserData);
    ma_context_enumerate_devices_by_type__wasapi(pContext, pDeviceEnumerator, ma_device_type_capture,  callback, pUserData);

    ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
#else
    /*
    UWP
    
    The MMDevice API is only supported on desktop applications. For now, while I'm still figuring out how to properly enumerate
    over devices without using MMDevice, I'm restricting devices to defaults.
    
    Hint: DeviceInformation::FindAllAsync() with DeviceClass.AudioCapture/AudioRender. https://blogs.windows.com/buildingapps/2014/05/15/real-time-audio-in-windows-store-and-windows-phone-apps/
    */
    if (callback) {
        ma_bool32 cbResult = MA_TRUE;

        /* Playback. */
        if (cbResult) {
            ma_device_info deviceInfo;
            MA_ZERO_OBJECT(&deviceInfo);
            ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
            deviceInfo._private.isDefault = MA_TRUE;
            cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
        }

        /* Capture. */
        if (cbResult) {
            ma_device_info deviceInfo;
            MA_ZERO_OBJECT(&deviceInfo);
            ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
            deviceInfo._private.isDefault = MA_TRUE;
            cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
        }
    }
#endif

    return MA_SUCCESS;
}

static ma_result ma_context_get_device_info__wasapi(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_share_mode shareMode, ma_device_info* pDeviceInfo)
{
#ifdef MA_WIN32_DESKTOP
    ma_result result;
    ma_IMMDevice* pMMDevice = NULL;
    LPWSTR pDefaultDeviceID = NULL;
    
    result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, &pMMDevice);
    if (result != MA_SUCCESS) {
        return result;
    }

    /* We need the default device ID so we can set the isDefault flag in the device info. */
    pDefaultDeviceID = ma_context_get_default_device_id__wasapi(pContext, deviceType);

    result = ma_context_get_device_info_from_MMDevice__wasapi(pContext, pMMDevice, shareMode, pDefaultDeviceID, MA_FALSE, pDeviceInfo);   /* MA_FALSE = !onlySimpleInfo. */

    if (pDefaultDeviceID != NULL) {
        ma_CoTaskMemFree(pContext, pDefaultDeviceID);
        pDefaultDeviceID = NULL;
    }

    ma_IMMDevice_Release(pMMDevice);

    return result;
#else
    ma_IAudioClient* pAudioClient;
    ma_result result;

    /* UWP currently only uses default devices. */

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

    MA_REFERENCE_TIME periodDurationInMicroseconds;
    ma_bool32 wasInitializedUsingIAudioClient3 = MA_FALSE;
    WAVEFORMATEXTENSIBLE wf;
    ma_WASAPIDeviceInterface* pDeviceInterface = NULL;
    ma_IAudioClient2* pAudioClient2;
    ma_uint32 nativeSampleRate;

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

    /* This function is only used to initialize one device type: either playback, capture or loopback. Never full-duplex. */
    if (deviceType == ma_device_type_duplex) {
        return MA_INVALID_ARGS;
    }

    pData->pAudioClient = NULL;
    pData->pRenderClient = NULL;
    pData->pCaptureClient = NULL;

    streamFlags = MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
    if (!pData->noAutoConvertSRC && !pData->usingDefaultSampleRate && pData->shareMode != ma_share_mode_exclusive) {    /* <-- Exclusive streams must use the native sample rate. */
        streamFlags |= MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
    }
    if (!pData->noDefaultQualitySRC && !pData->usingDefaultSampleRate && (streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) != 0) {
        streamFlags |= MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
    }
    if (deviceType == ma_device_type_loopback) {
        streamFlags |= MA_AUDCLNT_STREAMFLAGS_LOOPBACK;
    }

    result = ma_context_get_IAudioClient__wasapi(pContext, deviceType, pDeviceID, &pData->pAudioClient, &pDeviceInterface);
    if (result != MA_SUCCESS) {
        goto done;
    }

    MA_ZERO_OBJECT(&wf);

    /* Try enabling hardware offloading. */
    if (!pData->noHardwareOffloading) {
        hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient2, (void**)&pAudioClient2);
        if (SUCCEEDED(hr)) {
            BOOL isHardwareOffloadingSupported = 0;
            hr = ma_IAudioClient2_IsOffloadCapable(pAudioClient2, MA_AudioCategory_Other, &isHardwareOffloadingSupported);
            if (SUCCEEDED(hr) && isHardwareOffloadingSupported) {
                ma_AudioClientProperties clientProperties;
                MA_ZERO_OBJECT(&clientProperties);
                clientProperties.cbSize = sizeof(clientProperties);
                clientProperties.bIsOffload = 1;
                clientProperties.eCategory = MA_AudioCategory_Other;
                ma_IAudioClient2_SetClientProperties(pAudioClient2, &clientProperties);
            }

            pAudioClient2->lpVtbl->Release(pAudioClient2);
        }
    }

    /* Here is where we try to determine the best format to use with the device. If the client if wanting exclusive mode, first try finding the best format for that. If this fails, fall back to shared mode. */
    result = MA_FORMAT_NOT_SUPPORTED;
    if (pData->shareMode == ma_share_mode_exclusive) {
    #ifdef MA_WIN32_DESKTOP
        /* In exclusive mode on desktop we always use the backend's native format. */
        ma_IPropertyStore* pStore = NULL;
        hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pStore);
        if (SUCCEEDED(hr)) {
            PROPVARIANT prop;
            ma_PropVariantInit(&prop);
            hr = ma_IPropertyStore_GetValue(pStore, &MA_PKEY_AudioEngine_DeviceFormat, &prop);
            if (SUCCEEDED(hr)) {
                WAVEFORMATEX* pActualFormat = (WAVEFORMATEX*)prop.blob.pBlobData;
                hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pData->pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pActualFormat, NULL);
                if (SUCCEEDED(hr)) {
                    MA_COPY_MEMORY(&wf, pActualFormat, sizeof(WAVEFORMATEXTENSIBLE));
                }

                ma_PropVariantClear(pContext, &prop);
            }

            ma_IPropertyStore_Release(pStore);
        }
    #else
        /*
        I do not know how to query the device's native format on UWP so for now I'm just disabling support for
        exclusive mode. The alternative is to enumerate over different formats and check IsFormatSupported()
        until you find one that works.
        
        TODO: Add support for exclusive mode to UWP.
        */
        hr = S_FALSE;
    #endif

        if (hr == S_OK) {
            shareMode = MA_AUDCLNT_SHAREMODE_EXCLUSIVE;
            result = MA_SUCCESS;
        } else {
            result = MA_SHARE_MODE_NOT_SUPPORTED;
        }
    } else {
        /* In shared mode we are always using the format reported by the operating system. */
        WAVEFORMATEXTENSIBLE* pNativeFormat = NULL;
        hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pData->pAudioClient, (WAVEFORMATEX**)&pNativeFormat);
        if (hr != S_OK) {
            result = MA_FORMAT_NOT_SUPPORTED;
        } else {
            MA_COPY_MEMORY(&wf, pNativeFormat, sizeof(wf));
            result = MA_SUCCESS;
        }

        ma_CoTaskMemFree(pContext, pNativeFormat);

        shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
    }

    /* Return an error if we still haven't found a format. */
    if (result != MA_SUCCESS) {
        errorMsg = "[WASAPI] Failed to find best device mix format.";
        goto done;
    }

    /*
    Override the native sample rate with the one requested by the caller, but only if we're not using the default sample rate. We'll use
    WASAPI to perform the sample rate conversion.

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

            pDeviceInfo->minSampleRate = UINT32_MAX;
            pDeviceInfo->maxSampleRate = 0;
            for (iSampleRate = 0; iSampleRate < sampleRateRangeCount; ++iSampleRate) {
                if (pDeviceInfo->minSampleRate > pSampleRateRanges[iSampleRate].mMinimum) {
                    pDeviceInfo->minSampleRate = pSampleRateRanges[iSampleRate].mMinimum;
                }
                if (pDeviceInfo->maxSampleRate < pSampleRateRanges[iSampleRate].mMaximum) {
                    pDeviceInfo->maxSampleRate = pSampleRateRanges[iSampleRate].mMaximum;
                }
            }
        }
    }
#else
    /* Mobile */
    {
        AudioComponentDescription desc;
        AudioComponent component;
        AudioUnit audioUnit;
        OSStatus status;
        AudioUnitScope formatScope;
        AudioUnitElement formatElement;
        AudioStreamBasicDescription bestFormat;
        UInt32 propSize;
        
        /* We want to ensure we use a consistent device name to device enumeration. */
        if (pDeviceID != NULL) {
            ma_bool32 found = MA_FALSE;
            if (deviceType == ma_device_type_playback) {
                NSArray *pOutputs = [[[AVAudioSession sharedInstance] currentRoute] outputs];
                for (AVAudioSessionPortDescription* pPortDesc in pOutputs) {
                    if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
                        ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
                        found = MA_TRUE;
                        break;
                    }
                }
            } else {
                NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
                for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
                    if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
                        ma_AVAudioSessionPortDescription_to_device_info(pPortDesc, pDeviceInfo);
                        found = MA_TRUE;
                        break;
                    }
                }
            }
            
            if (!found) {
                return MA_DOES_NOT_EXIST;
            }
        } else {
            if (deviceType == ma_device_type_playback) {
                ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
            } else {
                ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
            }
        }
        
    
        /*
        Retrieving device information is more annoying on mobile than desktop. For simplicity I'm locking this down to whatever format is
        reported on a temporary I/O unit. The problem, however, is that this doesn't return a value for the sample rate which we need to
        retrieve from the AVAudioSession shared instance.
        */
        desc.componentType = kAudioUnitType_Output;
        desc.componentSubType = kAudioUnitSubType_RemoteIO;
        desc.componentManufacturer = kAudioUnitManufacturer_Apple;
        desc.componentFlags = 0;
        desc.componentFlagsMask = 0;
    
        component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(NULL, &desc);
        if (component == NULL) {
            return MA_FAILED_TO_INIT_BACKEND;
        }
    
        status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)(component, &audioUnit);
        if (status != noErr) {
            return ma_result_from_OSStatus(status);
        }
    
        formatScope   = (deviceType == ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
        formatElement = (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
    
        propSize = sizeof(bestFormat);
        status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
        if (status != noErr) {
            ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
            return ma_result_from_OSStatus(status);
        }
    
        ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
        audioUnit = NULL;
    
    
        pDeviceInfo->minChannels = bestFormat.mChannelsPerFrame;
        pDeviceInfo->maxChannels = bestFormat.mChannelsPerFrame;
    
        pDeviceInfo->formatCount = 1;
        result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pDeviceInfo->formats[0]);
        if (result != MA_SUCCESS) {
            return result;
        }
    
        /*
        It looks like Apple are wanting to push the whole AVAudioSession thing. Thus, we need to use that to determine device settings. To do
        this we just get the shared instance and inspect.
        */
        @autoreleasepool {
            AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
            MA_ASSERT(pAudioSession != NULL);

            pDeviceInfo->minSampleRate = (ma_uint32)pAudioSession.sampleRate;
            pDeviceInfo->maxSampleRate = pDeviceInfo->minSampleRate;
        }
    }
#endif
    
    (void)pDeviceInfo; /* Unused. */
    return MA_SUCCESS;
}

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

    if (deviceType == ma_device_type_duplex) {
        return MA_INVALID_ARGS;
    }

    MA_ASSERT(pContext != NULL);
    MA_ASSERT(deviceType == ma_device_type_playback || deviceType == ma_device_type_capture);

#if defined(MA_APPLE_DESKTOP)
    pData->deviceObjectID = 0;
#endif
    pData->component = NULL;
    pData->audioUnit = NULL;
    pData->pAudioBufferList = NULL;
    
#if defined(MA_APPLE_DESKTOP)
    result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
    if (result != MA_SUCCESS) {
        return result;
    }
    
    pData->deviceObjectID = deviceObjectID;
#endif
    
    /* Core audio doesn't really use the notion of a period so we can leave this unmodified, but not too over the top. */
    pData->periodsOut = pData->periodsIn;
    if (pData->periodsOut == 0) {
        pData->periodsOut = MA_DEFAULT_PERIODS;
    }
    if (pData->periodsOut > 16) {
        pData->periodsOut = 16;
    }
    
    
    /* Audio unit. */
    status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)((AudioComponent)pContext->coreaudio.component, (AudioUnit*)&pData->audioUnit);
    if (status != noErr) {
        return ma_result_from_OSStatus(status);
    }
    
    
    /* The input/output buses need to be explicitly enabled and disabled. We set the flag based on the output unit first, then we just swap it for input. */
    enableIOFlag = 1;
    if (deviceType == ma_device_type_capture) {
        enableIOFlag = 0;
    }
    
    status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &enableIOFlag, sizeof(enableIOFlag));
    if (status != noErr) {
        ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
        return ma_result_from_OSStatus(status);
    }
    
    enableIOFlag = (enableIOFlag == 0) ? 1 : 0;
    status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &enableIOFlag, sizeof(enableIOFlag));
    if (status != noErr) {
        ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
        return ma_result_from_OSStatus(status);
    }
    
    
    /* Set the device to use with this audio unit. This is only used on desktop since we are using defaults on mobile. */
#if defined(MA_APPLE_DESKTOP)
    status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_I...
    if (status != noErr) {
        ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
        return ma_result_from_OSStatus(result);
    }
#else
    /*
    For some reason it looks like Apple is only allowing selection of the input device. There does not appear to be any way to change
    the default output route. I have no idea why this is like this, but for now we'll only be able to configure capture devices.
    */
    if (pDeviceID != NULL) {
        if (deviceType == ma_device_type_capture) {
            ma_bool32 found = MA_FALSE;
            NSArray *pInputs = [[[AVAudioSession sharedInstance] currentRoute] inputs];
            for (AVAudioSessionPortDescription* pPortDesc in pInputs) {
                if (strcmp(pDeviceID->coreaudio, [pPortDesc.UID UTF8String]) == 0) {
                    [[AVAudioSession sharedInstance] setPreferredInput:pPortDesc error:nil];
                    found = MA_TRUE;
                    break;
                }
            }
            
            if (found == MA_FALSE) {
                return MA_DOES_NOT_EXIST;
            }
        }
    }
#endif
    
    /*
    Format. This is the hardest part of initialization because there's a few variables to take into account.
      1) The format must be supported by the device.
      2) The format must be supported miniaudio.
      3) There's a priority that miniaudio prefers.
    
    Ideally we would like to use a format that's as close to the hardware as possible so we can get as close to a passthrough as possible. The
    most important property is the sample rate. miniaudio can do format conversion for any sample rate and channel count, but cannot do the same
    for the sample data format. If the sample data format is not supported by miniaudio it must be ignored completely.
    
    On mobile platforms this is a bit different. We just force the use of whatever the audio unit's current format is set to.
    */
    {
        AudioUnitScope   formatScope   = (deviceType == ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
        AudioUnitElement formatElement = (deviceType == ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;

    #if defined(MA_APPLE_DESKTOP)
        AudioStreamBasicDescription origFormat;
        UInt32 origFormatSize;
        
        origFormatSize = sizeof(origFormat);
        status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &origFormat, &origFormatSize);
        if (status != noErr) {
            ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
            return result;
        }

        result = ma_find_best_format__coreaudio(pContext, deviceObjectID, deviceType, pData->formatIn, pData->channelsIn, pData->sampleRateIn, pData->usingDefaultFormat, pData->usingDefaultChannels, pData->usingDefaultSampleRate, &origFormat, &bestFo...
        if (result != MA_SUCCESS) {
            ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);



( run in 1.859 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )