451 #if defined(_MSC_VER)
452 #pragma warning(push)
453 #pragma warning(disable:4201)
454 #pragma warning(disable:4324)
456 #pragma GCC diagnostic push
457 #pragma GCC diagnostic ignored "-Wpedantic"
463 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
466 #define MA_WIN32_DESKTOP
474 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
487 #ifdef __EMSCRIPTEN__
488 #define MA_EMSCRIPTEN
496 #if defined(__clang__)
497 #pragma GCC diagnostic push
498 #pragma GCC diagnostic ignored "-Wlanguage-extension-token"
499 #pragma GCC diagnostic ignored "-Wc++11-long-long"
509 #if defined(__clang__)
510 #pragma GCC diagnostic pop
513 #define MA_HAS_STDINT
534 #elif defined(__GNUC__)
535 #if defined(__LP64__)
554 #if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
563 #if defined(SIZE_MAX)
564 #define MA_SIZE_MAX SIZE_MAX
566 #define MA_SIZE_MAX 0xFFFFFFFF
571 #define MA_INLINE __forceinline
574 #define MA_INLINE __inline__ __attribute__((always_inline))
580 #if defined(_MSC_VER)
582 #define MA_ALIGN(alignment) __declspec(align(alignment))
584 #elif !defined(__DMC__)
585 #define MA_ALIGN(alignment) __attribute__((aligned(alignment)))
588 #define MA_ALIGN(alignment)
592 #define MA_ALIGNED_STRUCT(alignment) MA_ALIGN(alignment) struct
594 #define MA_ALIGNED_STRUCT(alignment) struct MA_ALIGN(alignment)
598 #define MA_SIMD_ALIGNMENT 64
602 #define MA_LOG_LEVEL_VERBOSE 4
603 #define MA_LOG_LEVEL_INFO 3
604 #define MA_LOG_LEVEL_WARNING 2
605 #define MA_LOG_LEVEL_ERROR 1
608 #define MA_LOG_LEVEL MA_LOG_LEVEL_ERROR
615 #define MA_CHANNEL_NONE 0
616 #define MA_CHANNEL_MONO 1
617 #define MA_CHANNEL_FRONT_LEFT 2
618 #define MA_CHANNEL_FRONT_RIGHT 3
619 #define MA_CHANNEL_FRONT_CENTER 4
620 #define MA_CHANNEL_LFE 5
621 #define MA_CHANNEL_BACK_LEFT 6
622 #define MA_CHANNEL_BACK_RIGHT 7
623 #define MA_CHANNEL_FRONT_LEFT_CENTER 8
624 #define MA_CHANNEL_FRONT_RIGHT_CENTER 9
625 #define MA_CHANNEL_BACK_CENTER 10
626 #define MA_CHANNEL_SIDE_LEFT 11
627 #define MA_CHANNEL_SIDE_RIGHT 12
628 #define MA_CHANNEL_TOP_CENTER 13
629 #define MA_CHANNEL_TOP_FRONT_LEFT 14
630 #define MA_CHANNEL_TOP_FRONT_CENTER 15
631 #define MA_CHANNEL_TOP_FRONT_RIGHT 16
632 #define MA_CHANNEL_TOP_BACK_LEFT 17
633 #define MA_CHANNEL_TOP_BACK_CENTER 18
634 #define MA_CHANNEL_TOP_BACK_RIGHT 19
635 #define MA_CHANNEL_AUX_0 20
636 #define MA_CHANNEL_AUX_1 21
637 #define MA_CHANNEL_AUX_2 22
638 #define MA_CHANNEL_AUX_3 23
639 #define MA_CHANNEL_AUX_4 24
640 #define MA_CHANNEL_AUX_5 25
641 #define MA_CHANNEL_AUX_6 26
642 #define MA_CHANNEL_AUX_7 27
643 #define MA_CHANNEL_AUX_8 28
644 #define MA_CHANNEL_AUX_9 29
645 #define MA_CHANNEL_AUX_10 30
646 #define MA_CHANNEL_AUX_11 31
647 #define MA_CHANNEL_AUX_12 32
648 #define MA_CHANNEL_AUX_13 33
649 #define MA_CHANNEL_AUX_14 34
650 #define MA_CHANNEL_AUX_15 35
651 #define MA_CHANNEL_AUX_16 36
652 #define MA_CHANNEL_AUX_17 37
653 #define MA_CHANNEL_AUX_18 38
654 #define MA_CHANNEL_AUX_19 39
655 #define MA_CHANNEL_AUX_20 40
656 #define MA_CHANNEL_AUX_21 41
657 #define MA_CHANNEL_AUX_22 42
658 #define MA_CHANNEL_AUX_23 43
659 #define MA_CHANNEL_AUX_24 44
660 #define MA_CHANNEL_AUX_25 45
661 #define MA_CHANNEL_AUX_26 46
662 #define MA_CHANNEL_AUX_27 47
663 #define MA_CHANNEL_AUX_28 48
664 #define MA_CHANNEL_AUX_29 49
665 #define MA_CHANNEL_AUX_30 50
666 #define MA_CHANNEL_AUX_31 51
667 #define MA_CHANNEL_LEFT MA_CHANNEL_FRONT_LEFT
668 #define MA_CHANNEL_RIGHT MA_CHANNEL_FRONT_RIGHT
669 #define MA_CHANNEL_POSITION_COUNT MA_CHANNEL_AUX_31 + 1
677 #define MA_INVALID_ARGS -2
678 #define MA_INVALID_OPERATION -3
679 #define MA_OUT_OF_MEMORY -4
680 #define MA_ACCESS_DENIED -5
681 #define MA_TOO_LARGE -6
682 #define MA_TIMEOUT -7
685 #define MA_FORMAT_NOT_SUPPORTED -100
686 #define MA_DEVICE_TYPE_NOT_SUPPORTED -101
687 #define MA_SHARE_MODE_NOT_SUPPORTED -102
688 #define MA_NO_BACKEND -103
689 #define MA_NO_DEVICE -104
690 #define MA_API_NOT_FOUND -105
691 #define MA_INVALID_DEVICE_CONFIG -106
694 #define MA_DEVICE_BUSY -200
695 #define MA_DEVICE_NOT_INITIALIZED -201
696 #define MA_DEVICE_NOT_STARTED -202
697 #define MA_DEVICE_UNAVAILABLE -203
700 #define MA_FAILED_TO_MAP_DEVICE_BUFFER -300
701 #define MA_FAILED_TO_UNMAP_DEVICE_BUFFER -301
702 #define MA_FAILED_TO_INIT_BACKEND -302
703 #define MA_FAILED_TO_READ_DATA_FROM_CLIENT -303
704 #define MA_FAILED_TO_READ_DATA_FROM_DEVICE -304
705 #define MA_FAILED_TO_SEND_DATA_TO_CLIENT -305
706 #define MA_FAILED_TO_SEND_DATA_TO_DEVICE -306
707 #define MA_FAILED_TO_OPEN_BACKEND_DEVICE -307
708 #define MA_FAILED_TO_START_BACKEND_DEVICE -308
709 #define MA_FAILED_TO_STOP_BACKEND_DEVICE -309
710 #define MA_FAILED_TO_CONFIGURE_BACKEND_DEVICE -310
711 #define MA_FAILED_TO_CREATE_MUTEX -311
712 #define MA_FAILED_TO_CREATE_EVENT -312
713 #define MA_FAILED_TO_CREATE_THREAD -313
717 #define MA_SAMPLE_RATE_8000 8000
718 #define MA_SAMPLE_RATE_11025 11025
719 #define MA_SAMPLE_RATE_16000 16000
720 #define MA_SAMPLE_RATE_22050 22050
721 #define MA_SAMPLE_RATE_24000 24000
722 #define MA_SAMPLE_RATE_32000 32000
723 #define MA_SAMPLE_RATE_44100 44100
724 #define MA_SAMPLE_RATE_48000 48000
725 #define MA_SAMPLE_RATE_88200 88200
726 #define MA_SAMPLE_RATE_96000 96000
727 #define MA_SAMPLE_RATE_176400 176400
728 #define MA_SAMPLE_RATE_192000 192000
729 #define MA_SAMPLE_RATE_352800 352800
730 #define MA_SAMPLE_RATE_384000 384000
732 #define MA_MIN_PCM_SAMPLE_SIZE_IN_BYTES 1
733 #define MA_MAX_PCM_SAMPLE_SIZE_IN_BYTES 8
734 #define MA_MIN_CHANNELS 1
735 #define MA_MAX_CHANNELS 32
736 #define MA_MIN_SAMPLE_RATE MA_SAMPLE_RATE_8000
737 #define MA_MAX_SAMPLE_RATE MA_SAMPLE_RATE_384000
738 #define MA_SRC_SINC_MIN_WINDOW_WIDTH 2
739 #define MA_SRC_SINC_MAX_WINDOW_WIDTH 32
740 #define MA_SRC_SINC_DEFAULT_WINDOW_WIDTH 32
741 #define MA_SRC_SINC_LOOKUP_TABLE_RESOLUTION 8
742 #define MA_SRC_INPUT_BUFFER_SIZE_IN_SAMPLES 256
984 ma_bool32 isDynamicSampleRateAllowed : 1;
985 ma_bool32 isPreFormatConversionRequired : 1;
986 ma_bool32 isPostFormatConversionRequired : 1;
1348 ma_uint64 ma_convert_frames_ex(
void* pOut,
ma_format formatOut,
ma_uint32 channelsOut,
ma_uint32 sampleRateOut,
ma_channel channelMapOut[
MA_MAX_CHANNELS],
const void* pIn,
ma_format formatIn,
ma_uint32 channelsIn,
ma_uint32 sampleRateIn,
ma_channel channelMapIn[
MA_MAX_CHANNELS],
ma_uint64 frameCount);
1417 ma_result ma_rb_init_ex(
size_t subbufferSizeInBytes,
size_t subbufferCount,
size_t subbufferStrideInBytes,
void* pOptionalPreallocatedBuffer,
ma_rb* pRB);
1562 #ifndef MA_NO_DEVICE_IO
1564 #if defined(MA_WIN32)
1565 #define MA_SUPPORT_WASAPI
1566 #if defined(MA_WIN32_DESKTOP)
1567 #define MA_SUPPORT_DSOUND
1568 #define MA_SUPPORT_WINMM
1569 #define MA_SUPPORT_JACK
1572 #if defined(MA_UNIX)
1573 #if defined(MA_LINUX)
1574 #if !defined(MA_ANDROID)
1575 #define MA_SUPPORT_ALSA
1578 #if !defined(MA_BSD) && !defined(MA_ANDROID) && !defined(MA_EMSCRIPTEN)
1579 #define MA_SUPPORT_PULSEAUDIO
1580 #define MA_SUPPORT_JACK
1582 #if defined(MA_ANDROID)
1583 #define MA_SUPPORT_AAUDIO
1584 #define MA_SUPPORT_OPENSL
1586 #if defined(__OpenBSD__)
1587 #define MA_SUPPORT_SNDIO
1589 #if defined(__NetBSD__) || defined(__OpenBSD__)
1590 #define MA_SUPPORT_AUDIO4
1592 #if defined(__FreeBSD__) || defined(__DragonFly__)
1593 #define MA_SUPPORT_OSS
1596 #if defined(MA_APPLE)
1597 #define MA_SUPPORT_COREAUDIO
1599 #if defined(MA_EMSCRIPTEN)
1600 #define MA_SUPPORT_WEBAUDIO
1604 #if !defined(MA_EMSCRIPTEN)
1605 #define MA_SUPPORT_NULL
1609 #if !defined(MA_NO_WASAPI) && defined(MA_SUPPORT_WASAPI)
1610 #define MA_ENABLE_WASAPI
1612 #if !defined(MA_NO_DSOUND) && defined(MA_SUPPORT_DSOUND)
1613 #define MA_ENABLE_DSOUND
1615 #if !defined(MA_NO_WINMM) && defined(MA_SUPPORT_WINMM)
1616 #define MA_ENABLE_WINMM
1618 #if !defined(MA_NO_ALSA) && defined(MA_SUPPORT_ALSA)
1619 #define MA_ENABLE_ALSA
1621 #if !defined(MA_NO_PULSEAUDIO) && defined(MA_SUPPORT_PULSEAUDIO)
1622 #define MA_ENABLE_PULSEAUDIO
1624 #if !defined(MA_NO_JACK) && defined(MA_SUPPORT_JACK)
1625 #define MA_ENABLE_JACK
1627 #if !defined(MA_NO_COREAUDIO) && defined(MA_SUPPORT_COREAUDIO)
1628 #define MA_ENABLE_COREAUDIO
1630 #if !defined(MA_NO_SNDIO) && defined(MA_SUPPORT_SNDIO)
1631 #define MA_ENABLE_SNDIO
1633 #if !defined(MA_NO_AUDIO4) && defined(MA_SUPPORT_AUDIO4)
1634 #define MA_ENABLE_AUDIO4
1636 #if !defined(MA_NO_OSS) && defined(MA_SUPPORT_OSS)
1637 #define MA_ENABLE_OSS
1639 #if !defined(MA_NO_AAUDIO) && defined(MA_SUPPORT_AAUDIO)
1640 #define MA_ENABLE_AAUDIO
1642 #if !defined(MA_NO_OPENSL) && defined(MA_SUPPORT_OPENSL)
1643 #define MA_ENABLE_OPENSL
1645 #if !defined(MA_NO_WEBAUDIO) && defined(MA_SUPPORT_WEBAUDIO)
1646 #define MA_ENABLE_WEBAUDIO
1648 #if !defined(MA_NO_NULL) && defined(MA_SUPPORT_NULL)
1649 #define MA_ENABLE_NULL
1652 #ifdef MA_SUPPORT_WASAPI
1731 pthread_mutex_t mutex;
1753 pthread_mutex_t mutex;
1754 pthread_cond_t condition;
1819 #ifdef MA_SUPPORT_WASAPI
1822 #ifdef MA_SUPPORT_DSOUND
1825 #ifdef MA_SUPPORT_WINMM
1828 #ifdef MA_SUPPORT_ALSA
1831 #ifdef MA_SUPPORT_PULSEAUDIO
1834 #ifdef MA_SUPPORT_JACK
1837 #ifdef MA_SUPPORT_COREAUDIO
1838 char coreaudio[256];
1840 #ifdef MA_SUPPORT_SNDIO
1843 #ifdef MA_SUPPORT_AUDIO4
1846 #ifdef MA_SUPPORT_OSS
1849 #ifdef MA_SUPPORT_AAUDIO
1852 #ifdef MA_SUPPORT_OPENSL
1855 #ifdef MA_SUPPORT_WEBAUDIO
1858 #ifdef MA_SUPPORT_NULL
1983 #ifdef MA_SUPPORT_WASAPI
1989 #ifdef MA_SUPPORT_DSOUND
1999 #ifdef MA_SUPPORT_WINMM
2022 #ifdef MA_SUPPORT_ALSA
2028 ma_proc snd_pcm_hw_params_sizeof;
2029 ma_proc snd_pcm_hw_params_any;
2030 ma_proc snd_pcm_hw_params_set_format;
2031 ma_proc snd_pcm_hw_params_set_format_first;
2032 ma_proc snd_pcm_hw_params_get_format_mask;
2033 ma_proc snd_pcm_hw_params_set_channels_near;
2034 ma_proc snd_pcm_hw_params_set_rate_resample;
2035 ma_proc snd_pcm_hw_params_set_rate_near;
2036 ma_proc snd_pcm_hw_params_set_buffer_size_near;
2037 ma_proc snd_pcm_hw_params_set_periods_near;
2038 ma_proc snd_pcm_hw_params_set_access;
2039 ma_proc snd_pcm_hw_params_get_format;
2040 ma_proc snd_pcm_hw_params_get_channels;
2041 ma_proc snd_pcm_hw_params_get_channels_min;
2042 ma_proc snd_pcm_hw_params_get_channels_max;
2043 ma_proc snd_pcm_hw_params_get_rate;
2044 ma_proc snd_pcm_hw_params_get_rate_min;
2045 ma_proc snd_pcm_hw_params_get_rate_max;
2046 ma_proc snd_pcm_hw_params_get_buffer_size;
2047 ma_proc snd_pcm_hw_params_get_periods;
2048 ma_proc snd_pcm_hw_params_get_access;
2050 ma_proc snd_pcm_sw_params_sizeof;
2051 ma_proc snd_pcm_sw_params_current;
2052 ma_proc snd_pcm_sw_params_get_boundary;
2053 ma_proc snd_pcm_sw_params_set_avail_min;
2054 ma_proc snd_pcm_sw_params_set_start_threshold;
2055 ma_proc snd_pcm_sw_params_set_stop_threshold;
2057 ma_proc snd_pcm_format_mask_sizeof;
2058 ma_proc snd_pcm_format_mask_test;
2066 ma_proc snd_device_name_get_hint;
2068 ma_proc snd_device_name_free_hint;
2079 ma_proc snd_pcm_info_get_name;
2080 ma_proc snd_config_update_free_global;
2086 #ifdef MA_SUPPORT_PULSEAUDIO
2098 ma_proc pa_context_disconnect;
2099 ma_proc pa_context_set_state_callback;
2101 ma_proc pa_context_get_sink_info_list;
2102 ma_proc pa_context_get_source_info_list;
2103 ma_proc pa_context_get_sink_info_by_name;
2104 ma_proc pa_context_get_source_info_by_name;
2106 ma_proc pa_operation_get_state;
2107 ma_proc pa_channel_map_init_extend;
2109 ma_proc pa_channel_map_compatible;
2112 ma_proc pa_stream_connect_playback;
2113 ma_proc pa_stream_connect_record;
2116 ma_proc pa_stream_get_sample_spec;
2117 ma_proc pa_stream_get_channel_map;
2118 ma_proc pa_stream_get_buffer_attr;
2119 ma_proc pa_stream_set_buffer_attr;
2120 ma_proc pa_stream_get_device_name;
2121 ma_proc pa_stream_set_write_callback;
2122 ma_proc pa_stream_set_read_callback;
2128 ma_proc pa_stream_begin_write;
2132 ma_proc pa_stream_writable_size;
2133 ma_proc pa_stream_readable_size;
2135 char* pApplicationName;
2140 #ifdef MA_SUPPORT_JACK
2165 #ifdef MA_SUPPORT_COREAUDIO
2172 ma_proc AudioObjectGetPropertyData;
2173 ma_proc AudioObjectGetPropertyDataSize;
2174 ma_proc AudioObjectSetPropertyData;
2175 ma_proc AudioObjectAddPropertyListener;
2178 ma_proc AudioComponentFindNext;
2179 ma_proc AudioComponentInstanceDispose;
2180 ma_proc AudioComponentInstanceNew;
2183 ma_proc AudioUnitAddPropertyListener;
2184 ma_proc AudioUnitGetPropertyInfo;
2193 #ifdef MA_SUPPORT_SNDIO
2216 #ifdef MA_SUPPORT_AUDIO4
2222 #ifdef MA_SUPPORT_OSS
2229 #ifdef MA_SUPPORT_AAUDIO
2233 ma_proc AAudio_createStreamBuilder;
2234 ma_proc AAudioStreamBuilder_delete;
2235 ma_proc AAudioStreamBuilder_setDeviceId;
2236 ma_proc AAudioStreamBuilder_setDirection;
2237 ma_proc AAudioStreamBuilder_setSharingMode;
2238 ma_proc AAudioStreamBuilder_setFormat;
2239 ma_proc AAudioStreamBuilder_setChannelCount;
2240 ma_proc AAudioStreamBuilder_setSampleRate;
2241 ma_proc AAudioStreamBuilder_setBufferCapacityInFrames;
2242 ma_proc AAudioStreamBuilder_setFramesPerDataCallback;
2243 ma_proc AAudioStreamBuilder_setDataCallback;
2244 ma_proc AAudioStreamBuilder_setPerformanceMode;
2245 ma_proc AAudioStreamBuilder_openStream;
2247 ma_proc AAudioStream_getState;
2248 ma_proc AAudioStream_waitForStateChange;
2249 ma_proc AAudioStream_getFormat;
2250 ma_proc AAudioStream_getChannelCount;
2251 ma_proc AAudioStream_getSampleRate;
2252 ma_proc AAudioStream_getBufferCapacityInFrames;
2253 ma_proc AAudioStream_getFramesPerDataCallback;
2254 ma_proc AAudioStream_getFramesPerBurst;
2255 ma_proc AAudioStream_requestStart;
2256 ma_proc AAudioStream_requestStop;
2259 #ifdef MA_SUPPORT_OPENSL
2265 #ifdef MA_SUPPORT_WEBAUDIO
2271 #ifdef MA_SUPPORT_NULL
2309 ma_proc pthread_mutex_destroy;
2318 ma_proc pthread_attr_setschedpolicy;
2319 ma_proc pthread_attr_getschedparam;
2320 ma_proc pthread_attr_setschedparam;
2389 #ifdef MA_SUPPORT_WASAPI
2392 ma_ptr pAudioClientPlayback;
2393 ma_ptr pAudioClientCapture;
2396 ma_ptr pDeviceEnumerator;
2400 ma_uint32 actualBufferSizeInFramesPlayback;
2401 ma_uint32 actualBufferSizeInFramesCapture;
2403 ma_uint32 originalBufferSizeInMilliseconds;
2405 ma_bool32 hasDefaultPlaybackDeviceChanged;
2406 ma_bool32 hasDefaultCaptureDeviceChanged;
2413 #ifdef MA_SUPPORT_DSOUND
2417 ma_ptr pPlaybackPrimaryBuffer;
2423 #ifdef MA_SUPPORT_WINMM
2438 ma_uint8* pIntermediaryBufferPlayback;
2439 ma_uint8* pIntermediaryBufferCapture;
2444 #ifdef MA_SUPPORT_ALSA
2453 #ifdef MA_SUPPORT_PULSEAUDIO
2462 void* pMappedBufferPlayback;
2463 const void* pMappedBufferCapture;
2464 ma_uint32 mappedBufferFramesRemainingPlayback;
2465 ma_uint32 mappedBufferFramesRemainingCapture;
2466 ma_uint32 mappedBufferFramesCapacityPlayback;
2467 ma_uint32 mappedBufferFramesCapacityCapture;
2471 #ifdef MA_SUPPORT_JACK
2477 float* pIntermediaryBufferPlayback;
2478 float* pIntermediaryBufferCapture;
2482 #ifdef MA_SUPPORT_COREAUDIO
2487 ma_ptr audioUnitPlayback;
2492 ma_uint32 originalBufferSizeInMilliseconds;
2501 #ifdef MA_SUPPORT_SNDIO
2510 #ifdef MA_SUPPORT_AUDIO4
2517 #ifdef MA_SUPPORT_OSS
2524 #ifdef MA_SUPPORT_AAUDIO
2532 #ifdef MA_SUPPORT_OPENSL
2539 ma_ptr pAudioRecorderObj;
2541 ma_ptr pBufferQueuePlayback;
2542 ma_ptr pBufferQueueCapture;
2550 #ifdef MA_SUPPORT_WEBAUDIO
2558 #ifdef MA_SUPPORT_NULL
2567 double priorRunTime;
2568 ma_uint32 currentPeriodFramesRemainingPlayback;
2569 ma_uint32 currentPeriodFramesRemainingCapture;
2577 #if defined(_MSC_VER)
2578 #pragma warning(pop)
2580 #pragma GCC diagnostic pop
2990 #ifndef MA_NO_DECODING
3108 double periodsPerSecond;
3131 #if defined(MINIAUDIO_IMPLEMENTATION) || defined(MA_IMPLEMENTATION)
3136 #if defined(MA_DEBUG_OUTPUT)
3141 #include <windows.h>
3142 #include <objbase.h>
3144 #include <mmsystem.h>
3150 #if defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
3151 #include <mach/mach_time.h>
3155 #include <sys/time.h>
3156 #include <sys/types.h>
3161 #ifdef MA_EMSCRIPTEN
3162 #include <emscripten/emscripten.h>
3165 #if !defined(MA_64BIT) && !defined(MA_32BIT)
3175 #if !defined(MA_64BIT) && !defined(MA_32BIT)
3185 #if !defined(MA_64BIT) && !defined(MA_32BIT)
3187 #if INTPTR_MAX == INT64_MAX
3195 #if defined(__x86_64__) || defined(_M_X64)
3197 #elif defined(__i386) || defined(_M_IX86)
3199 #elif defined(__arm__) || defined(_M_ARM)
3204 #if !defined(MA_NO_AVX512) && defined(MA_NO_AVX2)
3205 #define MA_NO_AVX512
3209 #if defined(MA_X64) || defined(MA_X86)
3210 #if defined(_MSC_VER) && !defined(__clang__)
3212 #if _MSC_VER >= 1400 && !defined(MA_NO_SSE2)
3213 #define MA_SUPPORT_SSE2
3218 #if _MSC_VER >= 1700 && !defined(MA_NO_AVX2)
3219 #define MA_SUPPORT_AVX2
3221 #if _MSC_VER >= 1910 && !defined(MA_NO_AVX512)
3222 #define MA_SUPPORT_AVX512
3226 #if defined(__SSE2__) && !defined(MA_NO_SSE2)
3227 #define MA_SUPPORT_SSE2
3232 #if defined(__AVX2__) && !defined(MA_NO_AVX2)
3233 #define MA_SUPPORT_AVX2
3235 #if defined(__AVX512F__) && !defined(MA_NO_AVX512)
3236 #define MA_SUPPORT_AVX512
3241 #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
3242 #if !defined(MA_SUPPORT_SSE2) && !defined(MA_NO_SSE2) && __has_include(<emmintrin.h>)
3243 #define MA_SUPPORT_SSE2
3248 #if !defined(MA_SUPPORT_AVX2) && !defined(MA_NO_AVX2) && __has_include(<immintrin.h>)
3249 #define MA_SUPPORT_AVX2
3251 #if !defined(MA_SUPPORT_AVX512) && !defined(MA_NO_AVX512) && __has_include(<zmmintrin.h>)
3252 #define MA_SUPPORT_AVX512
3256 #if defined(MA_SUPPORT_AVX512)
3257 #include <immintrin.h>
3258 #elif defined(MA_SUPPORT_AVX2) || defined(MA_SUPPORT_AVX)
3259 #include <immintrin.h>
3260 #elif defined(MA_SUPPORT_SSE2)
3261 #include <emmintrin.h>
3266 #if !defined(MA_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
3267 #define MA_SUPPORT_NEON
3271 #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
3272 #if !defined(MA_SUPPORT_NEON) && !defined(MA_NO_NEON) && __has_include(<arm_neon.h>)
3273 #define MA_SUPPORT_NEON
3277 #if defined(MA_SUPPORT_NEON)
3278 #include <arm_neon.h>
3282 #if defined(_MSC_VER)
3283 #pragma warning(push)
3284 #pragma warning(disable:4752)
3287 #if defined(MA_X64) || defined(MA_X86)
3288 #if defined(_MSC_VER) && !defined(__clang__)
3289 #if _MSC_VER >= 1400
3291 static MA_INLINE void ma_cpuid(
int info[4],
int fid)
3299 #if _MSC_VER >= 1600
3300 static MA_INLINE unsigned __int64 ma_xgetbv(
int reg)
3302 return _xgetbv(reg);
3305 #define MA_NO_XGETBV
3307 #elif (defined(__GNUC__) || defined(__clang__)) && !defined(MA_ANDROID)
3308 static MA_INLINE void ma_cpuid(
int info[4],
int fid)
3317 #if defined(DRFLAC_X86) && defined(__PIC__)
3318 __asm__ __volatile__ (
3319 "xchg{l} {%%}ebx, %k1;"
3321 "xchg{l} {%%}ebx, %k1;"
3322 :
"=a"(info[0]),
"=&r"(info[1]),
"=c"(info[2]),
"=d"(info[3]) :
"a"(fid),
"c"(0)
3325 __asm__ __volatile__ (
3326 "cpuid" :
"=a"(info[0]),
"=b"(info[1]),
"=c"(info[2]),
"=d"(info[3]) :
"a"(fid),
"c"(0)
3336 __asm__ __volatile__ (
3337 "xgetbv" :
"=a"(lo),
"=d"(hi) :
"c"(reg)
3344 #define MA_NO_XGETBV
3348 #define MA_NO_XGETBV
3353 #if defined(MA_SUPPORT_SSE2)
3354 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_SSE2)
3357 #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)
3360 #if defined(MA_NO_CPUID)
3365 return (info[3] & (1 << 26)) != 0;
3379 #if defined(MA_SUPPORT_AVX)
3380 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX)
3381 #if defined(_AVX_) || defined(__AVX__)
3385 #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
3390 if (((info[2] & (1 << 27)) != 0) && ((info[2] & (1 << 28)) != 0)) {
3392 if ((xrc & 0x06) == 0x06) {
3413 #if defined(MA_SUPPORT_AVX2)
3414 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX2)
3415 #if defined(_AVX2_) || defined(__AVX2__)
3419 #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
3426 if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 5)) != 0)) {
3428 if ((xrc & 0x06) == 0x06) {
3448 #if defined(MA_SUPPORT_AVX512)
3449 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX512)
3450 #if defined(__AVX512F__)
3454 #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
3461 if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 16)) != 0)) {
3463 if ((xrc & 0xE6) == 0xE6) {
3483 #if defined(MA_SUPPORT_NEON)
3484 #if defined(MA_ARM) && !defined(MA_NO_NEON)
3485 #if (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
3502 #if defined(MA_X86) || defined(MA_X64)
3506 return (*(
char*)&n) == 1;
3512 return !ma_is_little_endian();
3516 #ifndef MA_COINIT_VALUE
3517 #define MA_COINIT_VALUE 0
3523 #define MA_PI 3.14159265358979323846264f
3526 #define MA_PI_D 3.14159265358979323846264
3529 #define MA_TAU 6.28318530717958647693f
3532 #define MA_TAU_D 6.28318530717958647693
3537 #ifndef MA_DEFAULT_FORMAT
3538 #define MA_DEFAULT_FORMAT ma_format_f32
3542 #ifndef MA_DEFAULT_CHANNELS
3543 #define MA_DEFAULT_CHANNELS 2
3547 #ifndef MA_DEFAULT_SAMPLE_RATE
3548 #define MA_DEFAULT_SAMPLE_RATE 48000
3552 #ifndef MA_DEFAULT_PERIODS
3553 #define MA_DEFAULT_PERIODS 3
3557 #ifndef MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_LOW_LATENCY
3558 #define MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_LOW_LATENCY (10*MA_DEFAULT_PERIODS)
3562 #ifndef MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_CONSERVATIVE
3563 #define MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_CONSERVATIVE (100*MA_DEFAULT_PERIODS)
3568 ma_uint32 g_maStandardSampleRatePriorities[] = {
3610 #define MA_MALLOC(sz) HeapAlloc(GetProcessHeap(), 0, (sz))
3612 #define MA_MALLOC(sz) malloc((sz))
3618 #define MA_REALLOC(p, sz) (((sz) > 0) ? ((p) ? HeapReAlloc(GetProcessHeap(), 0, (p), (sz)) : HeapAlloc(GetProcessHeap(), 0, (sz))) : ((VOID*)(size_t)(HeapFree(GetProcessHeap(), 0, (p)) & 0)))
3620 #define MA_REALLOC(p, sz) realloc((p), (sz))
3626 #define MA_FREE(p) HeapFree(GetProcessHeap(), 0, (p))
3628 #define MA_FREE(p) free((p))
3632 #ifndef MA_ZERO_MEMORY
3634 #define MA_ZERO_MEMORY(p, sz) ZeroMemory((p), (sz))
3636 #define MA_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
3640 #ifndef MA_COPY_MEMORY
3642 #define MA_COPY_MEMORY(dst, src, sz) CopyMemory((dst), (src), (sz))
3644 #define MA_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
3650 #define MA_ASSERT(condition) assert(condition)
3652 #define MA_ASSERT(condition) assert(condition)
3656 #define ma_zero_memory MA_ZERO_MEMORY
3657 #define ma_copy_memory MA_COPY_MEMORY
3658 #define ma_assert MA_ASSERT
3660 #define ma_zero_object(p) ma_zero_memory((p), sizeof(*(p)))
3661 #define ma_countof(x) (sizeof(x) / sizeof(x[0]))
3662 #define ma_max(x, y) (((x) > (y)) ? (x) : (y))
3663 #define ma_min(x, y) (((x) < (y)) ? (x) : (y))
3664 #define ma_clamp(x, lo, hi) (ma_max(lo, ma_min(x, hi)))
3665 #define ma_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
3667 #define ma_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / ma_get_bytes_per_sample(format) / (channels))
3677 int ma_strcpy_s(
char* dst,
size_t dstSizeInBytes,
const char* src)
3684 if (dstSizeInBytes == 0) {
3692 for (
i = 0;
i < dstSizeInBytes && src[
i] !=
'\0'; ++
i) {
3696 if (
i < dstSizeInBytes) {
3705 int ma_strncpy_s(
char* dst,
size_t dstSizeInBytes,
const char* src,
size_t count)
3713 if (dstSizeInBytes == 0) {
3722 if (
count == ((
size_t)-1) ||
count >= dstSizeInBytes) {
3723 maxcount = dstSizeInBytes - 1;
3726 for (
i = 0;
i < maxcount && src[
i] !=
'\0'; ++
i) {
3730 if (src[
i] ==
'\0' ||
i ==
count ||
count == ((
size_t)-1)) {
3739 int ma_strcat_s(
char* dst,
size_t dstSizeInBytes,
const char* src)
3746 if (dstSizeInBytes == 0) {
3756 while (dstSizeInBytes > 0 && dst[0] !=
'\0') {
3758 dstSizeInBytes -= 1;
3761 if (dstSizeInBytes == 0) {
3766 while (dstSizeInBytes > 0 && src[0] !=
'\0') {
3768 dstSizeInBytes -= 1;
3771 if (dstSizeInBytes > 0) {
3781 int ma_strncat_s(
char* dst,
size_t dstSizeInBytes,
const char* src,
size_t count)
3788 if (dstSizeInBytes == 0) {
3797 while (dstSizeInBytes > 0 && dst[0] !=
'\0') {
3799 dstSizeInBytes -= 1;
3802 if (dstSizeInBytes == 0) {
3807 if (
count == ((
size_t)-1)) {
3808 count = dstSizeInBytes - 1;
3811 while (dstSizeInBytes > 0 && src[0] !=
'\0' &&
count > 0) {
3813 dstSizeInBytes -= 1;
3817 if (dstSizeInBytes > 0) {
3827 int ma_itoa_s(
int value,
char* dst,
size_t dstSizeInBytes,
int radix)
3830 unsigned int valueU;
3833 if (dst ==
NULL || dstSizeInBytes == 0) {
3836 if (radix < 2 || radix > 36) {
3841 sign = (
value < 0 && radix == 10) ? -1 : 1;
3852 int remainder = valueU % radix;
3853 if (remainder > 9) {
3854 *dstEnd = (char)((remainder - 10) +
'a');
3856 *dstEnd = (char)(remainder +
'0');
3860 dstSizeInBytes -= 1;
3862 }
while (dstSizeInBytes > 0 && valueU > 0);
3864 if (dstSizeInBytes == 0) {
3871 dstSizeInBytes -= 1;
3874 if (dstSizeInBytes == 0) {
3884 while (dst < dstEnd) {
3896 int ma_strcmp(
const char* str1,
const char* str2)
3898 if (str1 == str2)
return 0;
3901 if (str1 ==
NULL)
return -1;
3902 if (str2 ==
NULL)
return 1;
3905 if (str1[0] ==
'\0') {
3908 if (str1[0] != str2[0]) {
3916 return ((
unsigned char*)str1)[0] - ((
unsigned char*)str2)[0];
3919 int ma_strappend(
char* dst,
size_t dstSize,
const char* srcA,
const char* srcB)
3923 result = ma_strncpy_s(dst, dstSize, srcA, (
size_t)-1);
3928 result = ma_strncat_s(dst, dstSize, srcB, (
size_t)-1);
3936 char* ma_copy_string(
const char* src)
3938 size_t sz = strlen(src)+1;
3944 ma_strcpy_s(dst, sz, src);
3951 static MA_INLINE unsigned int ma_next_power_of_2(
unsigned int x)
3964 static MA_INLINE unsigned int ma_prev_power_of_2(
unsigned int x)
3966 return ma_next_power_of_2(
x) >> 1;
3969 static MA_INLINE unsigned int ma_round_to_power_of_2(
unsigned int x)
3971 unsigned int prev = ma_prev_power_of_2(
x);
3972 unsigned int next = ma_next_power_of_2(
x);
3973 if ((next -
x) > (
x - prev)) {
3980 static MA_INLINE unsigned int ma_count_set_bits(
unsigned int x)
3982 unsigned int count = 0;
3999 if (
x < -1)
return -1;
4000 if (
x > +1)
return +1;
4004 static MA_INLINE float ma_mix_f32(
float x,
float y,
float a)
4006 return x*(1-a) +
y*a;
4008 static MA_INLINE float ma_mix_f32_fast(
float x,
float y,
float a)
4016 #if defined(MA_SUPPORT_SSE2)
4017 static MA_INLINE __m128 ma_mix_f32_fast__sse2(__m128
x, __m128
y, __m128 a)
4019 return _mm_add_ps(
x, _mm_mul_ps(_mm_sub_ps(
y,
x), a));
4022 #if defined(MA_SUPPORT_AVX2)
4023 static MA_INLINE __m256 ma_mix_f32_fast__avx2(__m256
x, __m256
y, __m256 a)
4025 return _mm256_add_ps(
x, _mm256_mul_ps(_mm256_sub_ps(
y,
x), a));
4028 #if defined(MA_SUPPORT_AVX512)
4029 static MA_INLINE __m512 ma_mix_f32_fast__avx512(__m512
x, __m512
y, __m512 a)
4031 return _mm512_add_ps(
x, _mm512_mul_ps(_mm512_sub_ps(
y,
x), a));
4034 #if defined(MA_SUPPORT_NEON)
4035 static MA_INLINE float32x4_t ma_mix_f32_fast__neon(float32x4_t
x, float32x4_t
y, float32x4_t a)
4037 return vaddq_f32(
x, vmulq_f32(vsubq_f32(
y,
x), a));
4042 static MA_INLINE double ma_mix_f64(
double x,
double y,
double a)
4044 return x*(1-a) +
y*a;
4046 static MA_INLINE double ma_mix_f64_fast(
double x,
double y,
double a)
4048 return x + (
y -
x)*a;
4051 static MA_INLINE float ma_scale_to_range_f32(
float x,
float lo,
float hi)
4053 return lo +
x*(hi-lo);
4066 #define MA_LCG_M 2147483647
4067 #define MA_LCG_A 48271
4079 ma_int32 r = (MA_LCG_A * lcg + MA_LCG_C) % MA_LCG_M;
4084 double ma_rand_f64()
4086 return (ma_rand_s32() + 0x80000000) / (double)0x7FFFFFFF;
4091 return (
float)ma_rand_f64();
4094 static MA_INLINE float ma_rand_range_f32(
float lo,
float hi)
4096 return ma_scale_to_range_f32(ma_rand_f32(), lo, hi);
4101 double x = ma_rand_f64();
4106 static MA_INLINE float ma_dither_f32_rectangle(
float ditherMin,
float ditherMax)
4108 return ma_rand_range_f32(ditherMin, ditherMax);
4111 static MA_INLINE float ma_dither_f32_triangle(
float ditherMin,
float ditherMax)
4113 float a = ma_rand_range_f32(ditherMin, 0);
4114 float b = ma_rand_range_f32(0, ditherMax);
4121 return ma_dither_f32_rectangle(ditherMin, ditherMax);
4124 return ma_dither_f32_triangle(ditherMin, ditherMax);
4133 ma_int32 a = ma_rand_range_s32(ditherMin, ditherMax);
4137 ma_int32 a = ma_rand_range_s32(ditherMin, 0);
4138 ma_int32 b = ma_rand_range_s32(0, ditherMax);
4150 void ma_split_buffer(
void* pBuffer,
size_t bufferSize,
size_t splitCount,
size_t alignment,
void** ppBuffersOut,
size_t* pSplitSizeOut)
4154 size_t unalignedBytes;
4157 if (pSplitSizeOut) {
4161 if (pBuffer ==
NULL || bufferSize == 0 || splitCount == 0) {
4165 if (alignment == 0) {
4170 pBufferAligned = (pBufferUnaligned + (alignment-1)) & ~(alignment-1);
4171 unalignedBytes = (size_t)(pBufferAligned - pBufferUnaligned);
4174 if (bufferSize >= unalignedBytes) {
4175 splitSize = (bufferSize - unalignedBytes) / splitCount;
4176 splitSize = splitSize & ~(alignment-1);
4179 if (ppBuffersOut !=
NULL) {
4181 for (
i = 0;
i < splitCount; ++
i) {
4182 ppBuffersOut[
i] = (
ma_uint8*)(pBufferAligned + (splitSize*
i));
4186 if (pSplitSizeOut) {
4187 *pSplitSizeOut = splitSize;
4197 #if defined(_WIN32) && !defined(__GNUC__)
4198 #define ma_memory_barrier() MemoryBarrier()
4199 #define ma_atomic_exchange_32(a, b) InterlockedExchange((LONG*)a, (LONG)b)
4200 #define ma_atomic_exchange_64(a, b) InterlockedExchange64((LONGLONG*)a, (LONGLONG)b)
4201 #define ma_atomic_increment_32(a) InterlockedIncrement((LONG*)a)
4202 #define ma_atomic_decrement_32(a) InterlockedDecrement((LONG*)a)
4204 #define ma_memory_barrier() __sync_synchronize()
4205 #define ma_atomic_exchange_32(a, b) (void)__sync_lock_test_and_set(a, b); __sync_synchronize()
4206 #define ma_atomic_exchange_64(a, b) (void)__sync_lock_test_and_set(a, b); __sync_synchronize()
4207 #define ma_atomic_increment_32(a) __sync_add_and_fetch(a, 1)
4208 #define ma_atomic_decrement_32(a) __sync_sub_and_fetch(a, 1)
4212 #define ma_atomic_exchange_ptr ma_atomic_exchange_64
4215 #define ma_atomic_exchange_ptr ma_atomic_exchange_32
4222 for (
i = 0;
i < ma_countof(g_maStandardSampleRatePriorities); ++
i) {
4223 if (g_maStandardSampleRatePriorities[
i] == sampleRate) {
4233 double srcRatio = (double)sampleRateOut / sampleRateIn;
4234 double frameCountOutF = (
ma_int64)frameCountIn * srcRatio;
4238 if ((frameCountOutF - (
ma_int64)frameCountOut) > 0.0) {
4242 return frameCountOut;
4254 #ifndef MA_NO_DEVICE_IO
4265 #ifndef MA_NO_RUNTIME_LINKING
4266 #if defined(MA_ANDROID) || defined(MA_EMSCRIPTEN)
4267 #define MA_NO_RUNTIME_LINKING
4275 #ifdef MA_ENABLE_WASAPI
4276 #define MA_HAS_WASAPI
4278 #ifdef MA_ENABLE_DSOUND
4279 #define MA_HAS_DSOUND
4281 #ifdef MA_ENABLE_WINMM
4282 #define MA_HAS_WINMM
4284 #ifdef MA_ENABLE_ALSA
4286 #ifdef MA_NO_RUNTIME_LINKING
4287 #ifdef __has_include
4288 #if !__has_include(<alsa/asoundlib.h>)
4294 #ifdef MA_ENABLE_PULSEAUDIO
4295 #define MA_HAS_PULSEAUDIO
4296 #ifdef MA_NO_RUNTIME_LINKING
4297 #ifdef __has_include
4298 #if !__has_include(<pulse/pulseaudio.h>)
4299 #undef MA_HAS_PULSEAUDIO
4304 #ifdef MA_ENABLE_JACK
4306 #ifdef MA_NO_RUNTIME_LINKING
4307 #ifdef __has_include
4308 #if !__has_include(<jack/jack.h>)
4314 #ifdef MA_ENABLE_COREAUDIO
4315 #define MA_HAS_COREAUDIO
4317 #ifdef MA_ENABLE_SNDIO
4318 #define MA_HAS_SNDIO
4320 #ifdef MA_ENABLE_AUDIO4
4321 #define MA_HAS_AUDIO4
4323 #ifdef MA_ENABLE_OSS
4326 #ifdef MA_ENABLE_AAUDIO
4327 #define MA_HAS_AAUDIO
4329 #ifdef MA_ENABLE_OPENSL
4330 #define MA_HAS_OPENSL
4332 #ifdef MA_ENABLE_WEBAUDIO
4333 #define MA_HAS_WEBAUDIO
4335 #ifdef MA_ENABLE_NULL
4357 default:
return "Unknown";
4364 #define MA_THREADCALL WINAPI
4365 typedef unsigned long ma_thread_result;
4367 #define MA_THREADCALL
4368 typedef void* ma_thread_result;
4370 typedef ma_thread_result (MA_THREADCALL * ma_thread_entry_proc)(
void* pData);
4373 typedef HRESULT (WINAPI * MA_PFN_CoInitializeEx)(LPVOID pvReserved,
DWORD dwCoInit);
4374 typedef void (WINAPI * MA_PFN_CoUninitialize)();
4375 typedef HRESULT (WINAPI * MA_PFN_CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN
pUnkOuter,
DWORD dwClsContext, REFIID riid, LPVOID *ppv);
4376 typedef void (WINAPI * MA_PFN_CoTaskMemFree)(LPVOID pv);
4377 typedef HRESULT (WINAPI * MA_PFN_PropVariantClear)(PROPVARIANT *pvar);
4378 typedef int (WINAPI * MA_PFN_StringFromGUID2)(
const GUID*
const rguid, LPOLESTR lpsz,
int cchMax);
4380 typedef HWND (WINAPI * MA_PFN_GetForegroundWindow)();
4381 typedef HWND (WINAPI * MA_PFN_GetDesktopWindow)();
4384 typedef LONG (WINAPI * MA_PFN_RegOpenKeyExA)(HKEY hKey, LPCSTR lpSubKey,
DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
4385 typedef LONG (WINAPI * MA_PFN_RegCloseKey)(HKEY hKey);
4386 typedef LONG (WINAPI * MA_PFN_RegQueryValueExA)(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE
lpData, LPDWORD lpcbData);
4390 #define MA_STATE_UNINITIALIZED 0
4391 #define MA_STATE_STOPPED 1
4392 #define MA_STATE_STARTED 2
4393 #define MA_STATE_STARTING 3
4394 #define MA_STATE_STOPPING 4
4396 #define MA_DEFAULT_PLAYBACK_DEVICE_NAME "Default Playback Device"
4397 #define MA_DEFAULT_CAPTURE_DEVICE_NAME "Default Capture Device"
4408 default:
return "ERROR";
4415 if (pContext ==
NULL) {
4419 #if defined(MA_LOG_LEVEL)
4423 #if defined(MA_DEBUG_OUTPUT)
4431 onLog(pContext, pDevice, logLevel, message);
4441 if (pContext ==
NULL) {
4442 if (pDevice !=
NULL) {
4443 pContext = pDevice->pContext;
4447 ma_log(pContext, pDevice, logLevel, message);
4453 return ma_context_post_error(
NULL, pDevice, logLevel, message, resultCode);
4463 LARGE_INTEGER g_ma_TimerFrequency = {{0}};
4464 void ma_timer_init(
ma_timer* pTimer)
4466 LARGE_INTEGER counter;
4468 if (g_ma_TimerFrequency.QuadPart == 0) {
4469 QueryPerformanceFrequency(&g_ma_TimerFrequency);
4472 QueryPerformanceCounter(&counter);
4473 pTimer->
counter = counter.QuadPart;
4476 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4478 LARGE_INTEGER counter;
4479 if (!QueryPerformanceCounter(&counter)) {
4483 return (
double)(counter.QuadPart - pTimer->
counter) / g_ma_TimerFrequency.QuadPart;
4485 #elif defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
4487 void ma_timer_init(
ma_timer* pTimer)
4489 mach_timebase_info_data_t baseTime;
4490 mach_timebase_info(&baseTime);
4491 g_ma_TimerFrequency = (baseTime.denom * 1e9) / baseTime.numer;
4493 pTimer->
counter = mach_absolute_time();
4496 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4498 ma_uint64 newTimeCounter = mach_absolute_time();
4501 return (newTimeCounter - oldTimeCounter) / g_ma_TimerFrequency;
4503 #elif defined(MA_EMSCRIPTEN)
4504 void ma_timer_init(
ma_timer* pTimer)
4506 pTimer->
counterD = emscripten_get_now();
4509 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4511 return (emscripten_get_now() - pTimer->
counterD) / 1000;
4514 #if _POSIX_C_SOURCE >= 199309L
4515 #if defined(CLOCK_MONOTONIC)
4516 #define MA_CLOCK_ID CLOCK_MONOTONIC
4518 #define MA_CLOCK_ID CLOCK_REALTIME
4521 void ma_timer_init(
ma_timer* pTimer)
4523 struct timespec newTime;
4524 clock_gettime(MA_CLOCK_ID, &newTime);
4526 pTimer->
counter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
4529 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4534 struct timespec newTime;
4535 clock_gettime(MA_CLOCK_ID, &newTime);
4537 newTimeCounter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
4538 oldTimeCounter = pTimer->
counter;
4540 return (newTimeCounter - oldTimeCounter) / 1000000000.0;
4543 void ma_timer_init(
ma_timer* pTimer)
4545 struct timeval newTime;
4546 gettimeofday(&newTime,
NULL);
4548 pTimer->
counter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
4551 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4556 struct timeval newTime;
4557 gettimeofday(&newTime,
NULL);
4559 newTimeCounter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
4560 oldTimeCounter = pTimer->
counter;
4562 return (newTimeCounter - oldTimeCounter) / 1000000.0;
4577 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_VERBOSE
4578 if (pContext !=
NULL) {
4580 ma_strappend(message,
sizeof(message),
"Loading library: ", filename);
4586 #ifdef MA_WIN32_DESKTOP
4587 handle = (
ma_handle)LoadLibraryA(filename);
4590 WCHAR filenameW[4096];
4591 if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW,
sizeof(filenameW)) == 0) {
4594 handle = (
ma_handle)LoadPackagedLibrary(filenameW, 0);
4598 handle = (
ma_handle)dlopen(filename, RTLD_NOW);
4605 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_INFO
4606 if (handle ==
NULL) {
4608 ma_strappend(message,
sizeof(message),
"Failed to load library: ", filename);
4620 FreeLibrary((HMODULE)handle);
4622 dlclose((
void*)handle);
4632 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_VERBOSE
4633 if (pContext !=
NULL) {
4635 ma_strappend(message,
sizeof(message),
"Loading symbol: ", symbol);
4641 proc = (
ma_proc)GetProcAddress((HMODULE)handle, symbol);
4643 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
4644 #pragma GCC diagnostic push
4645 #pragma GCC diagnostic ignored "-Wpedantic"
4647 proc = (
ma_proc)dlsym((
void*)handle, symbol);
4648 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
4649 #pragma GCC diagnostic pop
4653 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_WARNING
4654 if (handle ==
NULL) {
4656 ma_strappend(message,
sizeof(message),
"Failed to load symbol: ", symbol);
4682 default:
return THREAD_PRIORITY_NORMAL;
4688 pThread->
win32.hThread = CreateThread(
NULL, 0, entryProc, pData, 0,
NULL);
4693 SetThreadPriority((HANDLE)pThread->
win32.hThread, ma_thread_priority_to_win32(pContext->
threadPriority));
4698 void ma_thread_wait__win32(
ma_thread* pThread)
4700 WaitForSingleObject(pThread->
win32.hThread, INFINITE);
4703 void ma_sleep__win32(
ma_uint32 milliseconds)
4705 Sleep((
DWORD)milliseconds);
4721 void ma_mutex_uninit__win32(
ma_mutex* pMutex)
4723 CloseHandle(pMutex->
win32.hMutex);
4726 void ma_mutex_lock__win32(
ma_mutex* pMutex)
4728 WaitForSingleObject(pMutex->
win32.hMutex, INFINITE);
4731 void ma_mutex_unlock__win32(
ma_mutex* pMutex)
4733 SetEvent(pMutex->
win32.hMutex);
4749 void ma_event_uninit__win32(
ma_event* pEvent)
4751 CloseHandle(pEvent->
win32.hEvent);
4756 return WaitForSingleObject(pEvent->
win32.hEvent, INFINITE) == WAIT_OBJECT_0;
4761 return SetEvent(pEvent->
win32.hEvent);
4769 typedef int (* ma_pthread_create_proc)(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (
void *),
void *arg);
4770 typedef int (* ma_pthread_join_proc)(pthread_t thread,
void **retval);
4771 typedef int (* ma_pthread_mutex_init_proc)(pthread_mutex_t *__mutex,
const pthread_mutexattr_t *__mutexattr);
4772 typedef int (* ma_pthread_mutex_destroy_proc)(pthread_mutex_t *__mutex);
4773 typedef int (* ma_pthread_mutex_lock_proc)(pthread_mutex_t *__mutex);
4774 typedef int (* ma_pthread_mutex_unlock_proc)(pthread_mutex_t *__mutex);
4775 typedef int (* ma_pthread_cond_init_proc)(pthread_cond_t *__restrict __cond,
const pthread_condattr_t *__restrict __cond_attr);
4776 typedef int (* ma_pthread_cond_destroy_proc)(pthread_cond_t *__cond);
4777 typedef int (* ma_pthread_cond_signal_proc)(pthread_cond_t *__cond);
4778 typedef int (* ma_pthread_cond_wait_proc)(pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex);
4779 typedef int (* ma_pthread_attr_init_proc)(pthread_attr_t *attr);
4780 typedef int (* ma_pthread_attr_destroy_proc)(pthread_attr_t *attr);
4781 typedef int (* ma_pthread_attr_setschedpolicy_proc)(pthread_attr_t *attr,
int policy);
4782 typedef int (* ma_pthread_attr_getschedparam_proc)(
const pthread_attr_t *attr,
struct sched_param *
param);
4783 typedef int (* ma_pthread_attr_setschedparam_proc)(pthread_attr_t *attr,
const struct sched_param *
param);
4788 pthread_attr_t* pAttr =
NULL;
4790 #if !defined(__EMSCRIPTEN__)
4792 pthread_attr_t attr;
4793 if (((ma_pthread_attr_init_proc)pContext->posix.pthread_attr_init)(&attr) == 0) {
4797 if (((ma_pthread_attr_setschedpolicy_proc)pContext->posix.pthread_attr_setschedpolicy)(&attr, SCHED_IDLE) == 0) {
4798 scheduler = SCHED_IDLE;
4803 if (((ma_pthread_attr_setschedpolicy_proc)pContext->posix.pthread_attr_setschedpolicy)(&attr, SCHED_FIFO) == 0) {
4804 scheduler = SCHED_FIFO;
4809 scheduler = sched_getscheduler(0);
4813 if (scheduler != -1) {
4814 int priorityMin = sched_get_priority_min(scheduler);
4815 int priorityMax = sched_get_priority_max(scheduler);
4816 int priorityStep = (priorityMax - priorityMin) / 7;
4818 struct sched_param sched;
4819 if (((ma_pthread_attr_getschedparam_proc)pContext->posix.pthread_attr_getschedparam)(&attr, &sched) == 0) {
4821 sched.sched_priority = priorityMin;
4823 sched.sched_priority = priorityMax;
4826 if (sched.sched_priority < priorityMin) {
4827 sched.sched_priority = priorityMin;
4829 if (sched.sched_priority > priorityMax) {
4830 sched.sched_priority = priorityMax;
4834 if (((ma_pthread_attr_setschedparam_proc)pContext->posix.pthread_attr_setschedparam)(&attr, &sched) == 0) {
4840 ((ma_pthread_attr_destroy_proc)pContext->posix.pthread_attr_destroy)(&attr);
4844 result = ((ma_pthread_create_proc)pContext->posix.pthread_create)(&pThread->posix.thread, pAttr, entryProc, pData);
4852 void ma_thread_wait__posix(
ma_thread* pThread)
4854 ((ma_pthread_join_proc)pThread->
pContext->posix.pthread_join)(pThread->posix.thread,
NULL);
4857 void ma_sleep__posix(
ma_uint32 milliseconds)
4859 #ifdef MA_EMSCRIPTEN
4863 #if _POSIX_C_SOURCE >= 199309L
4865 ts.tv_sec = milliseconds / 1000000;
4866 ts.tv_nsec = milliseconds % 1000000 * 1000000;
4867 nanosleep(&ts,
NULL);
4870 tv.tv_sec = milliseconds / 1000;
4871 tv.tv_usec = milliseconds % 1000 * 1000;
4880 int result = ((ma_pthread_mutex_init_proc)pContext->posix.pthread_mutex_init)(&pMutex->posix.mutex,
NULL);
4888 void ma_mutex_uninit__posix(
ma_mutex* pMutex)
4890 ((ma_pthread_mutex_destroy_proc)pMutex->
pContext->posix.pthread_mutex_destroy)(&pMutex->posix.mutex);
4893 void ma_mutex_lock__posix(
ma_mutex* pMutex)
4895 ((ma_pthread_mutex_lock_proc)pMutex->
pContext->posix.pthread_mutex_lock)(&pMutex->posix.mutex);
4898 void ma_mutex_unlock__posix(
ma_mutex* pMutex)
4900 ((ma_pthread_mutex_unlock_proc)pMutex->
pContext->posix.pthread_mutex_unlock)(&pMutex->posix.mutex);
4906 if (((ma_pthread_mutex_init_proc)pContext->posix.pthread_mutex_init)(&pEvent->posix.mutex,
NULL) != 0) {
4910 if (((ma_pthread_cond_init_proc)pContext->posix.pthread_cond_init)(&pEvent->posix.condition,
NULL) != 0) {
4914 pEvent->posix.value = 0;
4918 void ma_event_uninit__posix(
ma_event* pEvent)
4920 ((ma_pthread_cond_destroy_proc)pEvent->
pContext->posix.pthread_cond_destroy)(&pEvent->posix.condition);
4921 ((ma_pthread_mutex_destroy_proc)pEvent->
pContext->posix.pthread_mutex_destroy)(&pEvent->posix.mutex);
4926 ((ma_pthread_mutex_lock_proc)pEvent->
pContext->posix.pthread_mutex_lock)(&pEvent->posix.mutex);
4928 while (pEvent->posix.value == 0) {
4929 ((ma_pthread_cond_wait_proc)pEvent->
pContext->posix.pthread_cond_wait)(&pEvent->posix.condition, &pEvent->posix.mutex);
4931 pEvent->posix.value = 0;
4933 ((ma_pthread_mutex_unlock_proc)pEvent->
pContext->posix.pthread_mutex_unlock)(&pEvent->posix.mutex);
4940 ((ma_pthread_mutex_lock_proc)pEvent->
pContext->posix.pthread_mutex_lock)(&pEvent->posix.mutex);
4942 pEvent->posix.value = 1;
4943 ((ma_pthread_cond_signal_proc)pEvent->
pContext->posix.pthread_cond_signal)(&pEvent->posix.condition);
4945 ((ma_pthread_mutex_unlock_proc)pEvent->
pContext->posix.pthread_mutex_unlock)(&pEvent->posix.mutex);
4953 if (pContext ==
NULL || pThread ==
NULL || entryProc ==
NULL) {
4960 return ma_thread_create__win32(pContext, pThread, entryProc, pData);
4963 return ma_thread_create__posix(pContext, pThread, entryProc, pData);
4969 if (pThread ==
NULL) {
4974 ma_thread_wait__win32(pThread);
4977 ma_thread_wait__posix(pThread);
4984 ma_sleep__win32(milliseconds);
4987 ma_sleep__posix(milliseconds);
4994 if (pContext ==
NULL || pMutex ==
NULL) {
5001 return ma_mutex_init__win32(pContext, pMutex);
5004 return ma_mutex_init__posix(pContext, pMutex);
5015 ma_mutex_uninit__win32(pMutex);
5018 ma_mutex_uninit__posix(pMutex);
5029 ma_mutex_lock__win32(pMutex);
5032 ma_mutex_lock__posix(pMutex);
5043 ma_mutex_unlock__win32(pMutex);
5046 ma_mutex_unlock__posix(pMutex);
5053 if (pContext ==
NULL || pEvent ==
NULL) {
5060 return ma_event_init__win32(pContext, pEvent);
5063 return ma_event_init__posix(pContext, pEvent);
5067 void ma_event_uninit(
ma_event* pEvent)
5074 ma_event_uninit__win32(pEvent);
5077 ma_event_uninit__posix(pEvent);
5088 return ma_event_wait__win32(pEvent);
5091 return ma_event_wait__posix(pEvent);
5102 return ma_event_signal__win32(pEvent);
5105 return ma_event_signal__posix(pEvent);
5119 if (sampleRateMin > sampleRateMax) {
5120 sampleRateMin = sampleRateMax;
5123 if (sampleRateMin == sampleRateMax) {
5124 return sampleRateMax;
5126 size_t iStandardRate;
5127 for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
5128 ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
5129 if (standardRate >= sampleRateMin && standardRate <= sampleRateMax) {
5130 return standardRate;
5144 size_t iStandardRate;
5146 for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
5147 ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
5150 if (sampleRateIn > standardRate) {
5151 diff = sampleRateIn - standardRate;
5153 diff = standardRate - sampleRateIn;
5157 return standardRate;
5160 if (closestDiff > diff) {
5162 closestRate = standardRate;
5172 return ma_max(1, (
ma_uint32)(baseBufferSize*scale));
5177 return bufferSizeInFrames / (sampleRate/1000);
5182 return bufferSizeInMilliseconds * (sampleRate/1000);
5188 return MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_LOW_LATENCY;
5190 return MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_CONSERVATIVE;
5200 if (bufferSizeInMilliseconds == 0) {
5201 bufferSizeInMilliseconds = 1;
5204 sampleRateMS = (sampleRate/1000);
5205 if (sampleRateMS == 0) {
5209 return bufferSizeInMilliseconds * sampleRateMS;
5214 ma_uint32 fragmentSizeInFrames = bufferSizeInFrames / periods;
5231 ma_assert(pDevice !=
NULL);
5233 ma_zero_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels);
5235 onData = pDevice->onData;
5237 onData(pDevice, pFramesOut,
NULL, frameCount);
5252 ma_assert(pDevice !=
NULL);
5254 if (pDevice->capture._dspFrameCount == 0) {
5258 framesToRead = frameCount;
5259 if (framesToRead > pDevice->capture._dspFrameCount) {
5260 framesToRead = pDevice->capture._dspFrameCount;
5263 bytesToRead = framesToRead *
ma_get_bytes_per_frame(pConverter->formatConverterIn.config.formatIn, pConverter->channelRouter.config.channelsIn);
5264 ma_copy_memory(pFramesOut, pDevice->capture._dspFrames, bytesToRead);
5265 pDevice->capture._dspFrameCount -= framesToRead;
5266 pDevice->capture._dspFrames += bytesToRead;
5268 return framesToRead;
5277 ma_assert(pDevice !=
NULL);
5279 if (pDevice->playback._dspFrameCount == 0) {
5283 framesToRead = frameCount;
5284 if (framesToRead > pDevice->playback._dspFrameCount) {
5285 framesToRead = pDevice->playback._dspFrameCount;
5288 bytesToRead = framesToRead *
ma_get_bytes_per_frame(pConverter->formatConverterIn.config.formatIn, pConverter->channelRouter.config.channelsIn);
5289 ma_copy_memory(pFramesOut, pDevice->playback._dspFrames, bytesToRead);
5290 pDevice->playback._dspFrameCount -= framesToRead;
5291 pDevice->playback._dspFrames += bytesToRead;
5293 return framesToRead;
5303 ma_assert(pDevice !=
NULL);
5304 ma_assert(frameCount > 0);
5305 ma_assert(pSamples !=
NULL);
5307 onData = pDevice->onData;
5309 if (pDevice->playback.converter.isPassthrough) {
5310 ma_zero_pcm_frames(pSamples, frameCount, pDevice->playback.format, pDevice->playback.channels);
5311 onData(pDevice, pSamples,
NULL, frameCount);
5323 ma_assert(pDevice !=
NULL);
5324 ma_assert(frameCount > 0);
5325 ma_assert(pSamples !=
NULL);
5327 onData = pDevice->onData;
5329 if (pDevice->capture.converter.isPassthrough) {
5330 onData(pDevice,
NULL, pSamples, frameCount);
5335 pDevice->capture._dspFrameCount = frameCount;
5336 pDevice->capture._dspFrames = (
const ma_uint8*)pSamples;
5338 chunkFrameCount =
sizeof(chunkBuffer) /
ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
5342 if (framesJustRead == 0) {
5346 onData(pDevice,
NULL, chunkBuffer, framesJustRead);
5348 if (framesJustRead < chunkFrameCount) {
5360 ma_assert(pDevice !=
NULL);
5361 ma_assert(frameCount > 0);
5362 ma_assert(pFramesInInternalFormat !=
NULL);
5363 ma_assert(pRB !=
NULL);
5365 pDevice->capture._dspFrameCount = (
ma_uint32)frameCount;
5366 pDevice->capture._dspFrames = (
const ma_uint8*)pFramesInInternalFormat;
5372 void* pFramesInExternalFormat;
5376 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"Failed to acquire capture PCM frames from ring buffer.", result);
5380 if (framesToProcess == 0) {
5391 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"Failed to commit capture PCM frames to ring buffer.", result);
5395 if (framesProcessed < framesToProcess) {
5406 ma_uint8 playbackFramesInExternalFormat[4096];
5411 ma_assert(pDevice !=
NULL);
5412 ma_assert(frameCount > 0);
5413 ma_assert(pFramesInInternalFormat !=
NULL);
5414 ma_assert(pRB !=
NULL);
5420 ma_zero_memory(silentInputFrames,
sizeof(silentInputFrames));
5423 totalFramesToReadFromClient = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->playback.internalSampleRate, frameCount);
5424 totalFramesReadFromClient = 0;
5425 while (totalFramesReadFromClient < totalFramesToReadFromClient &&
ma_device_is_started(pDevice)) {
5431 framesRemainingFromClient = (totalFramesToReadFromClient - totalFramesReadFromClient);
5432 framesToProcessFromClient =
sizeof(playbackFramesInExternalFormat) /
ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
5433 if (framesToProcessFromClient > framesRemainingFromClient) {
5434 framesToProcessFromClient = framesRemainingFromClient;
5438 inputFrameCount = framesToProcessFromClient;
5441 if (inputFrameCount > 0) {
5443 pDevice->onData(pDevice, playbackFramesInExternalFormat, pInputFrames, inputFrameCount);
5457 inputFrameCount = ma_min(
5458 sizeof(playbackFramesInExternalFormat) /
ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels),
5462 pDevice->onData(pDevice, playbackFramesInExternalFormat, silentInputFrames, inputFrameCount);
5466 pDevice->playback._dspFrameCount = inputFrameCount;
5467 pDevice->playback._dspFrames = (
const ma_uint8*)playbackFramesInExternalFormat;
5470 totalFramesReadFromClient += inputFrameCount;
5471 pFramesInInternalFormat = ma_offset_ptr(pFramesInInternalFormat, inputFrameCount *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
5480 ma_atomic_exchange_32(&pDevice->state, newState);
5486 return pDevice->state;
5492 return pDevice->onData !=
NULL;
5497 GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
5498 GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
5506 ma_assert(pContext !=
NULL);
5508 if (pID0 == pID1)
return MA_TRUE;
5510 if ((pID0 ==
NULL && pID1 !=
NULL) ||
5528 size_t nameBufferSize;
5530 } ma_context__try_get_device_name_by_id__enum_callback_data;
5534 ma_context__try_get_device_name_by_id__enum_callback_data* pData = (ma_context__try_get_device_name_by_id__enum_callback_data*)pUserData;
5535 ma_assert(pData !=
NULL);
5537 if (pData->deviceType == deviceType) {
5539 ma_strncpy_s(pData->pName, pData->nameBufferSize, pDeviceInfo->
name, (
size_t)-1);
5544 return !pData->foundDevice;
5555 ma_context__try_get_device_name_by_id__enum_callback_data data;
5557 ma_assert(pContext !=
NULL);
5558 ma_assert(pName !=
NULL);
5560 if (pDeviceID ==
NULL) {
5564 data.deviceType = deviceType;
5565 data.pDeviceID = pDeviceID;
5567 data.nameBufferSize = nameBufferSize;
5574 if (!data.foundDevice) {
5585 for (
i = 0;
i < ma_countof(g_maFormatPriorities); ++
i) {
5586 if (g_maFormatPriorities[
i] ==
format) {
5605 #define MA_DEVICE_OP_NONE__NULL 0
5606 #define MA_DEVICE_OP_START__NULL 1
5607 #define MA_DEVICE_OP_SUSPEND__NULL 2
5608 #define MA_DEVICE_OP_KILL__NULL 3
5610 ma_thread_result MA_THREADCALL ma_device_thread__null(
void* pData)
5613 ma_assert(pDevice !=
NULL);
5617 ma_event_wait(&pDevice->null_device.operationEvent);
5622 if (pDevice->null_device.operation == MA_DEVICE_OP_START__NULL) {
5623 ma_atomic_exchange_32(&pDevice->null_device.operation, MA_DEVICE_OP_NONE__NULL);
5626 ma_timer_init(&pDevice->null_device.timer);
5629 while (pDevice->null_device.operation != MA_DEVICE_OP_NONE__NULL && pDevice->null_device.operation != MA_DEVICE_OP_START__NULL) {
5634 ma_atomic_exchange_32(&pDevice->null_device.operationResult,
MA_SUCCESS);
5635 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
5640 if (pDevice->null_device.operation == MA_DEVICE_OP_SUSPEND__NULL) {
5641 ma_atomic_exchange_32(&pDevice->null_device.operation, MA_DEVICE_OP_NONE__NULL);
5644 pDevice->null_device.priorRunTime += ma_timer_get_time_in_seconds(&pDevice->null_device.timer);
5645 ma_timer_init(&pDevice->null_device.timer);
5648 ma_atomic_exchange_32(&pDevice->null_device.operationResult,
MA_SUCCESS);
5649 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
5654 if (pDevice->null_device.operation == MA_DEVICE_OP_KILL__NULL) {
5655 ma_atomic_exchange_32(&pDevice->null_device.operation, MA_DEVICE_OP_NONE__NULL);
5656 ma_atomic_exchange_32(&pDevice->null_device.operationResult,
MA_SUCCESS);
5657 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
5662 if (pDevice->null_device.operation == MA_DEVICE_OP_NONE__NULL) {
5665 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
5670 return (ma_thread_result)0;
5675 ma_atomic_exchange_32(&pDevice->null_device.operation, operation);
5676 if (!ma_event_signal(&pDevice->null_device.operationEvent)) {
5680 if (!ma_event_wait(&pDevice->null_device.operationCompletionEvent)) {
5684 return pDevice->null_device.operationResult;
5691 internalSampleRate = pDevice->capture.internalSampleRate;
5693 internalSampleRate = pDevice->playback.internalSampleRate;
5697 return (
ma_uint64)((pDevice->null_device.priorRunTime + ma_timer_get_time_in_seconds(&pDevice->null_device.timer)) * internalSampleRate);
5702 ma_assert(pContext !=
NULL);
5703 ma_assert(pID0 !=
NULL);
5704 ma_assert(pID1 !=
NULL);
5714 ma_assert(pContext !=
NULL);
5715 ma_assert(callback !=
NULL);
5720 ma_zero_object(&deviceInfo);
5721 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name),
"NULL Playback Device", (
size_t)-1);
5728 ma_zero_object(&deviceInfo);
5729 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name),
"NULL Capture Device", (
size_t)-1);
5740 ma_assert(pContext !=
NULL);
5748 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name),
"NULL Playback Device", (
size_t)-1);
5750 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name),
"NULL Capture Device", (
size_t)-1);
5755 for (iFormat = 0; iFormat < pDeviceInfo->
formatCount; ++iFormat) {
5770 void ma_device_uninit__null(
ma_device* pDevice)
5772 ma_assert(pDevice !=
NULL);
5775 ma_device_do_operation__null(pDevice, MA_DEVICE_OP_KILL__NULL);
5778 ma_event_uninit(&pDevice->null_device.operationCompletionEvent);
5779 ma_event_uninit(&pDevice->null_device.operationEvent);
5787 ma_assert(pDevice !=
NULL);
5789 ma_zero_object(&pDevice->null_device);
5792 if (bufferSizeInFrames == 0) {
5797 ma_strncpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name),
"NULL Capture Device", (
size_t)-1);
5801 pDevice->capture.internalBufferSizeInFrames = bufferSizeInFrames;
5802 pDevice->capture.internalPeriods = pConfig->
periods;
5805 ma_strncpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name),
"NULL Playback Device", (
size_t)-1);
5809 pDevice->playback.internalBufferSizeInFrames = bufferSizeInFrames;
5810 pDevice->playback.internalPeriods = pConfig->
periods;
5817 result = ma_event_init(pContext, &pDevice->null_device.operationEvent);
5822 result = ma_event_init(pContext, &pDevice->null_device.operationCompletionEvent);
5827 result = ma_thread_create(pContext, &pDevice->thread, ma_device_thread__null, pDevice);
5837 ma_assert(pDevice !=
NULL);
5839 ma_device_do_operation__null(pDevice, MA_DEVICE_OP_START__NULL);
5841 ma_atomic_exchange_32(&pDevice->null_device.isStarted,
MA_TRUE);
5847 ma_assert(pDevice !=
NULL);
5849 ma_device_do_operation__null(pDevice, MA_DEVICE_OP_SUSPEND__NULL);
5851 ma_atomic_exchange_32(&pDevice->null_device.isStarted,
MA_FALSE);
5861 wasStartedOnEntry = pDevice->null_device.isStarted;
5864 totalPCMFramesProcessed = 0;
5865 while (totalPCMFramesProcessed < frameCount) {
5869 if (pDevice->null_device.currentPeriodFramesRemainingPlayback > 0) {
5870 ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
5871 ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingPlayback;
5872 if (framesToProcess > framesRemaining) {
5873 framesToProcess = framesRemaining;
5879 pDevice->null_device.currentPeriodFramesRemainingPlayback -= framesToProcess;
5880 totalPCMFramesProcessed += framesToProcess;
5884 if (pDevice->null_device.currentPeriodFramesRemainingPlayback == 0) {
5885 pDevice->null_device.currentPeriodFramesRemainingPlayback = 0;
5887 if (!pDevice->null_device.isStarted && !wasStartedOnEntry) {
5888 result = ma_device_start__null(pDevice);
5896 ma_assert(totalPCMFramesProcessed <= frameCount);
5897 if (totalPCMFramesProcessed == frameCount) {
5902 targetFrame = pDevice->null_device.lastProcessedFramePlayback;
5907 if (!pDevice->null_device.isStarted) {
5911 currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
5912 if (currentFrame >= targetFrame) {
5920 pDevice->null_device.lastProcessedFramePlayback += pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
5921 pDevice->null_device.currentPeriodFramesRemainingPlayback = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
5933 if (!pDevice->null_device.isStarted) {
5934 result = ma_device_start__null(pDevice);
5941 totalPCMFramesProcessed = 0;
5942 while (totalPCMFramesProcessed < frameCount) {
5946 if (pDevice->null_device.currentPeriodFramesRemainingCapture > 0) {
5948 ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
5949 ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingCapture;
5950 if (framesToProcess > framesRemaining) {
5951 framesToProcess = framesRemaining;
5955 ma_zero_memory(ma_offset_ptr(pPCMFrames, totalPCMFramesProcessed*bpf), framesToProcess*bpf);
5957 pDevice->null_device.currentPeriodFramesRemainingCapture -= framesToProcess;
5958 totalPCMFramesProcessed += framesToProcess;
5962 if (pDevice->null_device.currentPeriodFramesRemainingCapture == 0) {
5963 pDevice->null_device.currentPeriodFramesRemainingCapture = 0;
5967 ma_assert(totalPCMFramesProcessed <= frameCount);
5968 if (totalPCMFramesProcessed == frameCount) {
5973 targetFrame = pDevice->null_device.lastProcessedFrameCapture + (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods);
5978 if (!pDevice->null_device.isStarted) {
5982 currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
5983 if (currentFrame >= targetFrame) {
5991 pDevice->null_device.lastProcessedFrameCapture += pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
5992 pDevice->null_device.currentPeriodFramesRemainingCapture = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
6000 ma_assert(pContext !=
NULL);
6009 ma_assert(pContext !=
NULL);
6013 pContext->
onUninit = ma_context_uninit__null;
6015 pContext->
onEnumDevices = ma_context_enumerate_devices__null;
6035 #if defined(MA_WIN32)
6036 #if defined(MA_WIN32_DESKTOP)
6037 #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit)
6038 #define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
6039 #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) ((MA_PFN_CoCreateInstance)pContext->win32.CoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv)
6040 #define ma_CoTaskMemFree(pContext, pv) ((MA_PFN_CoTaskMemFree)pContext->win32.CoTaskMemFree)(pv)
6041 #define ma_PropVariantClear(pContext, pvar) ((MA_PFN_PropVariantClear)pContext->win32.PropVariantClear)(pvar)
6043 #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) CoInitializeEx(pvReserved, dwCoInit)
6044 #define ma_CoUninitialize(pContext) CoUninitialize()
6045 #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv)
6046 #define ma_CoTaskMemFree(pContext, pv) CoTaskMemFree(pv)
6047 #define ma_PropVariantClear(pContext, pvar) PropVariantClear(pvar)
6050 #if !defined(MAXULONG_PTR)
6051 typedef size_t DWORD_PTR;
6054 #if !defined(WAVE_FORMAT_44M08)
6055 #define WAVE_FORMAT_44M08 0x00000100
6056 #define WAVE_FORMAT_44S08 0x00000200
6057 #define WAVE_FORMAT_44M16 0x00000400
6058 #define WAVE_FORMAT_44S16 0x00000800
6059 #define WAVE_FORMAT_48M08 0x00001000
6060 #define WAVE_FORMAT_48S08 0x00002000
6061 #define WAVE_FORMAT_48M16 0x00004000
6062 #define WAVE_FORMAT_48S16 0x00008000
6063 #define WAVE_FORMAT_96M08 0x00010000
6064 #define WAVE_FORMAT_96S08 0x00020000
6065 #define WAVE_FORMAT_96M16 0x00040000
6066 #define WAVE_FORMAT_96S16 0x00080000
6069 #ifndef SPEAKER_FRONT_LEFT
6070 #define SPEAKER_FRONT_LEFT 0x1
6071 #define SPEAKER_FRONT_RIGHT 0x2
6072 #define SPEAKER_FRONT_CENTER 0x4
6073 #define SPEAKER_LOW_FREQUENCY 0x8
6074 #define SPEAKER_BACK_LEFT 0x10
6075 #define SPEAKER_BACK_RIGHT 0x20
6076 #define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
6077 #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
6078 #define SPEAKER_BACK_CENTER 0x100
6079 #define SPEAKER_SIDE_LEFT 0x200
6080 #define SPEAKER_SIDE_RIGHT 0x400
6081 #define SPEAKER_TOP_CENTER 0x800
6082 #define SPEAKER_TOP_FRONT_LEFT 0x1000
6083 #define SPEAKER_TOP_FRONT_CENTER 0x2000
6084 #define SPEAKER_TOP_FRONT_RIGHT 0x4000
6085 #define SPEAKER_TOP_BACK_LEFT 0x8000
6086 #define SPEAKER_TOP_BACK_CENTER 0x10000
6087 #define SPEAKER_TOP_BACK_RIGHT 0x20000
6094 #if (defined(_MSC_VER) && !defined(_WAVEFORMATEXTENSIBLE_)) || defined(__DMC__)
6097 WAVEFORMATEX Format;
6100 WORD wValidBitsPerSample;
6101 WORD wSamplesPerBlock;
6104 DWORD dwChannelMask;
6106 } WAVEFORMATEXTENSIBLE;
6109 #ifndef WAVE_FORMAT_EXTENSIBLE
6110 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
6113 #ifndef WAVE_FORMAT_IEEE_FLOAT
6114 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
6117 GUID MA_GUID_NULL = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
6177 DWORD dwChannelMask = 0;
6180 for (iChannel = 0; iChannel <
channels; ++iChannel) {
6181 dwChannelMask |= ma_channel_id_to_win32(channelMap[iChannel]);
6184 return dwChannelMask;
6190 if (
channels == 1 && dwChannelMask == 0) {
6192 }
else if (
channels == 2 && dwChannelMask == 0) {
6196 if (
channels == 1 && (dwChannelMask & SPEAKER_FRONT_CENTER) != 0) {
6203 for (iBit = 0; iBit < 32; ++iBit) {
6204 DWORD bitValue = (dwChannelMask & (1UL << iBit));
6205 if (bitValue != 0) {
6207 channelMap[iChannel] = ma_channel_id_to_ma__win32(bitValue);
6216 ma_bool32 ma_is_guid_equal(
const void* a,
const void* b)
6218 return IsEqualGUID(*(
const GUID*)a, *(
const GUID*)b);
6221 #define ma_is_guid_equal(a, b) IsEqualGUID((const GUID*)a, (const GUID*)b)
6224 ma_format ma_format_from_WAVEFORMATEX(
const WAVEFORMATEX* pWF)
6226 ma_assert(pWF !=
NULL);
6228 if (pWF->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
6229 const WAVEFORMATEXTENSIBLE* pWFEX = (
const WAVEFORMATEXTENSIBLE*)pWF;
6230 if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_PCM)) {
6231 if (pWFEX->Samples.wValidBitsPerSample == 32) {
6234 if (pWFEX->Samples.wValidBitsPerSample == 24) {
6235 if (pWFEX->Format.wBitsPerSample == 32) {
6238 if (pWFEX->Format.wBitsPerSample == 24) {
6242 if (pWFEX->Samples.wValidBitsPerSample == 16) {
6245 if (pWFEX->Samples.wValidBitsPerSample == 8) {
6249 if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
6250 if (pWFEX->Samples.wValidBitsPerSample == 32) {
6260 if (pWF->wFormatTag == WAVE_FORMAT_PCM) {
6261 if (pWF->wBitsPerSample == 32) {
6264 if (pWF->wBitsPerSample == 24) {
6267 if (pWF->wBitsPerSample == 16) {
6270 if (pWF->wBitsPerSample == 8) {
6274 if (pWF->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
6275 if (pWF->wBitsPerSample == 32) {
6278 if (pWF->wBitsPerSample == 64) {
6294 #ifdef MA_HAS_WASAPI
6296 #if defined(_MSC_VER)
6297 #pragma warning(push)
6298 #pragma warning(disable:4091)
6300 #include <audioclient.h>
6301 #include <mmdeviceapi.h>
6302 #if defined(_MSC_VER)
6303 #pragma warning(pop)
6309 #define MA_WIN32_WINNT_VISTA 0x0600
6310 #define MA_VER_MINORVERSION 0x01
6311 #define MA_VER_MAJORVERSION 0x02
6312 #define MA_VER_SERVICEPACKMAJOR 0x20
6313 #define MA_VER_GREATER_EQUAL 0x03
6316 DWORD dwOSVersionInfoSize;
6317 DWORD dwMajorVersion;
6318 DWORD dwMinorVersion;
6319 DWORD dwBuildNumber;
6321 WCHAR szCSDVersion[128];
6322 WORD wServicePackMajor;
6323 WORD wServicePackMinor;
6327 } ma_OSVERSIONINFOEXW;
6329 typedef BOOL (WINAPI * ma_PFNVerifyVersionInfoW) (ma_OSVERSIONINFOEXW* lpVersionInfo,
DWORD dwTypeMask, DWORDLONG dwlConditionMask);
6330 typedef ULONGLONG (WINAPI * ma_PFNVerSetConditionMask)(ULONGLONG dwlConditionMask,
DWORD dwTypeBitMask, BYTE dwConditionMask);
6333 #ifndef PROPERTYKEY_DEFINED
6334 #define PROPERTYKEY_DEFINED
6343 static MA_INLINE void ma_PropVariantInit(PROPVARIANT* pProp)
6345 ma_zero_object(pProp);
6349 const PROPERTYKEY MA_PKEY_Device_FriendlyName = {{0xA45C254E, 0xDF1C, 0x4EFD, {0x80, 0x20, 0x67, 0xD1, 0x46, 0xA8, 0x50, 0xE0}}, 14};
6350 const PROPERTYKEY MA_PKEY_AudioEngine_DeviceFormat = {{0xF19F064D, 0x82C, 0x4E27, {0xBC, 0x73, 0x68, 0x82, 0xA1, 0xBB, 0x8E, 0x4C}}, 0};
6352 const IID MA_IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
6353 const IID MA_IID_IAgileObject = {0x94EA2B94, 0xE9CC, 0x49E0, {0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90}};
6355 const IID MA_IID_IAudioClient = {0x1CB9AD4C, 0xDBFA, 0x4C32, {0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2}};
6356 const IID MA_IID_IAudioClient2 = {0x726778CD, 0xF60A, 0x4EDA, {0x82, 0xDE, 0xE4, 0x76, 0x10, 0xCD, 0x78, 0xAA}};
6357 const IID MA_IID_IAudioClient3 = {0x7ED4EE07, 0x8E67, 0x4CD4, {0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42}};
6358 const IID MA_IID_IAudioRenderClient = {0xF294ACFC, 0x3146, 0x4483, {0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}};
6359 const IID MA_IID_IAudioCaptureClient = {0xC8ADBD64, 0xE71E, 0x48A0, {0xA4, 0xDE, 0x18, 0x5C, 0x39, 0x5C, 0xD3, 0x17}};
6360 const IID MA_IID_IMMNotificationClient = {0x7991EEC9, 0x7E89, 0x4D85, {0x83, 0x90, 0x6C, 0x70, 0x3C, 0xEC, 0x60, 0xC0}};
6361 #ifndef MA_WIN32_DESKTOP
6362 const IID MA_IID_DEVINTERFACE_AUDIO_RENDER = {0xE6327CAD, 0xDCEC, 0x4949, {0xAE, 0x8A, 0x99, 0x1E, 0x97, 0x6A, 0x79, 0xD2}};
6363 const IID MA_IID_DEVINTERFACE_AUDIO_CAPTURE = {0x2EEF81BE, 0x33FA, 0x4800, {0x96, 0x70, 0x1C, 0xD4, 0x74, 0x97, 0x2C, 0x3F}};
6364 const IID MA_IID_IActivateAudioInterfaceCompletionHandler = {0x41D949AB, 0x9862, 0x444A, {0x80, 0xF6, 0xC2, 0x61, 0x33, 0x4D, 0xA5, 0xEB}};
6367 const IID MA_CLSID_MMDeviceEnumerator_Instance = {0xBCDE0395, 0xE52F, 0x467C, {0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E}};
6368 const IID MA_IID_IMMDeviceEnumerator_Instance = {0xA95664D2, 0x9614, 0x4F35, {0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6}};
6370 #define MA_CLSID_MMDeviceEnumerator MA_CLSID_MMDeviceEnumerator_Instance
6371 #define MA_IID_IMMDeviceEnumerator MA_IID_IMMDeviceEnumerator_Instance
6373 #define MA_CLSID_MMDeviceEnumerator &MA_CLSID_MMDeviceEnumerator_Instance
6374 #define MA_IID_IMMDeviceEnumerator &MA_IID_IMMDeviceEnumerator_Instance
6377 typedef struct ma_IUnknown ma_IUnknown;
6378 #ifdef MA_WIN32_DESKTOP
6379 #define MA_MM_DEVICE_STATE_ACTIVE 1
6380 #define MA_MM_DEVICE_STATE_DISABLED 2
6381 #define MA_MM_DEVICE_STATE_NOTPRESENT 4
6382 #define MA_MM_DEVICE_STATE_UNPLUGGED 8
6384 typedef struct ma_IMMDeviceEnumerator ma_IMMDeviceEnumerator;
6385 typedef struct ma_IMMDeviceCollection ma_IMMDeviceCollection;
6386 typedef struct ma_IMMDevice ma_IMMDevice;
6388 typedef struct ma_IActivateAudioInterfaceCompletionHandler ma_IActivateAudioInterfaceCompletionHandler;
6389 typedef struct ma_IActivateAudioInterfaceAsyncOperation ma_IActivateAudioInterfaceAsyncOperation;
6391 typedef struct ma_IPropertyStore ma_IPropertyStore;
6392 typedef struct ma_IAudioClient ma_IAudioClient;
6393 typedef struct ma_IAudioClient2 ma_IAudioClient2;
6394 typedef struct ma_IAudioClient3 ma_IAudioClient3;
6395 typedef struct ma_IAudioRenderClient ma_IAudioRenderClient;
6396 typedef struct ma_IAudioCaptureClient ma_IAudioCaptureClient;
6398 typedef ma_int64 MA_REFERENCE_TIME;
6400 #define MA_AUDCLNT_STREAMFLAGS_CROSSPROCESS 0x00010000
6401 #define MA_AUDCLNT_STREAMFLAGS_LOOPBACK 0x00020000
6402 #define MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK 0x00040000
6403 #define MA_AUDCLNT_STREAMFLAGS_NOPERSIST 0x00080000
6404 #define MA_AUDCLNT_STREAMFLAGS_RATEADJUST 0x00100000
6405 #define MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY 0x08000000
6406 #define MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
6407 #define MA_AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED 0x10000000
6408 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE 0x20000000
6409 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED 0x40000000
6412 #define MA_AUDCLNT_E_INVALID_DEVICE_PERIOD (-2004287456)
6413 #define MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED (-2004287463)
6414 #define MA_AUDCLNT_S_BUFFER_EMPTY (143196161)
6415 #define MA_AUDCLNT_E_DEVICE_IN_USE (-2004287478)
6428 ma_eCommunications = 2
6433 MA_AUDCLNT_SHAREMODE_SHARED,
6434 MA_AUDCLNT_SHAREMODE_EXCLUSIVE
6435 } MA_AUDCLNT_SHAREMODE;
6439 MA_AudioCategory_Other = 0
6440 } MA_AUDIO_STREAM_CATEGORY;
6446 MA_AUDIO_STREAM_CATEGORY eCategory;
6447 } ma_AudioClientProperties;
6453 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IUnknown* pThis,
const IID*
const riid,
void** ppObject);
6454 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IUnknown* pThis);
6455 ULONG (STDMETHODCALLTYPE * Release) (ma_IUnknown* pThis);
6459 ma_IUnknownVtbl* lpVtbl;
6461 HRESULT ma_IUnknown_QueryInterface(ma_IUnknown* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6462 ULONG ma_IUnknown_AddRef(ma_IUnknown* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6463 ULONG ma_IUnknown_Release(ma_IUnknown* pThis) {
return pThis->lpVtbl->Release(pThis); }
6465 #ifdef MA_WIN32_DESKTOP
6478 HRESULT (STDMETHODCALLTYPE * OnDefaultDeviceChanged)(
ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID);
6480 } ma_IMMNotificationClientVtbl;
6486 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceEnumerator* pThis,
const IID*
const riid,
void** ppObject);
6487 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceEnumerator* pThis);
6488 ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceEnumerator* pThis);
6491 HRESULT (STDMETHODCALLTYPE * EnumAudioEndpoints) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow,
DWORD dwStateMask, ma_IMMDeviceCollection** ppDevices);
6492 HRESULT (STDMETHODCALLTYPE * GetDefaultAudioEndpoint) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, ma_ERole role, ma_IMMDevice** ppEndpoint);
6493 HRESULT (STDMETHODCALLTYPE * GetDevice) (ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice);
6496 } ma_IMMDeviceEnumeratorVtbl;
6497 struct ma_IMMDeviceEnumerator
6499 ma_IMMDeviceEnumeratorVtbl* lpVtbl;
6501 HRESULT ma_IMMDeviceEnumerator_QueryInterface(ma_IMMDeviceEnumerator* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6502 ULONG ma_IMMDeviceEnumerator_AddRef(ma_IMMDeviceEnumerator* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6503 ULONG ma_IMMDeviceEnumerator_Release(ma_IMMDeviceEnumerator* pThis) {
return pThis->lpVtbl->Release(pThis); }
6504 HRESULT ma_IMMDeviceEnumerator_EnumAudioEndpoints(ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow,
DWORD dwStateMask, ma_IMMDeviceCollection** ppDevices) {
return pThis->lpVtbl->EnumAudioEndpoints(pThis, dataFlow, dwStateMask, ppDevices); }
6505 HRESULT ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, ma_ERole role, ma_IMMDevice** ppEndpoint) {
return pThis->lpVtbl->GetDefaultAudioEndpoint(pThis, dataFlow, role, ppEndpoint); }
6506 HRESULT ma_IMMDeviceEnumerator_GetDevice(ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice) {
return pThis->lpVtbl->GetDevice(pThis, pID, ppDevice); }
6507 HRESULT ma_IMMDeviceEnumerator_RegisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis,
ma_IMMNotificationClient* pClient) {
return pThis->lpVtbl->RegisterEndpointNotificationCallback(pThis, pClient); }
6508 HRESULT ma_IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis,
ma_IMMNotificationClient* pClient) {
return pThis->lpVtbl->UnregisterEndpointNotificationCallback(pThis, pClient); }
6515 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceCollection* pThis,
const IID*
const riid,
void** ppObject);
6516 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceCollection* pThis);
6517 ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceCollection* pThis);
6520 HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IMMDeviceCollection* pThis,
UINT* pDevices);
6521 HRESULT (STDMETHODCALLTYPE * Item) (ma_IMMDeviceCollection* pThis,
UINT nDevice, ma_IMMDevice** ppDevice);
6522 } ma_IMMDeviceCollectionVtbl;
6523 struct ma_IMMDeviceCollection
6525 ma_IMMDeviceCollectionVtbl* lpVtbl;
6527 HRESULT ma_IMMDeviceCollection_QueryInterface(ma_IMMDeviceCollection* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6528 ULONG ma_IMMDeviceCollection_AddRef(ma_IMMDeviceCollection* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6529 ULONG ma_IMMDeviceCollection_Release(ma_IMMDeviceCollection* pThis) {
return pThis->lpVtbl->Release(pThis); }
6530 HRESULT ma_IMMDeviceCollection_GetCount(ma_IMMDeviceCollection* pThis,
UINT* pDevices) {
return pThis->lpVtbl->GetCount(pThis, pDevices); }
6531 HRESULT ma_IMMDeviceCollection_Item(ma_IMMDeviceCollection* pThis,
UINT nDevice, ma_IMMDevice** ppDevice) {
return pThis->lpVtbl->Item(pThis, nDevice, ppDevice); }
6538 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDevice* pThis,
const IID*
const riid,
void** ppObject);
6539 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDevice* pThis);
6540 ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDevice* pThis);
6543 HRESULT (STDMETHODCALLTYPE * Activate) (ma_IMMDevice* pThis,
const IID*
const iid,
DWORD dwClsCtx, PROPVARIANT* pActivationParams,
void** ppInterface);
6544 HRESULT (STDMETHODCALLTYPE * OpenPropertyStore)(ma_IMMDevice* pThis,
DWORD stgmAccess, ma_IPropertyStore** ppProperties);
6545 HRESULT (STDMETHODCALLTYPE * GetId) (ma_IMMDevice* pThis, LPWSTR *pID);
6546 HRESULT (STDMETHODCALLTYPE * GetState) (ma_IMMDevice* pThis,
DWORD *pState);
6550 ma_IMMDeviceVtbl* lpVtbl;
6552 HRESULT ma_IMMDevice_QueryInterface(ma_IMMDevice* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6553 ULONG ma_IMMDevice_AddRef(ma_IMMDevice* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6554 ULONG ma_IMMDevice_Release(ma_IMMDevice* pThis) {
return pThis->lpVtbl->Release(pThis); }
6555 HRESULT ma_IMMDevice_Activate(ma_IMMDevice* pThis,
const IID*
const iid,
DWORD dwClsCtx, PROPVARIANT* pActivationParams,
void** ppInterface) {
return pThis->lpVtbl->Activate(pThis, iid, dwClsCtx, pActivationParams, ppInterface); }
6556 HRESULT ma_IMMDevice_OpenPropertyStore(ma_IMMDevice* pThis,
DWORD stgmAccess, ma_IPropertyStore** ppProperties) {
return pThis->lpVtbl->OpenPropertyStore(pThis, stgmAccess, ppProperties); }
6557 HRESULT ma_IMMDevice_GetId(ma_IMMDevice* pThis, LPWSTR *pID) {
return pThis->lpVtbl->GetId(pThis, pID); }
6558 HRESULT ma_IMMDevice_GetState(ma_IMMDevice* pThis,
DWORD *pState) {
return pThis->lpVtbl->GetState(pThis, pState); }
6564 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IActivateAudioInterfaceAsyncOperation* pThis,
const IID*
const riid,
void** ppObject);
6565 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
6566 ULONG (STDMETHODCALLTYPE * Release) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
6569 HRESULT (STDMETHODCALLTYPE * GetActivateResult)(ma_IActivateAudioInterfaceAsyncOperation* pThis,
HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface);
6570 } ma_IActivateAudioInterfaceAsyncOperationVtbl;
6571 struct ma_IActivateAudioInterfaceAsyncOperation
6573 ma_IActivateAudioInterfaceAsyncOperationVtbl* lpVtbl;
6575 HRESULT ma_IActivateAudioInterfaceAsyncOperation_QueryInterface(ma_IActivateAudioInterfaceAsyncOperation* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6576 ULONG ma_IActivateAudioInterfaceAsyncOperation_AddRef(ma_IActivateAudioInterfaceAsyncOperation* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6577 ULONG ma_IActivateAudioInterfaceAsyncOperation_Release(ma_IActivateAudioInterfaceAsyncOperation* pThis) {
return pThis->lpVtbl->Release(pThis); }
6578 HRESULT ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(ma_IActivateAudioInterfaceAsyncOperation* pThis,
HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface) {
return pThis->lpVtbl->GetActivateResult(pThis, pActivateResult, ppActivatedInterface); }
6585 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IPropertyStore* pThis,
const IID*
const riid,
void** ppObject);
6586 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IPropertyStore* pThis);
6587 ULONG (STDMETHODCALLTYPE * Release) (ma_IPropertyStore* pThis);
6590 HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IPropertyStore* pThis,
DWORD* pPropCount);
6591 HRESULT (STDMETHODCALLTYPE * GetAt) (ma_IPropertyStore* pThis,
DWORD propIndex, PROPERTYKEY* pPropKey);
6592 HRESULT (STDMETHODCALLTYPE * GetValue)(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey, PROPVARIANT* pPropVar);
6593 HRESULT (STDMETHODCALLTYPE * SetValue)(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey,
const PROPVARIANT*
const pPropVar);
6594 HRESULT (STDMETHODCALLTYPE * Commit) (ma_IPropertyStore* pThis);
6595 } ma_IPropertyStoreVtbl;
6596 struct ma_IPropertyStore
6598 ma_IPropertyStoreVtbl* lpVtbl;
6600 HRESULT ma_IPropertyStore_QueryInterface(ma_IPropertyStore* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6601 ULONG ma_IPropertyStore_AddRef(ma_IPropertyStore* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6602 ULONG ma_IPropertyStore_Release(ma_IPropertyStore* pThis) {
return pThis->lpVtbl->Release(pThis); }
6603 HRESULT ma_IPropertyStore_GetCount(ma_IPropertyStore* pThis,
DWORD* pPropCount) {
return pThis->lpVtbl->GetCount(pThis, pPropCount); }
6604 HRESULT ma_IPropertyStore_GetAt(ma_IPropertyStore* pThis,
DWORD propIndex, PROPERTYKEY* pPropKey) {
return pThis->lpVtbl->GetAt(pThis, propIndex, pPropKey); }
6605 HRESULT ma_IPropertyStore_GetValue(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey, PROPVARIANT* pPropVar) {
return pThis->lpVtbl->GetValue(pThis, pKey, pPropVar); }
6606 HRESULT ma_IPropertyStore_SetValue(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey,
const PROPVARIANT*
const pPropVar) {
return pThis->lpVtbl->SetValue(pThis, pKey, pPropVar); }
6607 HRESULT ma_IPropertyStore_Commit(ma_IPropertyStore* pThis) {
return pThis->lpVtbl->Commit(pThis); }
6614 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient* pThis,
const IID*
const riid,
void** ppObject);
6615 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient* pThis);
6616 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient* pThis);
6619 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode,
DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
6620 HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient* pThis,
ma_uint32* pNumBufferFrames);
6621 HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency);
6622 HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient* pThis,
ma_uint32* pNumPaddingFrames);
6623 HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
6624 HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat);
6625 HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
6626 HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient* pThis);
6627 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient* pThis);
6628 HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient* pThis);
6629 HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient* pThis, HANDLE eventHandle);
6630 HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient* pThis,
const IID*
const riid,
void** pp);
6631 } ma_IAudioClientVtbl;
6632 struct ma_IAudioClient
6634 ma_IAudioClientVtbl* lpVtbl;
6636 HRESULT ma_IAudioClient_QueryInterface(ma_IAudioClient* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6637 ULONG ma_IAudioClient_AddRef(ma_IAudioClient* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6638 ULONG ma_IAudioClient_Release(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Release(pThis); }
6639 HRESULT ma_IAudioClient_Initialize(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode,
DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid) {
return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
6640 HRESULT ma_IAudioClient_GetBufferSize(ma_IAudioClient* pThis,
ma_uint32* pNumBufferFrames) {
return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
6641 HRESULT ma_IAudioClient_GetStreamLatency(ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency) {
return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
6642 HRESULT ma_IAudioClient_GetCurrentPadding(ma_IAudioClient* pThis,
ma_uint32* pNumPaddingFrames) {
return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
6643 HRESULT ma_IAudioClient_IsFormatSupported(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) {
return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
6644 HRESULT ma_IAudioClient_GetMixFormat(ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat) {
return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
6645 HRESULT ma_IAudioClient_GetDevicePeriod(ma_IAudioClient* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) {
return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
6646 HRESULT ma_IAudioClient_Start(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Start(pThis); }
6647 HRESULT ma_IAudioClient_Stop(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Stop(pThis); }
6648 HRESULT ma_IAudioClient_Reset(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Reset(pThis); }
6649 HRESULT ma_IAudioClient_SetEventHandle(ma_IAudioClient* pThis, HANDLE eventHandle) {
return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
6650 HRESULT ma_IAudioClient_GetService(ma_IAudioClient* pThis,
const IID*
const riid,
void** pp) {
return pThis->lpVtbl->GetService(pThis, riid, pp); }
6656 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient2* pThis,
const IID*
const riid,
void** ppObject);
6657 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient2* pThis);
6658 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient2* pThis);
6661 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode,
DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
6662 HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient2* pThis,
ma_uint32* pNumBufferFrames);
6663 HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency);
6664 HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient2* pThis,
ma_uint32* pNumPaddingFrames);
6665 HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
6666 HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat);
6667 HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
6668 HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient2* pThis);
6669 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient2* pThis);
6670 HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient2* pThis);
6671 HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient2* pThis, HANDLE eventHandle);
6672 HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient2* pThis,
const IID*
const riid,
void** pp);
6675 HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category,
BOOL* pOffloadCapable);
6676 HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient2* pThis,
const ma_AudioClientProperties* pProperties);
6677 HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient2* pThis,
const WAVEFORMATEX* pFormat,
BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
6678 } ma_IAudioClient2Vtbl;
6679 struct ma_IAudioClient2
6681 ma_IAudioClient2Vtbl* lpVtbl;
6683 HRESULT ma_IAudioClient2_QueryInterface(ma_IAudioClient2* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6684 ULONG ma_IAudioClient2_AddRef(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6685 ULONG ma_IAudioClient2_Release(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Release(pThis); }
6686 HRESULT ma_IAudioClient2_Initialize(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode,
DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid) {
return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
6687 HRESULT ma_IAudioClient2_GetBufferSize(ma_IAudioClient2* pThis,
ma_uint32* pNumBufferFrames) {
return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
6688 HRESULT ma_IAudioClient2_GetStreamLatency(ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency) {
return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
6689 HRESULT ma_IAudioClient2_GetCurrentPadding(ma_IAudioClient2* pThis,
ma_uint32* pNumPaddingFrames) {
return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
6690 HRESULT ma_IAudioClient2_IsFormatSupported(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) {
return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
6691 HRESULT ma_IAudioClient2_GetMixFormat(ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat) {
return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
6692 HRESULT ma_IAudioClient2_GetDevicePeriod(ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) {
return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
6693 HRESULT ma_IAudioClient2_Start(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Start(pThis); }
6694 HRESULT ma_IAudioClient2_Stop(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Stop(pThis); }
6695 HRESULT ma_IAudioClient2_Reset(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Reset(pThis); }
6696 HRESULT ma_IAudioClient2_SetEventHandle(ma_IAudioClient2* pThis, HANDLE eventHandle) {
return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
6697 HRESULT ma_IAudioClient2_GetService(ma_IAudioClient2* pThis,
const IID*
const riid,
void** pp) {
return pThis->lpVtbl->GetService(pThis, riid, pp); }
6698 HRESULT ma_IAudioClient2_IsOffloadCapable(ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category,
BOOL* pOffloadCapable) {
return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
6699 HRESULT ma_IAudioClient2_SetClientProperties(ma_IAudioClient2* pThis,
const ma_AudioClientProperties* pProperties) {
return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
6700 HRESULT ma_IAudioClient2_GetBufferSizeLimits(ma_IAudioClient2* pThis,
const WAVEFORMATEX* pFormat,
BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration) {
return pThis->lpVtbl->GetBufferSizeLimits(pThis, pFormat, eventDriven, pMinBufferDuration, pMaxBufferDuration); }
6707 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient3* pThis,
const IID*
const riid,
void** ppObject);
6708 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient3* pThis);
6709 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient3* pThis);
6712 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode,
DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
6713 HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient3* pThis,
ma_uint32* pNumBufferFrames);
6714 HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency);
6715 HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient3* pThis,
ma_uint32* pNumPaddingFrames);
6716 HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
6717 HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat);
6718 HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
6719 HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient3* pThis);
6720 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient3* pThis);
6721 HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient3* pThis);
6722 HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient3* pThis, HANDLE eventHandle);
6723 HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient3* pThis,
const IID*
const riid,
void** pp);
6726 HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category,
BOOL* pOffloadCapable);
6727 HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient3* pThis,
const ma_AudioClientProperties* pProperties);
6728 HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat,
BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
6731 HRESULT (STDMETHODCALLTYPE * GetSharedModeEnginePeriod) (ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat, UINT32* pDefaultPeriodInFrames, UINT32* pFundamentalPeriodInFrames, UINT32* pMinPeriodInFrames, UINT32* pMaxPeriodInFrames);
6732 HRESULT (STDMETHODCALLTYPE * GetCurrentSharedModeEnginePeriod)(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, UINT32* pCurrentPeriodInFrames);
6733 HRESULT (STDMETHODCALLTYPE * InitializeSharedAudioStream) (ma_IAudioClient3* pThis,
DWORD streamFlags, UINT32 periodInFrames,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
6734 } ma_IAudioClient3Vtbl;
6735 struct ma_IAudioClient3
6737 ma_IAudioClient3Vtbl* lpVtbl;
6739 HRESULT ma_IAudioClient3_QueryInterface(ma_IAudioClient3* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6740 ULONG ma_IAudioClient3_AddRef(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6741 ULONG ma_IAudioClient3_Release(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Release(pThis); }
6742 HRESULT ma_IAudioClient3_Initialize(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode,
DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid) {
return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
6743 HRESULT ma_IAudioClient3_GetBufferSize(ma_IAudioClient3* pThis,
ma_uint32* pNumBufferFrames) {
return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
6744 HRESULT ma_IAudioClient3_GetStreamLatency(ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency) {
return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
6745 HRESULT ma_IAudioClient3_GetCurrentPadding(ma_IAudioClient3* pThis,
ma_uint32* pNumPaddingFrames) {
return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
6746 HRESULT ma_IAudioClient3_IsFormatSupported(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) {
return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
6747 HRESULT ma_IAudioClient3_GetMixFormat(ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat) {
return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
6748 HRESULT ma_IAudioClient3_GetDevicePeriod(ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) {
return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
6749 HRESULT ma_IAudioClient3_Start(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Start(pThis); }
6750 HRESULT ma_IAudioClient3_Stop(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Stop(pThis); }
6751 HRESULT ma_IAudioClient3_Reset(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Reset(pThis); }
6752 HRESULT ma_IAudioClient3_SetEventHandle(ma_IAudioClient3* pThis, HANDLE eventHandle) {
return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
6753 HRESULT ma_IAudioClient3_GetService(ma_IAudioClient3* pThis,
const IID*
const riid,
void** pp) {
return pThis->lpVtbl->GetService(pThis, riid, pp); }
6754 HRESULT ma_IAudioClient3_IsOffloadCapable(ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category,
BOOL* pOffloadCapable) {
return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
6755 HRESULT ma_IAudioClient3_SetClientProperties(ma_IAudioClient3* pThis,
const ma_AudioClientProperties* pProperties) {
return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
6756 HRESULT ma_IAudioClient3_GetBufferSizeLimits(ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat,
BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration) {
return pThis->lpVtbl->GetBufferSizeLimits(pThis, pFormat, eventDriven, pMinBufferDuration, pMaxBufferDuration); }
6757 HRESULT ma_IAudioClient3_GetSharedModeEnginePeriod(ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat, UINT32* pDefaultPeriodInFrames, UINT32* pFundamentalPeriodInFrames, UINT32* pMinPeriodInFrames, UINT32* pMaxPeriodInFrames) {
return pThis->lpVtbl->GetSharedModeEnginePeriod(pThis, pFormat, pDefaultPeriodInFrames, pFundamentalPeriodInFrames, pMinPeriodInFrames, pMaxPeriodInFrames); }
6758 HRESULT ma_IAudioClient3_GetCurrentSharedModeEnginePeriod(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, UINT32* pCurrentPeriodInFrames) {
return pThis->lpVtbl->GetCurrentSharedModeEnginePeriod(pThis, ppFormat, pCurrentPeriodInFrames); }
6759 HRESULT ma_IAudioClient3_InitializeSharedAudioStream(ma_IAudioClient3* pThis,
DWORD streamFlags, UINT32 periodInFrames,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGUID) {
return pThis->lpVtbl->InitializeSharedAudioStream(pThis, streamFlags, periodInFrames, pFormat, pAudioSessionGUID); }
6766 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioRenderClient* pThis,
const IID*
const riid,
void** ppObject);
6767 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioRenderClient* pThis);
6768 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioRenderClient* pThis);
6771 HRESULT (STDMETHODCALLTYPE * GetBuffer) (ma_IAudioRenderClient* pThis,
ma_uint32 numFramesRequested, BYTE** ppData);
6772 HRESULT (STDMETHODCALLTYPE * ReleaseBuffer)(ma_IAudioRenderClient* pThis,
ma_uint32 numFramesWritten,
DWORD dwFlags);
6773 } ma_IAudioRenderClientVtbl;
6774 struct ma_IAudioRenderClient
6776 ma_IAudioRenderClientVtbl* lpVtbl;
6778 HRESULT ma_IAudioRenderClient_QueryInterface(ma_IAudioRenderClient* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6779 ULONG ma_IAudioRenderClient_AddRef(ma_IAudioRenderClient* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6780 ULONG ma_IAudioRenderClient_Release(ma_IAudioRenderClient* pThis) {
return pThis->lpVtbl->Release(pThis); }
6781 HRESULT ma_IAudioRenderClient_GetBuffer(ma_IAudioRenderClient* pThis,
ma_uint32 numFramesRequested, BYTE** ppData) {
return pThis->lpVtbl->GetBuffer(pThis, numFramesRequested, ppData); }
6782 HRESULT ma_IAudioRenderClient_ReleaseBuffer(ma_IAudioRenderClient* pThis,
ma_uint32 numFramesWritten,
DWORD dwFlags) {
return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesWritten, dwFlags); }
6789 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioCaptureClient* pThis,
const IID*
const riid,
void** ppObject);
6790 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioCaptureClient* pThis);
6791 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioCaptureClient* pThis);
6795 HRESULT (STDMETHODCALLTYPE * ReleaseBuffer) (ma_IAudioCaptureClient* pThis,
ma_uint32 numFramesRead);
6796 HRESULT (STDMETHODCALLTYPE * GetNextPacketSize)(ma_IAudioCaptureClient* pThis,
ma_uint32* pNumFramesInNextPacket);
6797 } ma_IAudioCaptureClientVtbl;
6798 struct ma_IAudioCaptureClient
6800 ma_IAudioCaptureClientVtbl* lpVtbl;
6802 HRESULT ma_IAudioCaptureClient_QueryInterface(ma_IAudioCaptureClient* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
6803 ULONG ma_IAudioCaptureClient_AddRef(ma_IAudioCaptureClient* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
6804 ULONG ma_IAudioCaptureClient_Release(ma_IAudioCaptureClient* pThis) {
return pThis->lpVtbl->Release(pThis); }
6805 HRESULT ma_IAudioCaptureClient_GetBuffer(ma_IAudioCaptureClient* pThis, BYTE** ppData,
ma_uint32* pNumFramesToRead,
DWORD* pFlags,
ma_uint64* pDevicePosition,
ma_uint64* pQPCPosition) {
return pThis->lpVtbl->GetBuffer(pThis, ppData, pNumFramesToRead, pFlags, pDevicePosition, pQPCPosition); }
6806 HRESULT ma_IAudioCaptureClient_ReleaseBuffer(ma_IAudioCaptureClient* pThis,
ma_uint32 numFramesRead) {
return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesRead); }
6807 HRESULT ma_IAudioCaptureClient_GetNextPacketSize(ma_IAudioCaptureClient* pThis,
ma_uint32* pNumFramesInNextPacket) {
return pThis->lpVtbl->GetNextPacketSize(pThis, pNumFramesInNextPacket); }
6809 #ifndef MA_WIN32_DESKTOP
6810 #include <mmdeviceapi.h>
6811 typedef struct ma_completion_handler_uwp ma_completion_handler_uwp;
6816 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_completion_handler_uwp* pThis,
const IID*
const riid,
void** ppObject);
6817 ULONG (STDMETHODCALLTYPE * AddRef) (ma_completion_handler_uwp* pThis);
6818 ULONG (STDMETHODCALLTYPE * Release) (ma_completion_handler_uwp* pThis);
6821 HRESULT (STDMETHODCALLTYPE * ActivateCompleted)(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation);
6822 } ma_completion_handler_uwp_vtbl;
6823 struct ma_completion_handler_uwp
6825 ma_completion_handler_uwp_vtbl* lpVtbl;
6830 HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_QueryInterface(ma_completion_handler_uwp* pThis,
const IID*
const riid,
void** ppObject)
6836 if (!ma_is_guid_equal(riid, &MA_IID_IUnknown) && !ma_is_guid_equal(riid, &MA_IID_IActivateAudioInterfaceCompletionHandler) && !ma_is_guid_equal(riid, &MA_IID_IAgileObject)) {
6838 return E_NOINTERFACE;
6842 *ppObject = (
void*)pThis;
6843 ((ma_completion_handler_uwp_vtbl*)pThis->lpVtbl)->AddRef(pThis);
6847 ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_AddRef(ma_completion_handler_uwp* pThis)
6849 return (ULONG)ma_atomic_increment_32(&pThis->counter);
6852 ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_Release(ma_completion_handler_uwp* pThis)
6854 ma_uint32 newRefCount = ma_atomic_decrement_32(&pThis->counter);
6855 if (newRefCount == 0) {
6859 return (ULONG)newRefCount;
6862 HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_ActivateCompleted(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation)
6864 (
void)pActivateOperation;
6865 SetEvent(pThis->hEvent);
6870 static ma_completion_handler_uwp_vtbl g_maCompletionHandlerVtblInstance = {
6871 ma_completion_handler_uwp_QueryInterface,
6872 ma_completion_handler_uwp_AddRef,
6873 ma_completion_handler_uwp_Release,
6874 ma_completion_handler_uwp_ActivateCompleted
6877 ma_result ma_completion_handler_uwp_init(ma_completion_handler_uwp* pHandler)
6879 ma_assert(pHandler !=
NULL);
6880 ma_zero_object(pHandler);
6882 pHandler->lpVtbl = &g_maCompletionHandlerVtblInstance;
6883 pHandler->counter = 1;
6885 if (pHandler->hEvent ==
NULL) {
6892 void ma_completion_handler_uwp_uninit(ma_completion_handler_uwp* pHandler)
6894 if (pHandler->hEvent !=
NULL) {
6895 CloseHandle(pHandler->hEvent);
6899 void ma_completion_handler_uwp_wait(ma_completion_handler_uwp* pHandler)
6901 WaitForSingleObject(pHandler->hEvent, INFINITE);
6906 #ifdef MA_WIN32_DESKTOP
6913 if (!ma_is_guid_equal(riid, &MA_IID_IUnknown) && !ma_is_guid_equal(riid, &MA_IID_IMMNotificationClient)) {
6915 return E_NOINTERFACE;
6919 *ppObject = (
void*)pThis;
6920 ((ma_IMMNotificationClientVtbl*)pThis->
lpVtbl)->AddRef(pThis);
6926 return (ULONG)ma_atomic_increment_32(&pThis->
counter);
6932 if (newRefCount == 0) {
6936 return (ULONG)newRefCount;
6942 #ifdef MA_DEBUG_OUTPUT
6943 printf(
"IMMNotificationClient_OnDeviceStateChanged(pDeviceID=%S, dwNewState=%u)\n", (pDeviceID !=
NULL) ? pDeviceID :
L"(NULL)", (
unsigned int)dwNewState);
6954 #ifdef MA_DEBUG_OUTPUT
6955 printf(
"IMMNotificationClient_OnDeviceAdded(pDeviceID=%S)\n", (pDeviceID !=
NULL) ? pDeviceID :
L"(NULL)");
6966 #ifdef MA_DEBUG_OUTPUT
6967 printf(
"IMMNotificationClient_OnDeviceRemoved(pDeviceID=%S)\n", (pDeviceID !=
NULL) ? pDeviceID :
L"(NULL)");
6976 HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged(
ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID)
6978 #ifdef MA_DEBUG_OUTPUT
6979 printf(
"IMMNotificationClient_OnDefaultDeviceChanged(dataFlow=%d, role=%d, pDefaultDeviceID=%S)\n", dataFlow, role, (pDefaultDeviceID !=
NULL) ? pDefaultDeviceID :
L"(NULL)");
6983 if (role != ma_eConsole) {
7007 if (dataFlow == ma_eRender) {
7008 ma_atomic_exchange_32(&pThis->
pDevice->wasapi.hasDefaultPlaybackDeviceChanged,
MA_TRUE);
7010 if (dataFlow == ma_eCapture) {
7011 ma_atomic_exchange_32(&pThis->
pDevice->wasapi.hasDefaultCaptureDeviceChanged,
MA_TRUE);
7014 (
void)pDefaultDeviceID;
7020 #ifdef MA_DEBUG_OUTPUT
7021 printf(
"IMMNotificationClient_OnPropertyValueChanged(pDeviceID=%S)\n", (pDeviceID !=
NULL) ? pDeviceID :
L"(NULL)");
7030 static ma_IMMNotificationClientVtbl g_maNotificationCientVtbl = {
7031 ma_IMMNotificationClient_QueryInterface,
7032 ma_IMMNotificationClient_AddRef,
7033 ma_IMMNotificationClient_Release,
7034 ma_IMMNotificationClient_OnDeviceStateChanged,
7035 ma_IMMNotificationClient_OnDeviceAdded,
7036 ma_IMMNotificationClient_OnDeviceRemoved,
7037 ma_IMMNotificationClient_OnDefaultDeviceChanged,
7038 ma_IMMNotificationClient_OnPropertyValueChanged
7042 #ifdef MA_WIN32_DESKTOP
7043 typedef ma_IMMDevice ma_WASAPIDeviceInterface;
7045 typedef ma_IUnknown ma_WASAPIDeviceInterface;
7052 ma_assert(pContext !=
NULL);
7053 ma_assert(pID0 !=
NULL);
7054 ma_assert(pID1 !=
NULL);
7060 void ma_set_device_info_from_WAVEFORMATEX(
const WAVEFORMATEX* pWF,
ma_device_info* pInfo)
7062 ma_assert(pWF !=
NULL);
7063 ma_assert(pInfo !=
NULL);
7066 pInfo->
formats[0] = ma_format_from_WAVEFORMATEX(pWF);
7075 ma_assert(pAudioClient !=
NULL);
7076 ma_assert(pInfo !=
NULL);
7081 WAVEFORMATEX* pWF =
NULL;
7082 HRESULT hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pAudioClient, (WAVEFORMATEX**)&pWF);
7083 if (SUCCEEDED(hr)) {
7084 ma_set_device_info_from_WAVEFORMATEX(pWF, pInfo);
7091 #ifdef MA_WIN32_DESKTOP
7096 ma_IPropertyStore *pProperties;
7097 HRESULT hr = ma_IMMDevice_OpenPropertyStore((ma_IMMDevice*)pMMDevice, STGM_READ, &pProperties);
7098 if (SUCCEEDED(hr)) {
7100 ma_PropVariantInit(&var);
7102 hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_AudioEngine_DeviceFormat, &var);
7103 if (SUCCEEDED(hr)) {
7104 WAVEFORMATEX* pWF = (WAVEFORMATEX*)var.blob.pBlobData;
7105 ma_set_device_info_from_WAVEFORMATEX(pWF, pInfo);
7111 hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pWF,
NULL);
7112 ma_PropVariantClear(pContext, &var);
7129 WAVEFORMATEXTENSIBLE wf;
7135 ma_zero_object(&wf);
7136 wf.Format.cbSize =
sizeof(wf);
7137 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
7138 wf.Format.nChannels = (WORD)
channels;
7139 wf.dwChannelMask = ma_channel_map_to_channel_mask__win32(defaultChannelMap,
channels);
7142 for (iFormat = 0; iFormat < ma_countof(formatsToSearch); ++iFormat) {
7147 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
7148 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
7149 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
7151 wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
7153 wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
7156 for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iSampleRate) {
7157 wf.Format.nSamplesPerSec = g_maStandardSampleRatePriorities[iSampleRate];
7159 hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, (WAVEFORMATEX*)&wf,
NULL);
7160 if (SUCCEEDED(hr)) {
7161 ma_set_device_info_from_WAVEFORMATEX((WAVEFORMATEX*)&wf, pInfo);
7173 ma_IPropertyStore_Release(pProperties);
7178 ma_IPropertyStore_Release(pProperties);
7193 #ifdef MA_WIN32_DESKTOP
7196 ma_IMMDeviceEnumerator* pDeviceEnumerator;
7199 ma_assert(pContext !=
NULL);
7200 ma_assert(ppMMDevice !=
NULL);
7202 hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator,
NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (
void**)&pDeviceEnumerator);
7207 if (pDeviceID ==
NULL) {
7208 hr = ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(pDeviceEnumerator, (deviceType ==
ma_device_type_playback) ? ma_eRender : ma_eCapture, ma_eConsole, ppMMDevice);
7210 hr = ma_IMMDeviceEnumerator_GetDevice(pDeviceEnumerator, pDeviceID->
wasapi, ppMMDevice);
7213 ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
7226 ma_assert(pContext !=
NULL);
7227 ma_assert(pMMDevice !=
NULL);
7228 ma_assert(pInfo !=
NULL);
7231 hr = ma_IMMDevice_GetId(pMMDevice, &
id);
7232 if (SUCCEEDED(hr)) {
7233 size_t idlen = wcslen(
id);
7234 if (idlen+1 > ma_countof(pInfo->
id.
wasapi)) {
7235 ma_CoTaskMemFree(pContext,
id);
7240 ma_copy_memory(pInfo->
id.
wasapi,
id, idlen *
sizeof(
wchar_t));
7243 ma_CoTaskMemFree(pContext,
id);
7247 ma_IPropertyStore *pProperties;
7248 hr = ma_IMMDevice_OpenPropertyStore(pMMDevice, STGM_READ, &pProperties);
7249 if (SUCCEEDED(hr)) {
7253 ma_PropVariantInit(&var);
7254 hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &var);
7255 if (SUCCEEDED(hr)) {
7256 WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, pInfo->
name,
sizeof(pInfo->
name), 0,
FALSE);
7257 ma_PropVariantClear(pContext, &var);
7260 ma_IPropertyStore_Release(pProperties);
7265 if (!onlySimpleInfo) {
7266 ma_IAudioClient* pAudioClient;
7267 hr = ma_IMMDevice_Activate(pMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL,
NULL, (
void**)&pAudioClient);
7268 if (SUCCEEDED(hr)) {
7269 ma_result result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext, pMMDevice, pAudioClient, shareMode, pInfo);
7271 ma_IAudioClient_Release(pAudioClient);
7287 ma_assert(pContext !=
NULL);
7288 ma_assert(callback !=
NULL);
7290 hr = ma_IMMDeviceCollection_GetCount(pDeviceCollection, &deviceCount);
7295 for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
7297 ma_IMMDevice* pMMDevice;
7299 ma_zero_object(&deviceInfo);
7301 hr = ma_IMMDeviceCollection_Item(pDeviceCollection, iDevice, &pMMDevice);
7302 if (SUCCEEDED(hr)) {
7305 ma_IMMDevice_Release(pMMDevice);
7307 ma_bool32 cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
7319 #ifdef MA_WIN32_DESKTOP
7325 ma_assert(pContext !=
NULL);
7326 ma_assert(ppAudioClient !=
NULL);
7327 ma_assert(ppMMDevice !=
NULL);
7329 result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, ppMMDevice);
7334 hr = ma_IMMDevice_Activate(*ppMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL,
NULL, (
void**)ppAudioClient);
7344 ma_IActivateAudioInterfaceAsyncOperation *pAsyncOp =
NULL;
7345 ma_completion_handler_uwp completionHandler;
7351 ma_IUnknown* pActivatedInterface;
7353 ma_assert(pContext !=
NULL);
7354 ma_assert(ppAudioClient !=
NULL);
7356 if (pDeviceID !=
NULL) {
7357 ma_copy_memory(&iid, pDeviceID->
wasapi,
sizeof(iid));
7360 iid = MA_IID_DEVINTERFACE_AUDIO_RENDER;
7362 iid = MA_IID_DEVINTERFACE_AUDIO_CAPTURE;
7366 #if defined(__cplusplus)
7367 hr = StringFromIID(iid, &iidStr);
7369 hr = StringFromIID(&iid, &iidStr);
7375 result = ma_completion_handler_uwp_init(&completionHandler);
7377 ma_CoTaskMemFree(pContext, iidStr);
7381 #if defined(__cplusplus)
7382 hr = ActivateAudioInterfaceAsync(iidStr, MA_IID_IAudioClient,
NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
7384 hr = ActivateAudioInterfaceAsync(iidStr, &MA_IID_IAudioClient,
NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
7387 ma_completion_handler_uwp_uninit(&completionHandler);
7388 ma_CoTaskMemFree(pContext, iidStr);
7392 ma_CoTaskMemFree(pContext, iidStr);
7395 ma_completion_handler_uwp_wait(&completionHandler);
7396 ma_completion_handler_uwp_uninit(&completionHandler);
7398 hr = ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(pAsyncOp, &activateResult, &pActivatedInterface);
7399 ma_IActivateAudioInterfaceAsyncOperation_Release(pAsyncOp);
7401 if (FAILED(hr) || FAILED(activateResult)) {
7406 hr = ma_IUnknown_QueryInterface(pActivatedInterface, &MA_IID_IAudioClient, (
void**)ppAudioClient);
7411 if (ppActivatedInterface) {
7412 *ppActivatedInterface = pActivatedInterface;
7414 ma_IUnknown_Release(pActivatedInterface);
7423 #ifdef MA_WIN32_DESKTOP
7424 return ma_context_get_IAudioClient_Desktop__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
7426 return ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
7434 #ifdef MA_WIN32_DESKTOP
7437 ma_IMMDeviceEnumerator* pDeviceEnumerator;
7438 ma_IMMDeviceCollection* pDeviceCollection;
7440 hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator,
NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (
void**)&pDeviceEnumerator);
7446 hr = ma_IMMDeviceEnumerator_EnumAudioEndpoints(pDeviceEnumerator, ma_eRender, MA_MM_DEVICE_STATE_ACTIVE, &pDeviceCollection);
7447 if (SUCCEEDED(hr)) {
7448 ma_context_enumerate_device_collection__wasapi(pContext, pDeviceCollection,
ma_device_type_playback, callback, pUserData);
7449 ma_IMMDeviceCollection_Release(pDeviceCollection);
7453 hr = ma_IMMDeviceEnumerator_EnumAudioEndpoints(pDeviceEnumerator, ma_eCapture, MA_MM_DEVICE_STATE_ACTIVE, &pDeviceCollection);
7454 if (SUCCEEDED(hr)) {
7455 ma_context_enumerate_device_collection__wasapi(pContext, pDeviceCollection,
ma_device_type_capture, callback, pUserData);
7456 ma_IMMDeviceCollection_Release(pDeviceCollection);
7459 ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
7475 ma_zero_object(&deviceInfo);
7476 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
7483 ma_zero_object(&deviceInfo);
7484 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
7495 #ifdef MA_WIN32_DESKTOP
7496 ma_IMMDevice* pMMDevice =
NULL;
7499 result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, &pMMDevice);
7504 result = ma_context_get_device_info_from_MMDevice__wasapi(pContext, pMMDevice, shareMode,
MA_FALSE, pDeviceInfo);
7506 ma_IMMDevice_Release(pMMDevice);
7509 ma_IAudioClient* pAudioClient;
7514 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
7516 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
7524 result = ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, &pAudioClient,
NULL);
7529 result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext,
NULL, pAudioClient, shareMode, pDeviceInfo);
7531 ma_IAudioClient_Release(pAudioClient);
7536 void ma_device_uninit__wasapi(
ma_device* pDevice)
7538 ma_assert(pDevice !=
NULL);
7540 #ifdef MA_WIN32_DESKTOP
7541 if (pDevice->wasapi.pDeviceEnumerator) {
7542 ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient);
7543 ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator);
7547 if (pDevice->wasapi.pRenderClient) {
7548 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
7550 if (pDevice->wasapi.pCaptureClient) {
7551 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
7554 if (pDevice->wasapi.pAudioClientPlayback) {
7555 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
7557 if (pDevice->wasapi.pAudioClientCapture) {
7558 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
7561 if (pDevice->wasapi.hEventPlayback) {
7562 CloseHandle(pDevice->wasapi.hEventPlayback);
7564 if (pDevice->wasapi.hEventCapture) {
7565 CloseHandle(pDevice->wasapi.hEventCapture);
7587 ma_IAudioClient* pAudioClient;
7588 ma_IAudioRenderClient* pRenderClient;
7589 ma_IAudioCaptureClient* pCaptureClient;
7597 char deviceName[256];
7598 } ma_device_init_internal_data__wasapi;
7604 const char* errorMsg =
"";
7605 MA_AUDCLNT_SHAREMODE shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
7606 MA_REFERENCE_TIME bufferDurationInMicroseconds;
7608 WAVEFORMATEXTENSIBLE wf;
7609 ma_WASAPIDeviceInterface* pDeviceInterface =
NULL;
7610 ma_IAudioClient2* pAudioClient2;
7612 ma_assert(pContext !=
NULL);
7613 ma_assert(pData !=
NULL);
7620 pData->pAudioClient =
NULL;
7621 pData->pRenderClient =
NULL;
7622 pData->pCaptureClient =
NULL;
7624 result = ma_context_get_IAudioClient__wasapi(pContext, deviceType, pDeviceID, &pData->pAudioClient, &pDeviceInterface);
7631 hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient2, (
void**)&pAudioClient2);
7632 if (SUCCEEDED(hr)) {
7633 BOOL isHardwareOffloadingSupported = 0;
7634 hr = ma_IAudioClient2_IsOffloadCapable(pAudioClient2, MA_AudioCategory_Other, &isHardwareOffloadingSupported);
7635 if (SUCCEEDED(hr) && isHardwareOffloadingSupported) {
7636 ma_AudioClientProperties clientProperties;
7637 ma_zero_object(&clientProperties);
7638 clientProperties.cbSize =
sizeof(clientProperties);
7639 clientProperties.bIsOffload = 1;
7640 clientProperties.eCategory = MA_AudioCategory_Other;
7641 ma_IAudioClient2_SetClientProperties(pAudioClient2, &clientProperties);
7649 #ifdef MA_WIN32_DESKTOP
7651 ma_IPropertyStore* pStore =
NULL;
7652 hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pStore);
7653 if (SUCCEEDED(hr)) {
7655 ma_PropVariantInit(&prop);
7656 hr = ma_IPropertyStore_GetValue(pStore, &MA_PKEY_AudioEngine_DeviceFormat, &prop);
7657 if (SUCCEEDED(hr)) {
7658 WAVEFORMATEX* pActualFormat = (WAVEFORMATEX*)prop.blob.pBlobData;
7659 hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pData->pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pActualFormat,
NULL);
7660 if (SUCCEEDED(hr)) {
7661 ma_copy_memory(&wf, pActualFormat,
sizeof(WAVEFORMATEXTENSIBLE));
7664 ma_PropVariantClear(pContext, &prop);
7667 ma_IPropertyStore_Release(pStore);
7681 shareMode = MA_AUDCLNT_SHAREMODE_EXCLUSIVE;
7688 WAVEFORMATEXTENSIBLE* pNativeFormat =
NULL;
7689 hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pData->pAudioClient, (WAVEFORMATEX**)&pNativeFormat);
7693 ma_copy_memory(&wf, pNativeFormat,
sizeof(wf));
7697 ma_CoTaskMemFree(pContext, pNativeFormat);
7699 shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
7704 errorMsg =
"[WASAPI] Failed to find best device mix format.";
7708 pData->formatOut = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)&wf);
7709 pData->channelsOut = wf.Format.nChannels;
7710 pData->sampleRateOut = wf.Format.nSamplesPerSec;
7713 ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
7716 pData->periodsOut = pData->periodsIn;
7717 pData->bufferSizeInFramesOut = pData->bufferSizeInFramesIn;
7718 if (pData->bufferSizeInFramesOut == 0) {
7722 bufferDurationInMicroseconds = ((
ma_uint64)pData->bufferSizeInFramesOut * 1000 * 1000) / pData->sampleRateOut;
7726 if (shareMode == MA_AUDCLNT_SHAREMODE_EXCLUSIVE) {
7727 MA_REFERENCE_TIME bufferDuration = (bufferDurationInMicroseconds / pData->periodsOut) * 10;
7735 hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf,
NULL);
7736 if (hr == MA_AUDCLNT_E_INVALID_DEVICE_PERIOD) {
7737 if (bufferDuration > 500*10000) {
7740 if (bufferDuration == 0) {
7744 bufferDuration = bufferDuration * 2;
7752 if (hr == MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
7753 UINT bufferSizeInFrames;
7754 hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &bufferSizeInFrames);
7755 if (SUCCEEDED(hr)) {
7756 bufferDuration = (MA_REFERENCE_TIME)((10000.0 * 1000 / wf.Format.nSamplesPerSec * bufferSizeInFrames) + 0.5);
7759 ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
7761 #ifdef MA_WIN32_DESKTOP
7762 hr = ma_IMMDevice_Activate(pDeviceInterface, &MA_IID_IAudioClient, CLSCTX_ALL,
NULL, (
void**)&pData->pAudioClient);
7764 hr = ma_IUnknown_QueryInterface(pDeviceInterface, &MA_IID_IAudioClient, (
void**)&pData->pAudioClient);
7767 if (SUCCEEDED(hr)) {
7768 hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf,
NULL);
7775 if (hr == E_ACCESSDENIED) {
7776 errorMsg =
"[WASAPI] Failed to initialize device in exclusive mode. Access denied.", result =
MA_ACCESS_DENIED;
7777 }
else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
7778 errorMsg =
"[WASAPI] Failed to initialize device in exclusive mode. Device in use.", result =
MA_DEVICE_BUSY;
7786 if (shareMode == MA_AUDCLNT_SHAREMODE_SHARED) {
7788 #ifndef MA_WASAPI_NO_LOW_LATENCY_SHARED_MODE
7789 ma_IAudioClient3* pAudioClient3 =
NULL;
7790 hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient3, (
void**)&pAudioClient3);
7791 if (SUCCEEDED(hr)) {
7792 UINT32 defaultPeriodInFrames;
7793 UINT32 fundamentalPeriodInFrames;
7794 UINT32 minPeriodInFrames;
7795 UINT32 maxPeriodInFrames;
7796 hr = ma_IAudioClient3_GetSharedModeEnginePeriod(pAudioClient3, (WAVEFORMATEX*)&wf, &defaultPeriodInFrames, &fundamentalPeriodInFrames, &minPeriodInFrames, &maxPeriodInFrames);
7797 if (SUCCEEDED(hr)) {
7798 UINT32 desiredPeriodInFrames = pData->bufferSizeInFramesOut / pData->periodsOut;
7799 UINT32 actualPeriodInFrames = desiredPeriodInFrames;
7802 actualPeriodInFrames = actualPeriodInFrames / fundamentalPeriodInFrames;
7803 actualPeriodInFrames = actualPeriodInFrames * fundamentalPeriodInFrames;
7806 actualPeriodInFrames = ma_clamp(actualPeriodInFrames, minPeriodInFrames, maxPeriodInFrames);
7809 if (actualPeriodInFrames >= desiredPeriodInFrames) {
7810 hr = ma_IAudioClient3_InitializeSharedAudioStream(pAudioClient3, MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK, actualPeriodInFrames, (WAVEFORMATEX*)&wf,
NULL);
7811 if (SUCCEEDED(hr)) {
7812 wasInitializedUsingIAudioClient3 =
MA_TRUE;
7813 pData->periodSizeInFramesOut = actualPeriodInFrames;
7814 pData->bufferSizeInFramesOut = actualPeriodInFrames * pData->periodsOut;
7819 ma_IAudioClient3_Release(pAudioClient3);
7820 pAudioClient3 =
NULL;
7825 if (!wasInitializedUsingIAudioClient3) {
7826 MA_REFERENCE_TIME bufferDuration = bufferDurationInMicroseconds*10;
7827 hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK, bufferDuration, 0, (WAVEFORMATEX*)&wf,
NULL);
7829 if (hr == E_ACCESSDENIED) {
7830 errorMsg =
"[WASAPI] Failed to initialize device. Access denied.", result =
MA_ACCESS_DENIED;
7831 }
else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
7832 errorMsg =
"[WASAPI] Failed to initialize device. Device in use.", result =
MA_DEVICE_BUSY;
7842 if (!wasInitializedUsingIAudioClient3) {
7843 hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &pData->bufferSizeInFramesOut);
7849 pData->periodSizeInFramesOut = pData->bufferSizeInFramesOut / pData->periodsOut;
7853 hr = ma_IAudioClient_GetService((ma_IAudioClient*)pData->pAudioClient, &MA_IID_IAudioRenderClient, (
void**)&pData->pRenderClient);
7855 hr = ma_IAudioClient_GetService((ma_IAudioClient*)pData->pAudioClient, &MA_IID_IAudioCaptureClient, (
void**)&pData->pCaptureClient);
7859 errorMsg =
"[WASAPI] Failed to get audio client service.", result =
MA_API_NOT_FOUND;
7865 #ifdef MA_WIN32_DESKTOP
7867 ma_IPropertyStore *pProperties;
7868 hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pProperties);
7869 if (SUCCEEDED(hr)) {
7870 PROPVARIANT varName;
7871 ma_PropVariantInit(&varName);
7872 hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &varName);
7873 if (SUCCEEDED(hr)) {
7874 WideCharToMultiByte(CP_UTF8, 0, varName.pwszVal, -1, pData->deviceName,
sizeof(pData->deviceName), 0,
FALSE);
7875 ma_PropVariantClear(pContext, &varName);
7878 ma_IPropertyStore_Release(pProperties);
7885 #ifdef MA_WIN32_DESKTOP
7886 if (pDeviceInterface !=
NULL) {
7887 ma_IMMDevice_Release(pDeviceInterface);
7890 if (pDeviceInterface !=
NULL) {
7891 ma_IUnknown_Release(pDeviceInterface);
7896 if (pData->pRenderClient) {
7897 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pData->pRenderClient);
7898 pData->pRenderClient =
NULL;
7900 if (pData->pCaptureClient) {
7901 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pData->pCaptureClient);
7902 pData->pCaptureClient =
NULL;
7904 if (pData->pAudioClient) {
7905 ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
7906 pData->pAudioClient =
NULL;
7917 ma_device_init_internal_data__wasapi data;
7920 ma_assert(pDevice !=
NULL);
7928 data.formatIn = pDevice->capture.format;
7929 data.channelsIn = pDevice->capture.channels;
7930 ma_copy_memory(data.channelMapIn, pDevice->capture.channelMap,
sizeof(pDevice->capture.channelMap));
7931 data.shareMode = pDevice->capture.shareMode;
7932 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
7933 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
7934 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
7936 data.formatIn = pDevice->playback.format;
7937 data.channelsIn = pDevice->playback.channels;
7938 ma_copy_memory(data.channelMapIn, pDevice->playback.channelMap,
sizeof(pDevice->playback.channelMap));
7939 data.shareMode = pDevice->playback.shareMode;
7940 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
7941 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
7942 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
7945 data.sampleRateIn = pDevice->sampleRate;
7946 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
7947 data.bufferSizeInFramesIn = pDevice->wasapi.originalBufferSizeInFrames;
7948 data.bufferSizeInMillisecondsIn = pDevice->wasapi.originalBufferSizeInMilliseconds;
7949 data.periodsIn = pDevice->wasapi.originalPeriods;
7950 result = ma_device_init_internal__wasapi(pDevice->pContext, deviceType,
NULL, &data);
7957 if (pDevice->wasapi.pCaptureClient) {
7958 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
7959 pDevice->wasapi.pCaptureClient =
NULL;
7962 if (pDevice->wasapi.pAudioClientCapture) {
7963 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
7964 pDevice->wasapi.pAudioClientCapture =
NULL;
7967 pDevice->wasapi.pAudioClientCapture = data.pAudioClient;
7968 pDevice->wasapi.pCaptureClient = data.pCaptureClient;
7970 pDevice->capture.internalFormat = data.formatOut;
7971 pDevice->capture.internalChannels = data.channelsOut;
7972 pDevice->capture.internalSampleRate = data.sampleRateOut;
7973 ma_copy_memory(pDevice->capture.internalChannelMap, data.channelMapOut,
sizeof(data.channelMapOut));
7974 pDevice->capture.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
7975 pDevice->capture.internalPeriods = data.periodsOut;
7976 ma_strcpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name), data.deviceName);
7978 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
7980 pDevice->wasapi.periodSizeInFramesCapture = data.periodSizeInFramesOut;
7981 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualBufferSizeInFramesCapture);
7984 if (pDevice->wasapi.isStartedCapture) {
7985 HRESULT hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
7993 if (pDevice->wasapi.pRenderClient) {
7994 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
7995 pDevice->wasapi.pRenderClient =
NULL;
7998 if (pDevice->wasapi.pAudioClientPlayback) {
7999 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8000 pDevice->wasapi.pAudioClientPlayback =
NULL;
8003 pDevice->wasapi.pAudioClientPlayback = data.pAudioClient;
8004 pDevice->wasapi.pRenderClient = data.pRenderClient;
8006 pDevice->playback.internalFormat = data.formatOut;
8007 pDevice->playback.internalChannels = data.channelsOut;
8008 pDevice->playback.internalSampleRate = data.sampleRateOut;
8009 ma_copy_memory(pDevice->playback.internalChannelMap, data.channelMapOut,
sizeof(data.channelMapOut));
8010 pDevice->playback.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
8011 pDevice->playback.internalPeriods = data.periodsOut;
8012 ma_strcpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name), data.deviceName);
8014 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
8016 pDevice->wasapi.periodSizeInFramesPlayback = data.periodSizeInFramesOut;
8017 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualBufferSizeInFramesPlayback);
8020 if (pDevice->wasapi.isStartedPlayback) {
8021 HRESULT hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8037 ma_assert(pContext !=
NULL);
8038 ma_assert(pDevice !=
NULL);
8040 ma_zero_object(&pDevice->wasapi);
8043 pDevice->wasapi.originalPeriods = pConfig->
periods;
8046 ma_device_init_internal_data__wasapi data;
8051 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
8052 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
8053 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
8054 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
8058 data.periodsIn = pConfig->
periods;
8065 pDevice->wasapi.pAudioClientCapture = data.pAudioClient;
8066 pDevice->wasapi.pCaptureClient = data.pCaptureClient;
8068 pDevice->capture.internalFormat = data.formatOut;
8069 pDevice->capture.internalChannels = data.channelsOut;
8070 pDevice->capture.internalSampleRate = data.sampleRateOut;
8071 ma_copy_memory(pDevice->capture.internalChannelMap, data.channelMapOut,
sizeof(data.channelMapOut));
8072 pDevice->capture.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
8073 pDevice->capture.internalPeriods = data.periodsOut;
8074 ma_strcpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name), data.deviceName);
8081 if (pDevice->wasapi.hEventCapture ==
NULL) {
8082 if (pDevice->wasapi.pCaptureClient !=
NULL) {
8083 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8084 pDevice->wasapi.pCaptureClient =
NULL;
8086 if (pDevice->wasapi.pAudioClientCapture !=
NULL) {
8087 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8088 pDevice->wasapi.pAudioClientCapture =
NULL;
8093 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
8095 pDevice->wasapi.periodSizeInFramesCapture = data.periodSizeInFramesOut;
8096 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualBufferSizeInFramesCapture);
8100 ma_device_init_internal_data__wasapi data;
8105 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
8106 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
8107 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
8108 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
8112 data.periodsIn = pConfig->
periods;
8117 if (pDevice->wasapi.pCaptureClient !=
NULL) {
8118 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8119 pDevice->wasapi.pCaptureClient =
NULL;
8121 if (pDevice->wasapi.pAudioClientCapture !=
NULL) {
8122 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8123 pDevice->wasapi.pAudioClientCapture =
NULL;
8126 CloseHandle(pDevice->wasapi.hEventCapture);
8127 pDevice->wasapi.hEventCapture =
NULL;
8132 pDevice->wasapi.pAudioClientPlayback = data.pAudioClient;
8133 pDevice->wasapi.pRenderClient = data.pRenderClient;
8135 pDevice->playback.internalFormat = data.formatOut;
8136 pDevice->playback.internalChannels = data.channelsOut;
8137 pDevice->playback.internalSampleRate = data.sampleRateOut;
8138 ma_copy_memory(pDevice->playback.internalChannelMap, data.channelMapOut,
sizeof(data.channelMapOut));
8139 pDevice->playback.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
8140 pDevice->playback.internalPeriods = data.periodsOut;
8141 ma_strcpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name), data.deviceName);
8151 if (pDevice->wasapi.hEventPlayback ==
NULL) {
8153 if (pDevice->wasapi.pCaptureClient !=
NULL) {
8154 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8155 pDevice->wasapi.pCaptureClient =
NULL;
8157 if (pDevice->wasapi.pAudioClientCapture !=
NULL) {
8158 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8159 pDevice->wasapi.pAudioClientCapture =
NULL;
8162 CloseHandle(pDevice->wasapi.hEventCapture);
8163 pDevice->wasapi.hEventCapture =
NULL;
8166 if (pDevice->wasapi.pRenderClient !=
NULL) {
8167 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
8168 pDevice->wasapi.pRenderClient =
NULL;
8170 if (pDevice->wasapi.pAudioClientPlayback !=
NULL) {
8171 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8172 pDevice->wasapi.pAudioClientPlayback =
NULL;
8177 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
8179 pDevice->wasapi.periodSizeInFramesPlayback = data.periodSizeInFramesOut;
8180 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualBufferSizeInFramesPlayback);
8187 #ifdef MA_WIN32_DESKTOP
8189 ma_IMMDeviceEnumerator* pDeviceEnumerator;
8190 HRESULT hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator,
NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (
void**)&pDeviceEnumerator);
8192 ma_device_uninit__wasapi(pDevice);
8196 pDevice->wasapi.notificationClient.lpVtbl = (
void*)&g_maNotificationCientVtbl;
8197 pDevice->wasapi.notificationClient.counter = 1;
8198 pDevice->wasapi.notificationClient.pDevice = pDevice;
8200 hr = pDeviceEnumerator->lpVtbl->RegisterEndpointNotificationCallback(pDeviceEnumerator, &pDevice->wasapi.notificationClient);
8201 if (SUCCEEDED(hr)) {
8202 pDevice->wasapi.pDeviceEnumerator = (
ma_ptr)pDeviceEnumerator;
8205 ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
8210 ma_atomic_exchange_32(&pDevice->wasapi.isStartedCapture,
MA_FALSE);
8211 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_FALSE);
8222 ma_assert(pDevice !=
NULL);
8223 ma_assert(pFrameCount !=
NULL);
8227 if ((
ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientPlayback && (
ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientCapture) {
8231 hr = ma_IAudioClient_GetCurrentPadding(pAudioClient, &paddingFramesCount);
8237 shareMode = ((
ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) ? pDevice->playback.shareMode : pDevice->capture.shareMode;
8239 *pFrameCount = paddingFramesCount;
8241 if ((
ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) {
8242 *pFrameCount = pDevice->wasapi.actualBufferSizeInFramesPlayback - paddingFramesCount;
8244 *pFrameCount = paddingFramesCount;
8253 ma_assert(pDevice !=
NULL);
8256 return pDevice->wasapi.hasDefaultPlaybackDeviceChanged;
8260 return pDevice->wasapi.hasDefaultCaptureDeviceChanged;
8275 ma_atomic_exchange_32(&pDevice->wasapi.hasDefaultPlaybackDeviceChanged,
MA_FALSE);
8278 ma_atomic_exchange_32(&pDevice->wasapi.hasDefaultCaptureDeviceChanged,
MA_FALSE);
8282 #ifdef MA_DEBUG_OUTPUT
8283 printf(
"=== CHANGING DEVICE ===\n");
8286 result = ma_device_reinit__wasapi(pDevice, deviceType);
8291 ma_device__post_init_setup(pDevice, deviceType);
8302 ma_uint32 framesWrittenToPlaybackDevice = 0;
8303 ma_uint32 mappedBufferSizeInFramesCapture = 0;
8304 ma_uint32 mappedBufferSizeInFramesPlayback = 0;
8305 ma_uint32 mappedBufferFramesRemainingCapture = 0;
8306 ma_uint32 mappedBufferFramesRemainingPlayback = 0;
8307 BYTE* pMappedBufferCapture =
NULL;
8308 BYTE* pMappedBufferPlayback =
NULL;
8311 ma_uint8 inputDataInExternalFormat[4096];
8312 ma_uint32 inputDataInExternalFormatCap =
sizeof(inputDataInExternalFormat) / bpfCapture;
8313 ma_uint8 outputDataInExternalFormat[4096];
8314 ma_uint32 outputDataInExternalFormatCap =
sizeof(outputDataInExternalFormat) / bpfPlayback;
8316 ma_assert(pDevice !=
NULL);
8320 hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8324 ma_atomic_exchange_32(&pDevice->wasapi.isStartedCapture,
MA_TRUE);
8327 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
8344 switch (pDevice->type)
8353 if (pMappedBufferPlayback ==
NULL) {
8356 if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) == WAIT_FAILED) {
8361 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
8371 if (framesAvailablePlayback >= pDevice->wasapi.periodSizeInFramesPlayback) {
8372 framesAvailablePlayback = pDevice->wasapi.periodSizeInFramesPlayback;
8377 if (framesAvailablePlayback == 0) {
8380 if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) == WAIT_FAILED) {
8389 hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedBufferPlayback);
8396 mappedBufferSizeInFramesPlayback = framesAvailablePlayback;
8397 mappedBufferFramesRemainingPlayback = framesAvailablePlayback;
8403 if (pMappedBufferCapture ==
NULL) {
8405 if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) == WAIT_FAILED) {
8410 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
8419 if (framesAvailableCapture == 0) {
8422 if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) == WAIT_FAILED) {
8431 mappedBufferSizeInFramesCapture = framesAvailableCapture;
8432 hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedBufferCapture, &mappedBufferSizeInFramesCapture, &flagsCapture,
NULL,
NULL);
8440 #ifdef MA_DEBUG_OUTPUT
8441 if (flagsCapture != 0) {
8442 printf(
"[WASAPI] Capture Flags: %d\n", flagsCapture);
8446 mappedBufferFramesRemainingCapture = mappedBufferSizeInFramesCapture;
8448 pDevice->capture._dspFrameCount = mappedBufferSizeInFramesCapture;
8449 pDevice->capture._dspFrames = (
const ma_uint8*)pMappedBufferCapture;
8455 BYTE* pRunningBufferCapture;
8456 BYTE* pRunningBufferPlayback;
8460 pRunningBufferCapture = pMappedBufferCapture + ((mappedBufferSizeInFramesCapture - mappedBufferFramesRemainingCapture ) * bpfPlayback);
8461 pRunningBufferPlayback = pMappedBufferPlayback + ((mappedBufferSizeInFramesPlayback - mappedBufferFramesRemainingPlayback) * bpfPlayback);
8464 if (!pDevice->playback.converter.isPassthrough) {
8466 if (framesProcessed > 0) {
8467 mappedBufferFramesRemainingPlayback -= framesProcessed;
8468 if (mappedBufferFramesRemainingPlayback == 0) {
8478 if (pDevice->capture.converter.isPassthrough && pDevice->playback.converter.isPassthrough) {
8480 framesToProcess = ma_min(mappedBufferFramesRemainingCapture, mappedBufferFramesRemainingPlayback);
8481 framesProcessed = framesToProcess;
8483 pDevice->onData(pDevice, pRunningBufferPlayback, pRunningBufferCapture, framesToProcess);
8485 mappedBufferFramesRemainingCapture -= framesProcessed;
8486 mappedBufferFramesRemainingPlayback -= framesProcessed;
8488 if (mappedBufferFramesRemainingCapture == 0) {
8491 if (mappedBufferFramesRemainingPlayback == 0) {
8494 }
else if (pDevice->capture.converter.isPassthrough) {
8496 framesToProcess = ma_min(mappedBufferFramesRemainingCapture, outputDataInExternalFormatCap);
8497 framesProcessed = framesToProcess;
8499 pDevice->onData(pDevice, outputDataInExternalFormat, pRunningBufferCapture, framesToProcess);
8500 mappedBufferFramesRemainingCapture -= framesProcessed;
8502 pDevice->playback._dspFrameCount = framesProcessed;
8503 pDevice->playback._dspFrames = (
const ma_uint8*)outputDataInExternalFormat;
8505 if (mappedBufferFramesRemainingCapture == 0) {
8508 }
else if (pDevice->playback.converter.isPassthrough) {
8510 framesToProcess = ma_min(inputDataInExternalFormatCap, mappedBufferFramesRemainingPlayback);
8512 if (framesProcessed == 0) {
8514 mappedBufferFramesRemainingCapture = 0;
8518 pDevice->onData(pDevice, pRunningBufferPlayback, inputDataInExternalFormat, framesProcessed);
8519 mappedBufferFramesRemainingPlayback -= framesProcessed;
8521 if (framesProcessed < framesToProcess) {
8522 mappedBufferFramesRemainingCapture = 0;
8526 if (mappedBufferFramesRemainingPlayback == 0) {
8530 framesToProcess = ma_min(inputDataInExternalFormatCap, outputDataInExternalFormatCap);
8532 if (framesProcessed == 0) {
8534 mappedBufferFramesRemainingCapture = 0;
8538 pDevice->onData(pDevice, outputDataInExternalFormat, inputDataInExternalFormat, framesProcessed);
8540 pDevice->playback._dspFrameCount = framesProcessed;
8541 pDevice->playback._dspFrames = (
const ma_uint8*)outputDataInExternalFormat;
8543 if (framesProcessed < framesToProcess) {
8545 mappedBufferFramesRemainingCapture = 0;
8553 if (mappedBufferFramesRemainingCapture == 0 && pMappedBufferCapture !=
NULL) {
8554 hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedBufferSizeInFramesCapture);
8563 pMappedBufferCapture =
NULL;
8564 mappedBufferFramesRemainingCapture = 0;
8565 mappedBufferSizeInFramesCapture = 0;
8569 if (mappedBufferFramesRemainingPlayback == 0) {
8576 if (mappedBufferFramesRemainingPlayback == 0 && pMappedBufferPlayback !=
NULL) {
8577 hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedBufferSizeInFramesPlayback, 0);
8585 framesWrittenToPlaybackDevice += mappedBufferSizeInFramesPlayback;
8587 pMappedBufferPlayback =
NULL;
8588 mappedBufferFramesRemainingPlayback = 0;
8589 mappedBufferSizeInFramesPlayback = 0;
8592 if (!pDevice->wasapi.isStartedPlayback) {
8593 if (pDevice->playback.shareMode ==
ma_share_mode_exclusive || framesWrittenToPlaybackDevice >= (pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*2) {
8594 hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8596 ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8597 ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8600 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_TRUE);
8613 if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) == WAIT_FAILED) {
8619 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
8625 if (framesAvailableCapture < pDevice->wasapi.periodSizeInFramesCapture) {
8630 mappedBufferSizeInFramesCapture = framesAvailableCapture;
8631 hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedBufferCapture, &mappedBufferSizeInFramesCapture, &flagsCapture,
NULL,
NULL);
8639 ma_device__send_frames_to_client(pDevice, mappedBufferSizeInFramesCapture, pMappedBufferCapture);
8642 hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedBufferSizeInFramesCapture);
8643 pMappedBufferCapture =
NULL;
8644 mappedBufferSizeInFramesCapture = 0;
8659 if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) == WAIT_FAILED) {
8665 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
8671 if (framesAvailablePlayback < pDevice->wasapi.periodSizeInFramesPlayback) {
8676 hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedBufferPlayback);
8684 ma_device__read_frames_from_client(pDevice, framesAvailablePlayback, pMappedBufferPlayback);
8687 hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, 0);
8688 pMappedBufferPlayback =
NULL;
8689 mappedBufferSizeInFramesPlayback = 0;
8697 framesWrittenToPlaybackDevice += framesAvailablePlayback;
8698 if (!pDevice->wasapi.isStartedPlayback) {
8699 if (pDevice->playback.shareMode ==
ma_share_mode_exclusive || framesWrittenToPlaybackDevice >= (pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*1) {
8700 hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8706 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_TRUE);
8718 if (pMappedBufferCapture !=
NULL) {
8719 hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedBufferSizeInFramesCapture);
8722 hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8728 hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8733 ma_atomic_exchange_32(&pDevice->wasapi.isStartedCapture,
MA_FALSE);
8738 if (pMappedBufferPlayback !=
NULL) {
8739 hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedBufferSizeInFramesPlayback, 0);
8746 if (pDevice->wasapi.isStartedPlayback) {
8748 WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE);
8750 ma_uint32 prevFramesAvaialablePlayback = (size_t)-1;
8753 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
8758 if (framesAvailablePlayback >= pDevice->wasapi.actualBufferSizeInFramesPlayback) {
8766 if (framesAvailablePlayback == prevFramesAvaialablePlayback) {
8769 prevFramesAvaialablePlayback = framesAvailablePlayback;
8771 WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE);
8772 ResetEvent(pDevice->wasapi.hEventPlayback);
8777 hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8783 hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8788 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_FALSE);
8796 ma_assert(pContext !=
NULL);
8807 ma_assert(pContext !=
NULL);
8811 #ifdef MA_WIN32_DESKTOP
8819 ma_OSVERSIONINFOEXW osvi;
8821 ma_PFNVerifyVersionInfoW _VerifyVersionInfoW;
8822 ma_PFNVerSetConditionMask _VerSetConditionMask;
8824 kernel32DLL = ma_dlopen(pContext,
"kernel32.dll");
8825 if (kernel32DLL ==
NULL) {
8829 _VerifyVersionInfoW = (ma_PFNVerifyVersionInfoW)ma_dlsym(pContext, kernel32DLL,
"VerifyVersionInfoW");
8830 _VerSetConditionMask = (ma_PFNVerSetConditionMask)ma_dlsym(pContext, kernel32DLL,
"VerSetConditionMask");
8831 if (_VerifyVersionInfoW ==
NULL || _VerSetConditionMask ==
NULL) {
8832 ma_dlclose(pContext, kernel32DLL);
8836 ma_zero_object(&osvi);
8837 osvi.dwOSVersionInfoSize =
sizeof(osvi);
8838 osvi.dwMajorVersion = HIBYTE(MA_WIN32_WINNT_VISTA);
8839 osvi.dwMinorVersion = LOBYTE(MA_WIN32_WINNT_VISTA);
8840 osvi.wServicePackMajor = 1;
8841 if (_VerifyVersionInfoW(&osvi, MA_VER_MAJORVERSION | MA_VER_MINORVERSION | MA_VER_SERVICEPACKMAJOR, _VerSetConditionMask(_VerSetConditionMask(_VerSetConditionMask(0, MA_VER_MAJORVERSION, MA_VER_GREATER_EQUAL), MA_VER_MINORVERSION, MA_VER_GREATER_EQUAL), MA_VER_SERVICEPACKMAJOR, MA_VER_GREATER_EQUAL))) {
8847 ma_dlclose(pContext, kernel32DLL);
8855 pContext->
onUninit = ma_context_uninit__wasapi;
8857 pContext->
onEnumDevices = ma_context_enumerate_devices__wasapi;
8876 #ifdef MA_HAS_DSOUND
8879 GUID MA_GUID_IID_DirectSoundNotify = {0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16}};
8882 #define MA_DSSCL_NORMAL 1
8883 #define MA_DSSCL_PRIORITY 2
8884 #define MA_DSSCL_EXCLUSIVE 3
8885 #define MA_DSSCL_WRITEPRIMARY 4
8887 #define MA_DSCAPS_PRIMARYMONO 0x00000001
8888 #define MA_DSCAPS_PRIMARYSTEREO 0x00000002
8889 #define MA_DSCAPS_PRIMARY8BIT 0x00000004
8890 #define MA_DSCAPS_PRIMARY16BIT 0x00000008
8891 #define MA_DSCAPS_CONTINUOUSRATE 0x00000010
8892 #define MA_DSCAPS_EMULDRIVER 0x00000020
8893 #define MA_DSCAPS_CERTIFIED 0x00000040
8894 #define MA_DSCAPS_SECONDARYMONO 0x00000100
8895 #define MA_DSCAPS_SECONDARYSTEREO 0x00000200
8896 #define MA_DSCAPS_SECONDARY8BIT 0x00000400
8897 #define MA_DSCAPS_SECONDARY16BIT 0x00000800
8899 #define MA_DSBCAPS_PRIMARYBUFFER 0x00000001
8900 #define MA_DSBCAPS_STATIC 0x00000002
8901 #define MA_DSBCAPS_LOCHARDWARE 0x00000004
8902 #define MA_DSBCAPS_LOCSOFTWARE 0x00000008
8903 #define MA_DSBCAPS_CTRL3D 0x00000010
8904 #define MA_DSBCAPS_CTRLFREQUENCY 0x00000020
8905 #define MA_DSBCAPS_CTRLPAN 0x00000040
8906 #define MA_DSBCAPS_CTRLVOLUME 0x00000080
8907 #define MA_DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100
8908 #define MA_DSBCAPS_CTRLFX 0x00000200
8909 #define MA_DSBCAPS_STICKYFOCUS 0x00004000
8910 #define MA_DSBCAPS_GLOBALFOCUS 0x00008000
8911 #define MA_DSBCAPS_GETCURRENTPOSITION2 0x00010000
8912 #define MA_DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000
8913 #define MA_DSBCAPS_LOCDEFER 0x00040000
8914 #define MA_DSBCAPS_TRUEPLAYPOSITION 0x00080000
8916 #define MA_DSBPLAY_LOOPING 0x00000001
8917 #define MA_DSBPLAY_LOCHARDWARE 0x00000002
8918 #define MA_DSBPLAY_LOCSOFTWARE 0x00000004
8919 #define MA_DSBPLAY_TERMINATEBY_TIME 0x00000008
8920 #define MA_DSBPLAY_TERMINATEBY_DISTANCE 0x00000010
8921 #define MA_DSBPLAY_TERMINATEBY_PRIORITY 0x00000020
8923 #define MA_DSCBSTART_LOOPING 0x00000001
8929 DWORD dwBufferBytes;
8931 WAVEFORMATEX* lpwfxFormat;
8932 GUID guid3DAlgorithm;
8939 DWORD dwBufferBytes;
8941 WAVEFORMATEX* lpwfxFormat;
8950 DWORD dwMinSecondarySampleRate;
8951 DWORD dwMaxSecondarySampleRate;
8952 DWORD dwPrimaryBuffers;
8953 DWORD dwMaxHwMixingAllBuffers;
8954 DWORD dwMaxHwMixingStaticBuffers;
8955 DWORD dwMaxHwMixingStreamingBuffers;
8956 DWORD dwFreeHwMixingAllBuffers;
8957 DWORD dwFreeHwMixingStaticBuffers;
8958 DWORD dwFreeHwMixingStreamingBuffers;
8959 DWORD dwMaxHw3DAllBuffers;
8960 DWORD dwMaxHw3DStaticBuffers;
8961 DWORD dwMaxHw3DStreamingBuffers;
8962 DWORD dwFreeHw3DAllBuffers;
8963 DWORD dwFreeHw3DStaticBuffers;
8964 DWORD dwFreeHw3DStreamingBuffers;
8965 DWORD dwTotalHwMemBytes;
8966 DWORD dwFreeHwMemBytes;
8967 DWORD dwMaxContigFreeHwMemBytes;
8968 DWORD dwUnlockTransferRateHwBuffers;
8969 DWORD dwPlayCpuOverheadSwBuffers;
8978 DWORD dwBufferBytes;
8979 DWORD dwUnlockTransferRate;
8980 DWORD dwPlayCpuOverhead;
8995 DWORD dwBufferBytes;
9002 HANDLE hEventNotify;
9003 } MA_DSBPOSITIONNOTIFY;
9005 typedef struct ma_IDirectSound ma_IDirectSound;
9006 typedef struct ma_IDirectSoundBuffer ma_IDirectSoundBuffer;
9007 typedef struct ma_IDirectSoundCapture ma_IDirectSoundCapture;
9008 typedef struct ma_IDirectSoundCaptureBuffer ma_IDirectSoundCaptureBuffer;
9009 typedef struct ma_IDirectSoundNotify ma_IDirectSoundNotify;
9023 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSound* pThis,
const IID*
const riid,
void** ppObject);
9024 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSound* pThis);
9025 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSound* pThis);
9028 HRESULT (STDMETHODCALLTYPE * CreateSoundBuffer) (ma_IDirectSound* pThis,
const MA_DSBUFFERDESC* pDSBufferDesc, ma_IDirectSoundBuffer** ppDSBuffer,
void*
pUnkOuter);
9029 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps);
9030 HRESULT (STDMETHODCALLTYPE * DuplicateSoundBuffer)(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate);
9031 HRESULT (STDMETHODCALLTYPE * SetCooperativeLevel) (ma_IDirectSound* pThis, HWND hwnd,
DWORD dwLevel);
9032 HRESULT (STDMETHODCALLTYPE * Compact) (ma_IDirectSound* pThis);
9033 HRESULT (STDMETHODCALLTYPE * GetSpeakerConfig) (ma_IDirectSound* pThis,
DWORD* pSpeakerConfig);
9034 HRESULT (STDMETHODCALLTYPE * SetSpeakerConfig) (ma_IDirectSound* pThis,
DWORD dwSpeakerConfig);
9035 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSound* pThis,
const GUID* pGuidDevice);
9036 } ma_IDirectSoundVtbl;
9037 struct ma_IDirectSound
9039 ma_IDirectSoundVtbl* lpVtbl;
9041 HRESULT ma_IDirectSound_QueryInterface(ma_IDirectSound* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
9042 ULONG ma_IDirectSound_AddRef(ma_IDirectSound* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
9043 ULONG ma_IDirectSound_Release(ma_IDirectSound* pThis) {
return pThis->lpVtbl->Release(pThis); }
9044 HRESULT ma_IDirectSound_CreateSoundBuffer(ma_IDirectSound* pThis,
const MA_DSBUFFERDESC* pDSBufferDesc, ma_IDirectSoundBuffer** ppDSBuffer,
void*
pUnkOuter) {
return pThis->lpVtbl->CreateSoundBuffer(pThis, pDSBufferDesc, ppDSBuffer,
pUnkOuter); }
9045 HRESULT ma_IDirectSound_GetCaps(ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSCaps); }
9046 HRESULT ma_IDirectSound_DuplicateSoundBuffer(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate) {
return pThis->lpVtbl->DuplicateSoundBuffer(pThis, pDSBufferOriginal, ppDSBufferDuplicate); }
9047 HRESULT ma_IDirectSound_SetCooperativeLevel(ma_IDirectSound* pThis, HWND hwnd,
DWORD dwLevel) {
return pThis->lpVtbl->SetCooperativeLevel(pThis, hwnd, dwLevel); }
9048 HRESULT ma_IDirectSound_Compact(ma_IDirectSound* pThis) {
return pThis->lpVtbl->Compact(pThis); }
9049 HRESULT ma_IDirectSound_GetSpeakerConfig(ma_IDirectSound* pThis,
DWORD* pSpeakerConfig) {
return pThis->lpVtbl->GetSpeakerConfig(pThis, pSpeakerConfig); }
9050 HRESULT ma_IDirectSound_SetSpeakerConfig(ma_IDirectSound* pThis,
DWORD dwSpeakerConfig) {
return pThis->lpVtbl->SetSpeakerConfig(pThis, dwSpeakerConfig); }
9051 HRESULT ma_IDirectSound_Initialize(ma_IDirectSound* pThis,
const GUID* pGuidDevice) {
return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
9058 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundBuffer* pThis,
const IID*
const riid,
void** ppObject);
9059 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundBuffer* pThis);
9060 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundBuffer* pThis);
9063 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps);
9064 HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundBuffer* pThis,
DWORD* pCurrentPlayCursor,
DWORD* pCurrentWriteCursor);
9065 HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat,
DWORD dwSizeAllocated,
DWORD* pSizeWritten);
9066 HRESULT (STDMETHODCALLTYPE * GetVolume) (ma_IDirectSoundBuffer* pThis, LONG* pVolume);
9067 HRESULT (STDMETHODCALLTYPE * GetPan) (ma_IDirectSoundBuffer* pThis, LONG* pPan);
9068 HRESULT (STDMETHODCALLTYPE * GetFrequency) (ma_IDirectSoundBuffer* pThis,
DWORD* pFrequency);
9069 HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundBuffer* pThis,
DWORD* pStatus);
9070 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound,
const MA_DSBUFFERDESC* pDSBufferDesc);
9071 HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundBuffer* pThis,
DWORD dwOffset,
DWORD dwBytes,
void** ppAudioPtr1,
DWORD* pAudioBytes1,
void** ppAudioPtr2,
DWORD* pAudioBytes2,
DWORD dwFlags);
9072 HRESULT (STDMETHODCALLTYPE * Play) (ma_IDirectSoundBuffer* pThis,
DWORD dwReserved1,
DWORD dwPriority,
DWORD dwFlags);
9073 HRESULT (STDMETHODCALLTYPE * SetCurrentPosition)(ma_IDirectSoundBuffer* pThis,
DWORD dwNewPosition);
9074 HRESULT (STDMETHODCALLTYPE * SetFormat) (ma_IDirectSoundBuffer* pThis,
const WAVEFORMATEX* pFormat);
9075 HRESULT (STDMETHODCALLTYPE * SetVolume) (ma_IDirectSoundBuffer* pThis, LONG volume);
9076 HRESULT (STDMETHODCALLTYPE * SetPan) (ma_IDirectSoundBuffer* pThis, LONG pan);
9077 HRESULT (STDMETHODCALLTYPE * SetFrequency) (ma_IDirectSoundBuffer* pThis,
DWORD dwFrequency);
9078 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundBuffer* pThis);
9079 HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundBuffer* pThis,
void* pAudioPtr1,
DWORD dwAudioBytes1,
void* pAudioPtr2,
DWORD dwAudioBytes2);
9080 HRESULT (STDMETHODCALLTYPE * Restore) (ma_IDirectSoundBuffer* pThis);
9081 } ma_IDirectSoundBufferVtbl;
9082 struct ma_IDirectSoundBuffer
9084 ma_IDirectSoundBufferVtbl* lpVtbl;
9086 HRESULT ma_IDirectSoundBuffer_QueryInterface(ma_IDirectSoundBuffer* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
9087 ULONG ma_IDirectSoundBuffer_AddRef(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
9088 ULONG ma_IDirectSoundBuffer_Release(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->Release(pThis); }
9089 HRESULT ma_IDirectSoundBuffer_GetCaps(ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSBufferCaps); }
9090 HRESULT ma_IDirectSoundBuffer_GetCurrentPosition(ma_IDirectSoundBuffer* pThis,
DWORD* pCurrentPlayCursor,
DWORD* pCurrentWriteCursor) {
return pThis->lpVtbl->GetCurrentPosition(pThis, pCurrentPlayCursor, pCurrentWriteCursor); }
9091 HRESULT ma_IDirectSoundBuffer_GetFormat(ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat,
DWORD dwSizeAllocated,
DWORD* pSizeWritten) {
return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
9092 HRESULT ma_IDirectSoundBuffer_GetVolume(ma_IDirectSoundBuffer* pThis, LONG* pVolume) {
return pThis->lpVtbl->GetVolume(pThis, pVolume); }
9093 HRESULT ma_IDirectSoundBuffer_GetPan(ma_IDirectSoundBuffer* pThis, LONG* pPan) {
return pThis->lpVtbl->GetPan(pThis, pPan); }
9094 HRESULT ma_IDirectSoundBuffer_GetFrequency(ma_IDirectSoundBuffer* pThis,
DWORD* pFrequency) {
return pThis->lpVtbl->GetFrequency(pThis, pFrequency); }
9095 HRESULT ma_IDirectSoundBuffer_GetStatus(ma_IDirectSoundBuffer* pThis,
DWORD* pStatus) {
return pThis->lpVtbl->GetStatus(pThis, pStatus); }
9096 HRESULT ma_IDirectSoundBuffer_Initialize(ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound,
const MA_DSBUFFERDESC* pDSBufferDesc) {
return pThis->lpVtbl->Initialize(pThis, pDirectSound, pDSBufferDesc); }
9097 HRESULT ma_IDirectSoundBuffer_Lock(ma_IDirectSoundBuffer* pThis,
DWORD dwOffset,
DWORD dwBytes,
void** ppAudioPtr1,
DWORD* pAudioBytes1,
void** ppAudioPtr2,
DWORD* pAudioBytes2,
DWORD dwFlags) {
return pThis->lpVtbl->Lock(pThis, dwOffset, dwBytes, ppAudioPtr1, pAudioBytes1, ppAudioPtr2, pAudioBytes2, dwFlags); }
9098 HRESULT ma_IDirectSoundBuffer_Play(ma_IDirectSoundBuffer* pThis,
DWORD dwReserved1,
DWORD dwPriority,
DWORD dwFlags) {
return pThis->lpVtbl->Play(pThis, dwReserved1, dwPriority, dwFlags); }
9099 HRESULT ma_IDirectSoundBuffer_SetCurrentPosition(ma_IDirectSoundBuffer* pThis,
DWORD dwNewPosition) {
return pThis->lpVtbl->SetCurrentPosition(pThis, dwNewPosition); }
9100 HRESULT ma_IDirectSoundBuffer_SetFormat(ma_IDirectSoundBuffer* pThis,
const WAVEFORMATEX* pFormat) {
return pThis->lpVtbl->SetFormat(pThis, pFormat); }
9101 HRESULT ma_IDirectSoundBuffer_SetVolume(ma_IDirectSoundBuffer* pThis, LONG volume) {
return pThis->lpVtbl->SetVolume(pThis, volume); }
9102 HRESULT ma_IDirectSoundBuffer_SetPan(ma_IDirectSoundBuffer* pThis, LONG pan) {
return pThis->lpVtbl->SetPan(pThis, pan); }
9103 HRESULT ma_IDirectSoundBuffer_SetFrequency(ma_IDirectSoundBuffer* pThis,
DWORD dwFrequency) {
return pThis->lpVtbl->SetFrequency(pThis, dwFrequency); }
9104 HRESULT ma_IDirectSoundBuffer_Stop(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->Stop(pThis); }
9105 HRESULT ma_IDirectSoundBuffer_Unlock(ma_IDirectSoundBuffer* pThis,
void* pAudioPtr1,
DWORD dwAudioBytes1,
void* pAudioPtr2,
DWORD dwAudioBytes2) {
return pThis->lpVtbl->Unlock(pThis, pAudioPtr1, dwAudioBytes1, pAudioPtr2, dwAudioBytes2); }
9106 HRESULT ma_IDirectSoundBuffer_Restore(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->Restore(pThis); }
9113 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCapture* pThis,
const IID*
const riid,
void** ppObject);
9114 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCapture* pThis);
9115 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCapture* pThis);
9118 HRESULT (STDMETHODCALLTYPE * CreateCaptureBuffer)(ma_IDirectSoundCapture* pThis,
const MA_DSCBUFFERDESC* pDSCBufferDesc, ma_IDirectSoundCaptureBuffer** ppDSCBuffer,
void*
pUnkOuter);
9119 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps);
9120 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCapture* pThis,
const GUID* pGuidDevice);
9121 } ma_IDirectSoundCaptureVtbl;
9122 struct ma_IDirectSoundCapture
9124 ma_IDirectSoundCaptureVtbl* lpVtbl;
9126 HRESULT ma_IDirectSoundCapture_QueryInterface(ma_IDirectSoundCapture* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
9127 ULONG ma_IDirectSoundCapture_AddRef(ma_IDirectSoundCapture* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
9128 ULONG ma_IDirectSoundCapture_Release(ma_IDirectSoundCapture* pThis) {
return pThis->lpVtbl->Release(pThis); }
9129 HRESULT ma_IDirectSoundCapture_CreateCaptureBuffer(ma_IDirectSoundCapture* pThis,
const MA_DSCBUFFERDESC* pDSCBufferDesc, ma_IDirectSoundCaptureBuffer** ppDSCBuffer,
void*
pUnkOuter) {
return pThis->lpVtbl->CreateCaptureBuffer(pThis, pDSCBufferDesc, ppDSCBuffer,
pUnkOuter); }
9130 HRESULT ma_IDirectSoundCapture_GetCaps (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSCCaps); }
9131 HRESULT ma_IDirectSoundCapture_Initialize (ma_IDirectSoundCapture* pThis,
const GUID* pGuidDevice) {
return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
9138 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCaptureBuffer* pThis,
const IID*
const riid,
void** ppObject);
9139 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCaptureBuffer* pThis);
9140 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCaptureBuffer* pThis);
9143 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps);
9144 HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundCaptureBuffer* pThis,
DWORD* pCapturePosition,
DWORD* pReadPosition);
9145 HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat,
DWORD dwSizeAllocated,
DWORD* pSizeWritten);
9146 HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundCaptureBuffer* pThis,
DWORD* pStatus);
9147 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture,
const MA_DSCBUFFERDESC* pDSCBufferDesc);
9148 HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundCaptureBuffer* pThis,
DWORD dwOffset,
DWORD dwBytes,
void** ppAudioPtr1,
DWORD* pAudioBytes1,
void** ppAudioPtr2,
DWORD* pAudioBytes2,
DWORD dwFlags);
9149 HRESULT (STDMETHODCALLTYPE * Start) (ma_IDirectSoundCaptureBuffer* pThis,
DWORD dwFlags);
9150 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundCaptureBuffer* pThis);
9151 HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundCaptureBuffer* pThis,
void* pAudioPtr1,
DWORD dwAudioBytes1,
void* pAudioPtr2,
DWORD dwAudioBytes2);
9152 } ma_IDirectSoundCaptureBufferVtbl;
9153 struct ma_IDirectSoundCaptureBuffer
9155 ma_IDirectSoundCaptureBufferVtbl* lpVtbl;
9157 HRESULT ma_IDirectSoundCaptureBuffer_QueryInterface(ma_IDirectSoundCaptureBuffer* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
9158 ULONG ma_IDirectSoundCaptureBuffer_AddRef(ma_IDirectSoundCaptureBuffer* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
9159 ULONG ma_IDirectSoundCaptureBuffer_Release(ma_IDirectSoundCaptureBuffer* pThis) {
return pThis->lpVtbl->Release(pThis); }
9160 HRESULT ma_IDirectSoundCaptureBuffer_GetCaps(ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSCBCaps); }
9161 HRESULT ma_IDirectSoundCaptureBuffer_GetCurrentPosition(ma_IDirectSoundCaptureBuffer* pThis,
DWORD* pCapturePosition,
DWORD* pReadPosition) {
return pThis->lpVtbl->GetCurrentPosition(pThis, pCapturePosition, pReadPosition); }
9162 HRESULT ma_IDirectSoundCaptureBuffer_GetFormat(ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat,
DWORD dwSizeAllocated,
DWORD* pSizeWritten) {
return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
9163 HRESULT ma_IDirectSoundCaptureBuffer_GetStatus(ma_IDirectSoundCaptureBuffer* pThis,
DWORD* pStatus) {
return pThis->lpVtbl->GetStatus(pThis, pStatus); }
9164 HRESULT ma_IDirectSoundCaptureBuffer_Initialize(ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture,
const MA_DSCBUFFERDESC* pDSCBufferDesc) {
return pThis->lpVtbl->Initialize(pThis, pDirectSoundCapture, pDSCBufferDesc); }
9165 HRESULT ma_IDirectSoundCaptureBuffer_Lock(ma_IDirectSoundCaptureBuffer* pThis,
DWORD dwOffset,
DWORD dwBytes,
void** ppAudioPtr1,
DWORD* pAudioBytes1,
void** ppAudioPtr2,
DWORD* pAudioBytes2,
DWORD dwFlags) {
return pThis->lpVtbl->Lock(pThis, dwOffset, dwBytes, ppAudioPtr1, pAudioBytes1, ppAudioPtr2, pAudioBytes2, dwFlags); }
9166 HRESULT ma_IDirectSoundCaptureBuffer_Start(ma_IDirectSoundCaptureBuffer* pThis,
DWORD dwFlags) {
return pThis->lpVtbl->Start(pThis, dwFlags); }
9167 HRESULT ma_IDirectSoundCaptureBuffer_Stop(ma_IDirectSoundCaptureBuffer* pThis) {
return pThis->lpVtbl->Stop(pThis); }
9168 HRESULT ma_IDirectSoundCaptureBuffer_Unlock(ma_IDirectSoundCaptureBuffer* pThis,
void* pAudioPtr1,
DWORD dwAudioBytes1,
void* pAudioPtr2,
DWORD dwAudioBytes2) {
return pThis->lpVtbl->Unlock(pThis, pAudioPtr1, dwAudioBytes1, pAudioPtr2, dwAudioBytes2); }
9175 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundNotify* pThis,
const IID*
const riid,
void** ppObject);
9176 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundNotify* pThis);
9177 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundNotify* pThis);
9180 HRESULT (STDMETHODCALLTYPE * SetNotificationPositions)(ma_IDirectSoundNotify* pThis,
DWORD dwPositionNotifies,
const MA_DSBPOSITIONNOTIFY* pPositionNotifies);
9181 } ma_IDirectSoundNotifyVtbl;
9182 struct ma_IDirectSoundNotify
9184 ma_IDirectSoundNotifyVtbl* lpVtbl;
9186 HRESULT ma_IDirectSoundNotify_QueryInterface(ma_IDirectSoundNotify* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
9187 ULONG ma_IDirectSoundNotify_AddRef(ma_IDirectSoundNotify* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
9188 ULONG ma_IDirectSoundNotify_Release(ma_IDirectSoundNotify* pThis) {
return pThis->lpVtbl->Release(pThis); }
9189 HRESULT ma_IDirectSoundNotify_SetNotificationPositions(ma_IDirectSoundNotify* pThis,
DWORD dwPositionNotifies,
const MA_DSBPOSITIONNOTIFY* pPositionNotifies) {
return pThis->lpVtbl->SetNotificationPositions(pThis, dwPositionNotifies, pPositionNotifies); }
9192 typedef BOOL (CALLBACK * ma_DSEnumCallbackAProc) (LPGUID pDeviceGUID, LPCSTR pDeviceDescription, LPCSTR pModule, LPVOID pContext);
9193 typedef HRESULT (WINAPI * ma_DirectSoundCreateProc) (
const GUID* pcGuidDevice, ma_IDirectSound** ppDS8, LPUNKNOWN
pUnkOuter);
9194 typedef HRESULT (WINAPI * ma_DirectSoundEnumerateAProc) (ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
9195 typedef HRESULT (WINAPI * ma_DirectSoundCaptureCreateProc) (
const GUID* pcGuidDevice, ma_IDirectSoundCapture** ppDSC8, LPUNKNOWN
pUnkOuter);
9196 typedef HRESULT (WINAPI * ma_DirectSoundCaptureEnumerateAProc)(ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
9203 void ma_get_channels_from_speaker_config__dsound(
DWORD speakerConfig, WORD* pChannelsOut,
DWORD* pChannelMapOut)
9209 if (pChannelsOut !=
NULL) {
9214 if (pChannelMapOut !=
NULL) {
9215 channelMap = *pChannelMapOut;
9222 switch ((BYTE)(speakerConfig)) {
9223 case 1 :
channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
break;
9224 case 2 :
channels = 1; channelMap = SPEAKER_FRONT_CENTER;
break;
9225 case 3 :
channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
break;
9226 case 4 :
channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
break;
9227 case 5 :
channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER;
break;
9228 case 6 :
channels = 6; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
break;
9229 case 7 :
channels = 8; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER;
break;
9230 case 8 :
channels = 8; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
break;
9231 case 9 :
channels = 6; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
break;
9235 if (pChannelsOut !=
NULL) {
9239 if (pChannelMapOut !=
NULL) {
9240 *pChannelMapOut = channelMap;
9247 ma_IDirectSound* pDirectSound;
9250 ma_assert(pContext !=
NULL);
9251 ma_assert(ppDirectSound !=
NULL);
9253 *ppDirectSound =
NULL;
9254 pDirectSound =
NULL;
9256 if (FAILED(((ma_DirectSoundCreateProc)pContext->
dsound.DirectSoundCreate)((pDeviceID ==
NULL) ?
NULL : (
const GUID*)pDeviceID->
dsound, &pDirectSound,
NULL))) {
9261 hWnd = ((MA_PFN_GetForegroundWindow)pContext->
win32.GetForegroundWindow)();
9263 hWnd = ((MA_PFN_GetDesktopWindow)pContext->
win32.GetDesktopWindow)();
9265 if (FAILED(ma_IDirectSound_SetCooperativeLevel(pDirectSound, hWnd, (shareMode ==
ma_share_mode_exclusive) ? MA_DSSCL_EXCLUSIVE : MA_DSSCL_PRIORITY))) {
9269 *ppDirectSound = pDirectSound;
9275 ma_IDirectSoundCapture* pDirectSoundCapture;
9277 ma_assert(pContext !=
NULL);
9278 ma_assert(ppDirectSoundCapture !=
NULL);
9285 *ppDirectSoundCapture =
NULL;
9286 pDirectSoundCapture =
NULL;
9288 if (FAILED(((ma_DirectSoundCaptureCreateProc)pContext->
dsound.DirectSoundCaptureCreate)((pDeviceID ==
NULL) ?
NULL : (
const GUID*)pDeviceID->
dsound, &pDirectSoundCapture,
NULL))) {
9292 *ppDirectSoundCapture = pDirectSoundCapture;
9296 ma_result ma_context_get_format_info_for_IDirectSoundCapture__dsound(
ma_context* pContext, ma_IDirectSoundCapture* pDirectSoundCapture, WORD* pChannels, WORD* pBitsPerSample,
DWORD* pSampleRate)
9302 ma_assert(pContext !=
NULL);
9303 ma_assert(pDirectSoundCapture !=
NULL);
9308 if (pBitsPerSample) {
9309 *pBitsPerSample = 0;
9315 ma_zero_object(&caps);
9316 caps.dwSize =
sizeof(caps);
9317 if (FAILED(ma_IDirectSoundCapture_GetCaps(pDirectSoundCapture, &caps))) {
9322 *pChannels = (WORD)caps.dwChannels;
9329 if (caps.dwChannels == 1) {
9330 if ((caps.dwFormats & WAVE_FORMAT_48M16) != 0) {
9332 }
else if ((caps.dwFormats & WAVE_FORMAT_44M16) != 0) {
9334 }
else if ((caps.dwFormats & WAVE_FORMAT_2M16) != 0) {
9336 }
else if ((caps.dwFormats & WAVE_FORMAT_1M16) != 0) {
9338 }
else if ((caps.dwFormats & WAVE_FORMAT_96M16) != 0) {
9342 if ((caps.dwFormats & WAVE_FORMAT_48M08) != 0) {
9344 }
else if ((caps.dwFormats & WAVE_FORMAT_44M08) != 0) {
9346 }
else if ((caps.dwFormats & WAVE_FORMAT_2M08) != 0) {
9348 }
else if ((caps.dwFormats & WAVE_FORMAT_1M08) != 0) {
9350 }
else if ((caps.dwFormats & WAVE_FORMAT_96M08) != 0) {
9356 }
else if (caps.dwChannels == 2) {
9357 if ((caps.dwFormats & WAVE_FORMAT_48S16) != 0) {
9359 }
else if ((caps.dwFormats & WAVE_FORMAT_44S16) != 0) {
9361 }
else if ((caps.dwFormats & WAVE_FORMAT_2S16) != 0) {
9363 }
else if ((caps.dwFormats & WAVE_FORMAT_1S16) != 0) {
9365 }
else if ((caps.dwFormats & WAVE_FORMAT_96S16) != 0) {
9369 if ((caps.dwFormats & WAVE_FORMAT_48S08) != 0) {
9371 }
else if ((caps.dwFormats & WAVE_FORMAT_44S08) != 0) {
9373 }
else if ((caps.dwFormats & WAVE_FORMAT_2S08) != 0) {
9375 }
else if ((caps.dwFormats & WAVE_FORMAT_1S08) != 0) {
9377 }
else if ((caps.dwFormats & WAVE_FORMAT_96S08) != 0) {
9385 if (pBitsPerSample) {
9386 *pBitsPerSample = bitsPerSample;
9389 *pSampleRate = sampleRate;
9397 ma_assert(pContext !=
NULL);
9398 ma_assert(pID0 !=
NULL);
9399 ma_assert(pID1 !=
NULL);
9413 } ma_context_enumerate_devices_callback_data__dsound;
9415 BOOL CALLBACK ma_context_enumerate_devices_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
9417 ma_context_enumerate_devices_callback_data__dsound* pData = (ma_context_enumerate_devices_callback_data__dsound*)lpContext;
9420 ma_zero_object(&deviceInfo);
9423 if (lpGuid !=
NULL) {
9424 ma_copy_memory(deviceInfo.
id.
dsound, lpGuid, 16);
9426 ma_zero_memory(deviceInfo.
id.
dsound, 16);
9430 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), lpcstrDescription, (
size_t)-1);
9434 ma_assert(pData !=
NULL);
9435 pData->terminated = !pData->callback(pData->pContext, pData->deviceType, &deviceInfo, pData->pUserData);
9436 if (pData->terminated) {
9447 ma_context_enumerate_devices_callback_data__dsound data;
9449 ma_assert(pContext !=
NULL);
9450 ma_assert(callback !=
NULL);
9452 data.pContext = pContext;
9453 data.callback = callback;
9458 if (!data.terminated) {
9460 ((ma_DirectSoundEnumerateAProc)pContext->
dsound.DirectSoundEnumerateA)(ma_context_enumerate_devices_callback__dsound, &data);
9464 if (!data.terminated) {
9466 ((ma_DirectSoundCaptureEnumerateAProc)pContext->
dsound.DirectSoundCaptureEnumerateA)(ma_context_enumerate_devices_callback__dsound, &data);
9478 } ma_context_get_device_info_callback_data__dsound;
9480 BOOL CALLBACK ma_context_get_device_info_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
9482 ma_context_get_device_info_callback_data__dsound* pData = (ma_context_get_device_info_callback_data__dsound*)lpContext;
9483 ma_assert(pData !=
NULL);
9485 if ((pData->pDeviceID ==
NULL || ma_is_guid_equal(pData->pDeviceID->dsound, &MA_GUID_NULL)) && (lpGuid ==
NULL || ma_is_guid_equal(lpGuid, &MA_GUID_NULL))) {
9487 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), lpcstrDescription, (
size_t)-1);
9492 if (lpGuid !=
NULL) {
9493 if (memcmp(pData->pDeviceID->dsound, lpGuid,
sizeof(pData->pDeviceID->dsound)) == 0) {
9494 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), lpcstrDescription, (
size_t)-1);
9512 if (pDeviceID !=
NULL) {
9513 ma_context_get_device_info_callback_data__dsound data;
9519 data.pDeviceID = pDeviceID;
9520 data.pDeviceInfo = pDeviceInfo;
9523 ((ma_DirectSoundEnumerateAProc)pContext->
dsound.DirectSoundEnumerateA)(ma_context_get_device_info_callback__dsound, &data);
9525 ((ma_DirectSoundCaptureEnumerateAProc)pContext->
dsound.DirectSoundCaptureEnumerateA)(ma_context_get_device_info_callback__dsound, &data);
9535 ma_zero_memory(pDeviceInfo->
id.
dsound, 16);
9539 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
9541 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
9548 ma_IDirectSound* pDirectSound;
9553 result = ma_context_create_IDirectSound__dsound(pContext, shareMode, pDeviceID, &pDirectSound);
9558 ma_zero_object(&caps);
9559 caps.dwSize =
sizeof(caps);
9560 if (FAILED(ma_IDirectSound_GetCaps(pDirectSound, &caps))) {
9564 if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
9569 DWORD speakerConfig;
9570 if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig(pDirectSound, &speakerConfig))) {
9571 ma_get_channels_from_speaker_config__dsound(speakerConfig, &
channels,
NULL);
9583 if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
9605 for (iFormat = 0; iFormat < pDeviceInfo->
formatCount; ++iFormat) {
9609 ma_IDirectSound_Release(pDirectSound);
9616 ma_IDirectSoundCapture* pDirectSoundCapture;
9622 result = ma_context_create_IDirectSoundCapture__dsound(pContext, shareMode, pDeviceID, &pDirectSoundCapture);
9627 result = ma_context_get_format_info_for_IDirectSoundCapture__dsound(pContext, pDirectSoundCapture, &
channels, &bitsPerSample, &sampleRate);
9629 ma_IDirectSoundCapture_Release(pDirectSoundCapture);
9638 if (bitsPerSample == 8) {
9640 }
else if (bitsPerSample == 16) {
9642 }
else if (bitsPerSample == 24) {
9644 }
else if (bitsPerSample == 32) {
9647 ma_IDirectSoundCapture_Release(pDirectSoundCapture);
9651 ma_IDirectSoundCapture_Release(pDirectSoundCapture);
9663 } ma_device_enum_data__dsound;
9665 BOOL CALLBACK ma_enum_devices_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
9667 ma_device_enum_data__dsound* pData = (ma_device_enum_data__dsound*)lpContext;
9668 ma_assert(pData !=
NULL);
9670 if (pData->pInfo !=
NULL) {
9671 if (pData->infoCount > 0) {
9672 ma_zero_object(pData->pInfo);
9673 ma_strncpy_s(pData->pInfo->name,
sizeof(pData->pInfo->name), lpcstrDescription, (
size_t)-1);
9675 if (lpGuid !=
NULL) {
9676 ma_copy_memory(pData->pInfo->id.dsound, lpGuid, 16);
9678 ma_zero_memory(pData->pInfo->id.dsound, 16);
9682 pData->infoCount -= 1;
9683 pData->deviceCount += 1;
9686 pData->deviceCount += 1;
9693 void ma_device_uninit__dsound(
ma_device* pDevice)
9695 ma_assert(pDevice !=
NULL);
9697 if (pDevice->dsound.pCaptureBuffer !=
NULL) {
9698 ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
9700 if (pDevice->dsound.pCapture !=
NULL) {
9701 ma_IDirectSoundCapture_Release((ma_IDirectSoundCapture*)pDevice->dsound.pCapture);
9704 if (pDevice->dsound.pPlaybackBuffer !=
NULL) {
9705 ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer);
9707 if (pDevice->dsound.pPlaybackPrimaryBuffer !=
NULL) {
9708 ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer);
9710 if (pDevice->dsound.pPlayback !=
NULL) {
9711 ma_IDirectSound_Release((ma_IDirectSound*)pDevice->dsound.pPlayback);
9727 subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
9732 subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
9739 ma_zero_object(pWF);
9740 pWF->Format.cbSize =
sizeof(*pWF);
9741 pWF->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
9742 pWF->Format.nChannels = (WORD)
channels;
9743 pWF->Format.nSamplesPerSec = (
DWORD)sampleRate;
9745 pWF->Format.nBlockAlign = (pWF->Format.nChannels * pWF->Format.wBitsPerSample) / 8;
9746 pWF->Format.nAvgBytesPerSec = pWF->Format.nBlockAlign * pWF->Format.nSamplesPerSec;
9747 pWF->Samples.wValidBitsPerSample = pWF->Format.wBitsPerSample;
9748 pWF->dwChannelMask = ma_channel_map_to_channel_mask__win32(pChannelMap,
channels);
9749 pWF->SubFormat = subformat;
9759 ma_assert(pDevice !=
NULL);
9760 ma_zero_object(&pDevice->dsound);
9763 if (bufferSizeInMilliseconds == 0) {
9768 if (pDevice->usingDefaultBufferSize) {
9770 bufferSizeInMilliseconds = 20 * pConfig->
periods;
9772 bufferSizeInMilliseconds = 200 * pConfig->
periods;
9777 if ((bufferSizeInMilliseconds/pConfig->
periods) < 20) {
9778 bufferSizeInMilliseconds = pConfig->
periods * 20;
9787 WAVEFORMATEXTENSIBLE wf;
9788 MA_DSCBUFFERDESC descDS;
9791 WAVEFORMATEXTENSIBLE* pActualFormat;
9800 ma_device_uninit__dsound(pDevice);
9804 result = ma_context_get_format_info_for_IDirectSoundCapture__dsound(pContext, (ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &wf.Format.nChannels, &wf.Format.wBitsPerSample, &wf.Format.nSamplesPerSec);
9806 ma_device_uninit__dsound(pDevice);
9810 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
9811 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
9812 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
9813 wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
9818 ma_zero_object(&descDS);
9819 descDS.dwSize =
sizeof(descDS);
9821 descDS.dwBufferBytes = bufferSizeInFrames *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, wf.Format.nChannels);
9822 descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
9823 if (FAILED(ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer,
NULL))) {
9824 ma_device_uninit__dsound(pDevice);
9829 pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
9830 if (FAILED(ma_IDirectSoundCaptureBuffer_GetFormat((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, (WAVEFORMATEX*)pActualFormat,
sizeof(rawdata),
NULL))) {
9831 ma_device_uninit__dsound(pDevice);
9835 pDevice->capture.internalFormat = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
9836 pDevice->capture.internalChannels = pActualFormat->Format.nChannels;
9837 pDevice->capture.internalSampleRate = pActualFormat->Format.nSamplesPerSec;
9840 if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
9841 ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDevice->capture.internalChannels, pDevice->capture.internalChannelMap);
9843 ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDevice->capture.internalChannels, pDevice->capture.internalChannelMap);
9850 if (bufferSizeInFrames != (descDS.dwBufferBytes /
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels))) {
9851 descDS.dwBufferBytes = bufferSizeInFrames *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, wf.Format.nChannels);
9852 ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
9854 if (FAILED(ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer,
NULL))) {
9855 ma_device_uninit__dsound(pDevice);
9861 pDevice->capture.internalBufferSizeInFrames = bufferSizeInFrames;
9862 pDevice->capture.internalPeriods = pConfig->
periods;
9866 WAVEFORMATEXTENSIBLE wf;
9867 MA_DSBUFFERDESC descDSPrimary;
9870 WAVEFORMATEXTENSIBLE* pActualFormat;
9872 MA_DSBUFFERDESC descDS;
9881 ma_device_uninit__dsound(pDevice);
9885 ma_zero_object(&descDSPrimary);
9886 descDSPrimary.dwSize =
sizeof(MA_DSBUFFERDESC);
9887 descDSPrimary.dwFlags = MA_DSBCAPS_PRIMARYBUFFER | MA_DSBCAPS_CTRLVOLUME;
9888 if (FAILED(ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDSPrimary, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackPrimaryBuffer,
NULL))) {
9889 ma_device_uninit__dsound(pDevice);
9895 ma_zero_object(&caps);
9896 caps.dwSize =
sizeof(caps);
9897 if (FAILED(ma_IDirectSound_GetCaps((ma_IDirectSound*)pDevice->dsound.pPlayback, &caps))) {
9898 ma_device_uninit__dsound(pDevice);
9902 if (pDevice->playback.usingDefaultChannels) {
9903 if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
9904 DWORD speakerConfig;
9907 wf.Format.nChannels = 2;
9910 if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig((ma_IDirectSound*)pDevice->dsound.pPlayback, &speakerConfig))) {
9911 ma_get_channels_from_speaker_config__dsound(speakerConfig, &wf.Format.nChannels, &wf.dwChannelMask);
9915 wf.Format.nChannels = 1;
9919 if (pDevice->usingDefaultSampleRate) {
9921 if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
9922 wf.Format.nSamplesPerSec = ma_get_best_sample_rate_within_range(caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate);
9924 wf.Format.nSamplesPerSec = caps.dwMaxSecondarySampleRate;
9928 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
9929 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
9938 if (FAILED(ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)&wf))) {
9939 ma_device_uninit__dsound(pDevice);
9944 pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
9945 if (FAILED(ma_IDirectSoundBuffer_GetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)pActualFormat,
sizeof(rawdata),
NULL))) {
9946 ma_device_uninit__dsound(pDevice);
9950 pDevice->playback.internalFormat = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
9951 pDevice->playback.internalChannels = pActualFormat->Format.nChannels;
9952 pDevice->playback.internalSampleRate = pActualFormat->Format.nSamplesPerSec;
9955 if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
9956 ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDevice->playback.internalChannels, pDevice->playback.internalChannelMap);
9958 ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDevice->playback.internalChannels, pDevice->playback.internalChannelMap);
9979 ma_zero_object(&descDS);
9980 descDS.dwSize =
sizeof(descDS);
9981 descDS.dwFlags = MA_DSBCAPS_CTRLPOSITIONNOTIFY | MA_DSBCAPS_GLOBALFOCUS | MA_DSBCAPS_GETCURRENTPOSITION2;
9982 descDS.dwBufferBytes = bufferSizeInFrames *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
9983 descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
9984 if (FAILED(ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDS, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackBuffer,
NULL))) {
9985 ma_device_uninit__dsound(pDevice);
9990 pDevice->playback.internalBufferSizeInFrames = bufferSizeInFrames;
9991 pDevice->playback.internalPeriods = pConfig->
periods;
10005 DWORD lockOffsetInBytesCapture;
10006 DWORD lockSizeInBytesCapture;
10007 DWORD mappedSizeInBytesCapture;
10008 void* pMappedBufferCapture;
10009 DWORD lockOffsetInBytesPlayback;
10010 DWORD lockSizeInBytesPlayback;
10011 DWORD mappedSizeInBytesPlayback;
10012 void* pMappedBufferPlayback;
10013 DWORD prevReadCursorInBytesCapture = 0;
10014 DWORD prevPlayCursorInBytesPlayback = 0;
10015 ma_bool32 physicalPlayCursorLoopFlagPlayback = 0;
10016 DWORD virtualWriteCursorInBytesPlayback = 0;
10017 ma_bool32 virtualWriteCursorLoopFlagPlayback = 0;
10019 ma_uint32 framesWrittenToPlaybackDevice = 0;
10022 ma_assert(pDevice !=
NULL);
10026 if (FAILED(ma_IDirectSoundCaptureBuffer_Start((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, MA_DSCBSTART_LOOPING))) {
10031 while (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
10032 switch (pDevice->type)
10036 DWORD physicalCaptureCursorInBytes;
10037 DWORD physicalReadCursorInBytes;
10038 if (FAILED(ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes))) {
10043 if (physicalReadCursorInBytes == prevReadCursorInBytesCapture) {
10044 ma_sleep(waitTimeInMilliseconds);
10052 if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
10054 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
10055 lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
10061 if (prevReadCursorInBytesCapture < pDevice->capture.internalBufferSizeInFrames*bpfCapture) {
10063 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
10064 lockSizeInBytesCapture = (pDevice->capture.internalBufferSizeInFrames*bpfCapture) - prevReadCursorInBytesCapture;
10067 lockOffsetInBytesCapture = 0;
10068 lockSizeInBytesCapture = physicalReadCursorInBytes;
10072 if (lockSizeInBytesCapture == 0) {
10073 ma_sleep(waitTimeInMilliseconds);
10077 hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedBufferCapture, &mappedSizeInBytesCapture,
NULL,
NULL, 0);
10084 pDevice->capture._dspFrameCount = mappedSizeInBytesCapture / bpfCapture;
10085 pDevice->capture._dspFrames = (
const ma_uint8*)pMappedBufferCapture;
10087 ma_uint8 inputFramesInExternalFormat[4096];
10088 ma_uint32 inputFramesInExternalFormatCap =
sizeof(inputFramesInExternalFormat) /
ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
10089 ma_uint32 inputFramesInExternalFormatCount;
10090 ma_uint8 outputFramesInExternalFormat[4096];
10091 ma_uint32 outputFramesInExternalFormatCap =
sizeof(outputFramesInExternalFormat) /
ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
10093 inputFramesInExternalFormatCount = (
ma_uint32)
ma_pcm_converter_read(&pDevice->capture.converter, inputFramesInExternalFormat, ma_min(inputFramesInExternalFormatCap, outputFramesInExternalFormatCap));
10094 if (inputFramesInExternalFormatCount == 0) {
10098 pDevice->onData(pDevice, outputFramesInExternalFormat, inputFramesInExternalFormat, inputFramesInExternalFormatCount);
10101 pDevice->playback._dspFrameCount = inputFramesInExternalFormatCount;
10102 pDevice->playback._dspFrames = (
const ma_uint8*)outputFramesInExternalFormat;
10105 DWORD physicalPlayCursorInBytes;
10106 DWORD physicalWriteCursorInBytes;
10107 DWORD availableBytesPlayback;
10108 DWORD silentPaddingInBytes = 0;
10111 if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
10115 if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
10116 physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
10118 prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
10121 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
10123 if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
10124 availableBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
10125 availableBytesPlayback += physicalPlayCursorInBytes;
10128 #ifdef MA_DEBUG_OUTPUT
10129 printf(
"[DirectSound] (Duplex/Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
10131 availableBytesPlayback = 0;
10135 if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
10136 availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
10139 #ifdef MA_DEBUG_OUTPUT
10140 printf(
"[DirectSound] (Duplex/Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
10142 availableBytesPlayback = 0;
10146 #ifdef MA_DEBUG_OUTPUT
10151 if (availableBytesPlayback == 0) {
10153 if (!isPlaybackDeviceStarted) {
10154 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
10155 ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
10158 isPlaybackDeviceStarted =
MA_TRUE;
10160 ma_sleep(waitTimeInMilliseconds);
10167 lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
10168 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
10170 lockSizeInBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
10173 lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
10176 hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedBufferPlayback, &mappedSizeInBytesPlayback,
NULL,
NULL, 0);
10186 if (isPlaybackDeviceStarted) {
10187 DWORD bytesQueuedForPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - availableBytesPlayback;
10188 if (bytesQueuedForPlayback < ((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*bpfPlayback)) {
10189 silentPaddingInBytes = ((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*2*bpfPlayback) - bytesQueuedForPlayback;
10190 if (silentPaddingInBytes > lockSizeInBytesPlayback) {
10191 silentPaddingInBytes = lockSizeInBytesPlayback;
10194 #ifdef MA_DEBUG_OUTPUT
10195 printf(
"[DirectSound] (Duplex/Playback) Playback buffer starved. availableBytesPlayback=%d, silentPaddingInBytes=%d\n", availableBytesPlayback, silentPaddingInBytes);
10201 if (silentPaddingInBytes > 0) {
10202 ma_zero_memory(pMappedBufferPlayback, silentPaddingInBytes);
10203 framesWrittenThisIteration = silentPaddingInBytes/bpfPlayback;
10205 framesWrittenThisIteration = (
ma_uint32)
ma_pcm_converter_read(&pDevice->playback.converter, pMappedBufferPlayback, mappedSizeInBytesPlayback/bpfPlayback);
10209 hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedBufferPlayback, framesWrittenThisIteration*bpfPlayback,
NULL, 0);
10215 virtualWriteCursorInBytesPlayback += framesWrittenThisIteration*bpfPlayback;
10216 if ((virtualWriteCursorInBytesPlayback/bpfPlayback) == pDevice->playback.internalBufferSizeInFrames) {
10217 virtualWriteCursorInBytesPlayback = 0;
10218 virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
10225 framesWrittenToPlaybackDevice += framesWrittenThisIteration;
10226 if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= ((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*2)) {
10227 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
10228 ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
10231 isPlaybackDeviceStarted =
MA_TRUE;
10234 if (framesWrittenThisIteration < mappedSizeInBytesPlayback/bpfPlayback) {
10239 if (inputFramesInExternalFormatCount < inputFramesInExternalFormatCap) {
10246 hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedBufferCapture, mappedSizeInBytesCapture,
NULL, 0);
10250 prevReadCursorInBytesCapture = (lockOffsetInBytesCapture + mappedSizeInBytesCapture);
10257 DWORD physicalCaptureCursorInBytes;
10258 DWORD physicalReadCursorInBytes;
10259 if (FAILED(ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes))) {
10264 if (prevReadCursorInBytesCapture == physicalReadCursorInBytes) {
10265 ma_sleep(waitTimeInMilliseconds);
10270 if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
10272 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
10273 lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
10279 if (prevReadCursorInBytesCapture < pDevice->capture.internalBufferSizeInFrames*bpfCapture) {
10281 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
10282 lockSizeInBytesCapture = (pDevice->capture.internalBufferSizeInFrames*bpfCapture) - prevReadCursorInBytesCapture;
10285 lockOffsetInBytesCapture = 0;
10286 lockSizeInBytesCapture = physicalReadCursorInBytes;
10290 #ifdef MA_DEBUG_OUTPUT
10295 if (lockSizeInBytesCapture < (pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods)) {
10296 ma_sleep(waitTimeInMilliseconds);
10300 hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedBufferCapture, &mappedSizeInBytesCapture,
NULL,
NULL, 0);
10305 #ifdef MA_DEBUG_OUTPUT
10306 if (lockSizeInBytesCapture != mappedSizeInBytesCapture) {
10307 printf(
"[DirectSound] (Capture) lockSizeInBytesCapture=%d != mappedSizeInBytesCapture=%d\n", lockSizeInBytesCapture, mappedSizeInBytesCapture);
10311 ma_device__send_frames_to_client(pDevice, mappedSizeInBytesCapture/bpfCapture, pMappedBufferCapture);
10313 hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedBufferCapture, mappedSizeInBytesCapture,
NULL, 0);
10317 prevReadCursorInBytesCapture = lockOffsetInBytesCapture + mappedSizeInBytesCapture;
10319 if (prevReadCursorInBytesCapture == (pDevice->capture.internalBufferSizeInFrames*bpfCapture)) {
10320 prevReadCursorInBytesCapture = 0;
10328 DWORD availableBytesPlayback;
10329 DWORD physicalPlayCursorInBytes;
10330 DWORD physicalWriteCursorInBytes;
10331 if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
10335 if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
10336 physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
10338 prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
10341 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
10343 if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
10344 availableBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
10345 availableBytesPlayback += physicalPlayCursorInBytes;
10348 #ifdef MA_DEBUG_OUTPUT
10349 printf(
"[DirectSound] (Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
10351 availableBytesPlayback = 0;
10355 if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
10356 availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
10359 #ifdef MA_DEBUG_OUTPUT
10360 printf(
"[DirectSound] (Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
10362 availableBytesPlayback = 0;
10366 #ifdef MA_DEBUG_OUTPUT
10371 if (availableBytesPlayback < (pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)) {
10373 if (availableBytesPlayback == 0 && !isPlaybackDeviceStarted) {
10374 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
10377 isPlaybackDeviceStarted =
MA_TRUE;
10379 ma_sleep(waitTimeInMilliseconds);
10385 lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
10386 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
10388 lockSizeInBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
10391 lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
10394 hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedBufferPlayback, &mappedSizeInBytesPlayback,
NULL,
NULL, 0);
10401 ma_device__read_frames_from_client(pDevice, (mappedSizeInBytesPlayback/bpfPlayback), pMappedBufferPlayback);
10403 hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedBufferPlayback, mappedSizeInBytesPlayback,
NULL, 0);
10409 virtualWriteCursorInBytesPlayback += mappedSizeInBytesPlayback;
10410 if (virtualWriteCursorInBytesPlayback == pDevice->playback.internalBufferSizeInFrames*bpfPlayback) {
10411 virtualWriteCursorInBytesPlayback = 0;
10412 virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
10419 framesWrittenToPlaybackDevice += mappedSizeInBytesPlayback/bpfPlayback;
10420 if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= (pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)) {
10421 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
10424 isPlaybackDeviceStarted =
MA_TRUE;
10439 if (FAILED(ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer))) {
10446 if (isPlaybackDeviceStarted) {
10448 DWORD availableBytesPlayback = 0;
10449 DWORD physicalPlayCursorInBytes;
10450 DWORD physicalWriteCursorInBytes;
10451 if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
10455 if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
10456 physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
10458 prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
10460 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
10462 if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
10463 availableBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
10464 availableBytesPlayback += physicalPlayCursorInBytes;
10470 if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
10471 availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
10477 if (availableBytesPlayback >= (pDevice->playback.internalBufferSizeInFrames*bpfPlayback)) {
10481 ma_sleep(waitTimeInMilliseconds);
10485 if (FAILED(ma_IDirectSoundBuffer_Stop((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer))) {
10489 ma_IDirectSoundBuffer_SetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0);
10497 ma_assert(pContext !=
NULL);
10500 ma_dlclose(pContext, pContext->
dsound.hDSoundDLL);
10507 ma_assert(pContext !=
NULL);
10511 pContext->
dsound.hDSoundDLL = ma_dlopen(pContext,
"dsound.dll");
10516 pContext->
dsound.DirectSoundCreate = ma_dlsym(pContext, pContext->
dsound.hDSoundDLL,
"DirectSoundCreate");
10517 pContext->
dsound.DirectSoundEnumerateA = ma_dlsym(pContext, pContext->
dsound.hDSoundDLL,
"DirectSoundEnumerateA");
10518 pContext->
dsound.DirectSoundCaptureCreate = ma_dlsym(pContext, pContext->
dsound.hDSoundDLL,
"DirectSoundCaptureCreate");
10519 pContext->
dsound.DirectSoundCaptureEnumerateA = ma_dlsym(pContext, pContext->
dsound.hDSoundDLL,
"DirectSoundCaptureEnumerateA");
10521 pContext->
onUninit = ma_context_uninit__dsound;
10523 pContext->
onEnumDevices = ma_context_enumerate_devices__dsound;
10544 #ifdef MA_HAS_WINMM
10555 MMVERSION vDriverVersion;
10556 CHAR szPname[MAXPNAMELEN];
10561 GUID ManufacturerGuid;
10564 } MA_WAVEOUTCAPS2A;
10569 MMVERSION vDriverVersion;
10570 CHAR szPname[MAXPNAMELEN];
10574 GUID ManufacturerGuid;
10579 typedef UINT (WINAPI * MA_PFN_waveOutGetNumDevs)(
void);
10580 typedef MMRESULT (WINAPI * MA_PFN_waveOutGetDevCapsA)(
ma_uintptr uDeviceID, LPWAVEOUTCAPSA pwoc,
UINT cbwoc);
10581 typedef MMRESULT (WINAPI * MA_PFN_waveOutOpen)(LPHWAVEOUT phwo,
UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance,
DWORD fdwOpen);
10582 typedef MMRESULT (WINAPI * MA_PFN_waveOutClose)(HWAVEOUT hwo);
10583 typedef MMRESULT (WINAPI * MA_PFN_waveOutPrepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh,
UINT cbwh);
10584 typedef MMRESULT (WINAPI * MA_PFN_waveOutUnprepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh,
UINT cbwh);
10585 typedef MMRESULT (WINAPI * MA_PFN_waveOutWrite)(HWAVEOUT hwo, LPWAVEHDR pwh,
UINT cbwh);
10586 typedef MMRESULT (WINAPI * MA_PFN_waveOutReset)(HWAVEOUT hwo);
10587 typedef UINT (WINAPI * MA_PFN_waveInGetNumDevs)(
void);
10588 typedef MMRESULT (WINAPI * MA_PFN_waveInGetDevCapsA)(
ma_uintptr uDeviceID, LPWAVEINCAPSA pwic,
UINT cbwic);
10589 typedef MMRESULT (WINAPI * MA_PFN_waveInOpen)(LPHWAVEIN phwi,
UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance,
DWORD fdwOpen);
10590 typedef MMRESULT (WINAPI * MA_PFN_waveInClose)(HWAVEIN hwi);
10591 typedef MMRESULT (WINAPI * MA_PFN_waveInPrepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh,
UINT cbwh);
10592 typedef MMRESULT (WINAPI * MA_PFN_waveInUnprepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh,
UINT cbwh);
10593 typedef MMRESULT (WINAPI * MA_PFN_waveInAddBuffer)(HWAVEIN hwi, LPWAVEHDR pwh,
UINT cbwh);
10594 typedef MMRESULT (WINAPI * MA_PFN_waveInStart)(HWAVEIN hwi);
10595 typedef MMRESULT (WINAPI * MA_PFN_waveInReset)(HWAVEIN hwi);
10597 ma_result ma_result_from_MMRESULT(MMRESULT resultMM)
10599 switch (resultMM) {
10607 case MMSYSERR_ERROR:
return MA_ERROR;
10612 char* ma_find_last_character(
char* str,
char ch)
10621 while (*str !=
'\0') {
10639 CHAR szPname[MAXPNAMELEN];
10647 WORD bitsPerSample = 0;
10648 DWORD sampleRate = 0;
10650 if (pBitsPerSample) {
10651 *pBitsPerSample = 0;
10658 bitsPerSample = 16;
10659 if ((dwFormats & WAVE_FORMAT_48M16) != 0) {
10660 sampleRate = 48000;
10661 }
else if ((dwFormats & WAVE_FORMAT_44M16) != 0) {
10662 sampleRate = 44100;
10663 }
else if ((dwFormats & WAVE_FORMAT_2M16) != 0) {
10664 sampleRate = 22050;
10665 }
else if ((dwFormats & WAVE_FORMAT_1M16) != 0) {
10666 sampleRate = 11025;
10667 }
else if ((dwFormats & WAVE_FORMAT_96M16) != 0) {
10668 sampleRate = 96000;
10671 if ((dwFormats & WAVE_FORMAT_48M08) != 0) {
10672 sampleRate = 48000;
10673 }
else if ((dwFormats & WAVE_FORMAT_44M08) != 0) {
10674 sampleRate = 44100;
10675 }
else if ((dwFormats & WAVE_FORMAT_2M08) != 0) {
10676 sampleRate = 22050;
10677 }
else if ((dwFormats & WAVE_FORMAT_1M08) != 0) {
10678 sampleRate = 11025;
10679 }
else if ((dwFormats & WAVE_FORMAT_96M08) != 0) {
10680 sampleRate = 96000;
10686 bitsPerSample = 16;
10687 if ((dwFormats & WAVE_FORMAT_48S16) != 0) {
10688 sampleRate = 48000;
10689 }
else if ((dwFormats & WAVE_FORMAT_44S16) != 0) {
10690 sampleRate = 44100;
10691 }
else if ((dwFormats & WAVE_FORMAT_2S16) != 0) {
10692 sampleRate = 22050;
10693 }
else if ((dwFormats & WAVE_FORMAT_1S16) != 0) {
10694 sampleRate = 11025;
10695 }
else if ((dwFormats & WAVE_FORMAT_96S16) != 0) {
10696 sampleRate = 96000;
10699 if ((dwFormats & WAVE_FORMAT_48S08) != 0) {
10700 sampleRate = 48000;
10701 }
else if ((dwFormats & WAVE_FORMAT_44S08) != 0) {
10702 sampleRate = 44100;
10703 }
else if ((dwFormats & WAVE_FORMAT_2S08) != 0) {
10704 sampleRate = 22050;
10705 }
else if ((dwFormats & WAVE_FORMAT_1S08) != 0) {
10706 sampleRate = 11025;
10707 }
else if ((dwFormats & WAVE_FORMAT_96S08) != 0) {
10708 sampleRate = 96000;
10715 if (pBitsPerSample) {
10716 *pBitsPerSample = bitsPerSample;
10719 *pSampleRate = sampleRate;
10727 ma_assert(pWF !=
NULL);
10729 ma_zero_object(pWF);
10730 pWF->cbSize =
sizeof(*pWF);
10731 pWF->wFormatTag = WAVE_FORMAT_PCM;
10733 if (pWF->nChannels > 2) {
10734 pWF->nChannels = 2;
10738 pWF->wBitsPerSample = 16;
10739 if ((dwFormats & WAVE_FORMAT_48M16) != 0) {
10740 pWF->nSamplesPerSec = 48000;
10741 }
else if ((dwFormats & WAVE_FORMAT_44M16) != 0) {
10742 pWF->nSamplesPerSec = 44100;
10743 }
else if ((dwFormats & WAVE_FORMAT_2M16) != 0) {
10744 pWF->nSamplesPerSec = 22050;
10745 }
else if ((dwFormats & WAVE_FORMAT_1M16) != 0) {
10746 pWF->nSamplesPerSec = 11025;
10747 }
else if ((dwFormats & WAVE_FORMAT_96M16) != 0) {
10748 pWF->nSamplesPerSec = 96000;
10750 pWF->wBitsPerSample = 8;
10751 if ((dwFormats & WAVE_FORMAT_48M08) != 0) {
10752 pWF->nSamplesPerSec = 48000;
10753 }
else if ((dwFormats & WAVE_FORMAT_44M08) != 0) {
10754 pWF->nSamplesPerSec = 44100;
10755 }
else if ((dwFormats & WAVE_FORMAT_2M08) != 0) {
10756 pWF->nSamplesPerSec = 22050;
10757 }
else if ((dwFormats & WAVE_FORMAT_1M08) != 0) {
10758 pWF->nSamplesPerSec = 11025;
10759 }
else if ((dwFormats & WAVE_FORMAT_96M08) != 0) {
10760 pWF->nSamplesPerSec = 96000;
10766 pWF->wBitsPerSample = 16;
10767 if ((dwFormats & WAVE_FORMAT_48S16) != 0) {
10768 pWF->nSamplesPerSec = 48000;
10769 }
else if ((dwFormats & WAVE_FORMAT_44S16) != 0) {
10770 pWF->nSamplesPerSec = 44100;
10771 }
else if ((dwFormats & WAVE_FORMAT_2S16) != 0) {
10772 pWF->nSamplesPerSec = 22050;
10773 }
else if ((dwFormats & WAVE_FORMAT_1S16) != 0) {
10774 pWF->nSamplesPerSec = 11025;
10775 }
else if ((dwFormats & WAVE_FORMAT_96S16) != 0) {
10776 pWF->nSamplesPerSec = 96000;
10778 pWF->wBitsPerSample = 8;
10779 if ((dwFormats & WAVE_FORMAT_48S08) != 0) {
10780 pWF->nSamplesPerSec = 48000;
10781 }
else if ((dwFormats & WAVE_FORMAT_44S08) != 0) {
10782 pWF->nSamplesPerSec = 44100;
10783 }
else if ((dwFormats & WAVE_FORMAT_2S08) != 0) {
10784 pWF->nSamplesPerSec = 22050;
10785 }
else if ((dwFormats & WAVE_FORMAT_1S08) != 0) {
10786 pWF->nSamplesPerSec = 11025;
10787 }
else if ((dwFormats & WAVE_FORMAT_96S08) != 0) {
10788 pWF->nSamplesPerSec = 96000;
10795 pWF->nBlockAlign = (pWF->nChannels * pWF->wBitsPerSample) / 8;
10796 pWF->nAvgBytesPerSec = pWF->nBlockAlign * pWF->nSamplesPerSec;
10803 WORD bitsPerSample;
10807 ma_assert(pContext !=
NULL);
10808 ma_assert(pCaps !=
NULL);
10809 ma_assert(pDeviceInfo !=
NULL);
10820 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), pCaps->szPname, (
size_t)-1);
10832 if (!ma_is_guid_equal(&pCaps->NameGuid, &MA_GUID_NULL)) {
10833 wchar_t guidStrW[256];
10834 if (((MA_PFN_StringFromGUID2)pContext->
win32.StringFromGUID2)(&pCaps->NameGuid, guidStrW, ma_countof(guidStrW)) > 0) {
10839 WideCharToMultiByte(CP_UTF8, 0, guidStrW, -1, guidStr,
sizeof(guidStr), 0,
FALSE);
10841 ma_strcpy_s(keyStr,
sizeof(keyStr),
"SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
10842 ma_strcat_s(keyStr,
sizeof(keyStr), guidStr);
10844 if (((MA_PFN_RegOpenKeyExA)pContext->
win32.RegOpenKeyExA)(HKEY_LOCAL_MACHINE, keyStr, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
10845 BYTE nameFromReg[512];
10846 DWORD nameFromRegSize =
sizeof(nameFromReg);
10847 result = ((MA_PFN_RegQueryValueExA)pContext->
win32.RegQueryValueExA)(hKey,
"Name", 0,
NULL, (LPBYTE)nameFromReg, (LPDWORD)&nameFromRegSize);
10848 ((MA_PFN_RegCloseKey)pContext->
win32.RegCloseKey)(hKey);
10850 if (result == ERROR_SUCCESS) {
10853 if (ma_strcpy_s(
name,
sizeof(
name), pDeviceInfo->
name) == 0) {
10854 char* nameBeg = ma_find_last_character(
name,
'(');
10855 if (nameBeg !=
NULL) {
10856 size_t leadingLen = (nameBeg -
name);
10857 ma_strncpy_s(nameBeg + 1,
sizeof(
name) - leadingLen, (
const char*)nameFromReg, (
size_t)-1);
10860 if (leadingLen + nameFromRegSize <
sizeof(
name)-1) {
10861 ma_strcat_s(
name,
sizeof(
name),
")");
10864 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name),
name, (
size_t)-1);
10873 result = ma_get_best_info_from_formats_flags__winmm(pCaps->dwFormats, pCaps->wChannels, &bitsPerSample, &sampleRate);
10883 if (bitsPerSample == 8) {
10885 }
else if (bitsPerSample == 16) {
10887 }
else if (bitsPerSample == 24) {
10889 }
else if (bitsPerSample == 32) {
10902 ma_assert(pContext !=
NULL);
10903 ma_assert(pCaps !=
NULL);
10904 ma_assert(pDeviceInfo !=
NULL);
10906 ma_copy_memory(caps.szPname, pCaps->szPname,
sizeof(caps.szPname));
10907 caps.dwFormats = pCaps->dwFormats;
10908 caps.wChannels = pCaps->wChannels;
10909 caps.NameGuid = pCaps->NameGuid;
10910 return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
10917 ma_assert(pContext !=
NULL);
10918 ma_assert(pCaps !=
NULL);
10919 ma_assert(pDeviceInfo !=
NULL);
10921 ma_copy_memory(caps.szPname, pCaps->szPname,
sizeof(caps.szPname));
10922 caps.dwFormats = pCaps->dwFormats;
10923 caps.wChannels = pCaps->wChannels;
10924 caps.NameGuid = pCaps->NameGuid;
10925 return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
10931 ma_assert(pContext !=
NULL);
10932 ma_assert(pID0 !=
NULL);
10933 ma_assert(pID1 !=
NULL);
10941 UINT playbackDeviceCount;
10942 UINT captureDeviceCount;
10943 UINT iPlaybackDevice;
10944 UINT iCaptureDevice;
10946 ma_assert(pContext !=
NULL);
10947 ma_assert(callback !=
NULL);
10950 playbackDeviceCount = ((MA_PFN_waveOutGetNumDevs)pContext->
winmm.waveOutGetNumDevs)();
10951 for (iPlaybackDevice = 0; iPlaybackDevice < playbackDeviceCount; ++iPlaybackDevice) {
10953 MA_WAVEOUTCAPS2A caps;
10955 ma_zero_object(&caps);
10957 result = ((MA_PFN_waveOutGetDevCapsA)pContext->
winmm.waveOutGetDevCapsA)(iPlaybackDevice, (WAVEOUTCAPSA*)&caps,
sizeof(caps));
10958 if (result == MMSYSERR_NOERROR) {
10961 ma_zero_object(&deviceInfo);
10962 deviceInfo.
id.
winmm = iPlaybackDevice;
10964 if (ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, &deviceInfo) ==
MA_SUCCESS) {
10974 captureDeviceCount = ((MA_PFN_waveInGetNumDevs)pContext->
winmm.waveInGetNumDevs)();
10975 for (iCaptureDevice = 0; iCaptureDevice < captureDeviceCount; ++iCaptureDevice) {
10977 MA_WAVEINCAPS2A caps;
10979 ma_zero_object(&caps);
10981 result = ((MA_PFN_waveInGetDevCapsA)pContext->
winmm.waveInGetDevCapsA)(iCaptureDevice, (WAVEINCAPSA*)&caps,
sizeof(caps));
10982 if (result == MMSYSERR_NOERROR) {
10985 ma_zero_object(&deviceInfo);
10986 deviceInfo.
id.
winmm = iCaptureDevice;
10988 if (ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, &deviceInfo) ==
MA_SUCCESS) {
11002 UINT winMMDeviceID;
11004 ma_assert(pContext !=
NULL);
11011 if (pDeviceID !=
NULL) {
11012 winMMDeviceID = (
UINT)pDeviceID->
winmm;
11015 pDeviceInfo->
id.
winmm = winMMDeviceID;
11019 MA_WAVEOUTCAPS2A caps;
11021 ma_zero_object(&caps);
11023 result = ((MA_PFN_waveOutGetDevCapsA)pContext->
winmm.waveOutGetDevCapsA)(winMMDeviceID, (WAVEOUTCAPSA*)&caps,
sizeof(caps));
11024 if (result == MMSYSERR_NOERROR) {
11025 return ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, pDeviceInfo);
11029 MA_WAVEINCAPS2A caps;
11031 ma_zero_object(&caps);
11033 result = ((MA_PFN_waveInGetDevCapsA)pContext->
winmm.waveInGetDevCapsA)(winMMDeviceID, (WAVEINCAPSA*)&caps,
sizeof(caps));
11034 if (result == MMSYSERR_NOERROR) {
11035 return ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, pDeviceInfo);
11043 void ma_device_uninit__winmm(
ma_device* pDevice)
11045 ma_assert(pDevice !=
NULL);
11048 ((MA_PFN_waveInClose)pDevice->pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
11049 CloseHandle((HANDLE)pDevice->winmm.hEventCapture);
11053 ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
11054 ((MA_PFN_waveOutClose)pDevice->pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
11055 CloseHandle((HANDLE)pDevice->winmm.hEventPlayback);
11058 ma_free(pDevice->winmm._pHeapData);
11060 ma_zero_object(&pDevice->winmm);
11065 const char* errorMsg =
"";
11069 UINT winMMDeviceIDPlayback = 0;
11070 UINT winMMDeviceIDCapture = 0;
11073 ma_assert(pDevice !=
NULL);
11074 ma_zero_object(&pDevice->winmm);
11083 if (bufferSizeInMilliseconds == 0) {
11088 if (pDevice->usingDefaultBufferSize) {
11090 bufferSizeInMilliseconds = 40 * pConfig->
periods;
11092 bufferSizeInMilliseconds = 400 * pConfig->
periods;
11112 if (pDevice->winmm.hEventCapture ==
NULL) {
11113 errorMsg =
"[WinMM] Failed to create event for fragment enqueing for the capture device.", errorCode =
MA_FAILED_TO_CREATE_EVENT;
11118 if (((MA_PFN_waveInGetDevCapsA)pContext->
winmm.waveInGetDevCapsA)(winMMDeviceIDCapture, &caps,
sizeof(caps)) != MMSYSERR_NOERROR) {
11123 result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
11125 errorMsg =
"[WinMM] Could not find appropriate format for internal device.", errorCode = result;
11129 resultMM = ((MA_PFN_waveInOpen)pDevice->pContext->winmm.waveInOpen)((LPHWAVEIN)&pDevice->winmm.hDeviceCapture, winMMDeviceIDCapture, &wf, (DWORD_PTR)pDevice->winmm.hEventCapture, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
11130 if (resultMM != MMSYSERR_NOERROR) {
11135 pDevice->capture.internalFormat = ma_format_from_WAVEFORMATEX(&wf);
11136 pDevice->capture.internalChannels = wf.nChannels;
11137 pDevice->capture.internalSampleRate = wf.nSamplesPerSec;
11139 pDevice->capture.internalPeriods = pConfig->
periods;
11150 if (pDevice->winmm.hEventPlayback ==
NULL) {
11151 errorMsg =
"[WinMM] Failed to create event for fragment enqueing for the playback device.", errorCode =
MA_FAILED_TO_CREATE_EVENT;
11156 if (((MA_PFN_waveOutGetDevCapsA)pContext->
winmm.waveOutGetDevCapsA)(winMMDeviceIDPlayback, &caps,
sizeof(caps)) != MMSYSERR_NOERROR) {
11161 result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
11163 errorMsg =
"[WinMM] Could not find appropriate format for internal device.", errorCode = result;
11167 resultMM = ((MA_PFN_waveOutOpen)pContext->
winmm.waveOutOpen)((LPHWAVEOUT)&pDevice->winmm.hDevicePlayback, winMMDeviceIDPlayback, &wf, (DWORD_PTR)pDevice->winmm.hEventPlayback, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
11168 if (resultMM != MMSYSERR_NOERROR) {
11173 pDevice->playback.internalFormat = ma_format_from_WAVEFORMATEX(&wf);
11174 pDevice->playback.internalChannels = wf.nChannels;
11175 pDevice->playback.internalSampleRate = wf.nSamplesPerSec;
11177 pDevice->playback.internalPeriods = pConfig->
periods;
11188 heapSize +=
sizeof(WAVEHDR)*pDevice->capture.internalPeriods + (pDevice->capture.internalBufferSizeInFrames*
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
11191 heapSize +=
sizeof(WAVEHDR)*pDevice->playback.internalPeriods + (pDevice->playback.internalBufferSizeInFrames*
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
11195 if (pDevice->winmm._pHeapData ==
NULL) {
11196 errorMsg =
"[WinMM] Failed to allocate memory for the intermediary buffer.", errorCode =
MA_OUT_OF_MEMORY;
11200 ma_zero_memory(pDevice->winmm._pHeapData, heapSize);
11206 pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
11207 pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods));
11209 pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
11210 pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods + pDevice->playback.internalPeriods));
11214 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
11215 ma_uint32 fragmentSizeInBytes = ma_get_fragment_size_in_bytes(pDevice->capture.internalBufferSizeInFrames, pDevice->capture.internalPeriods, pDevice->capture.internalFormat, pDevice->capture.internalChannels);
11217 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferCapture + (fragmentSizeInBytes*iPeriod));
11218 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwBufferLength = fragmentSizeInBytes;
11219 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwFlags = 0
L;
11220 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwLoops = 0
L;
11221 ((MA_PFN_waveInPrepareHeader)pContext->
winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod],
sizeof(WAVEHDR));
11227 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwUser = 0;
11234 pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData;
11235 pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*pDevice->playback.internalPeriods);
11237 pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods));
11238 pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods + pDevice->playback.internalPeriods)) + (pDevice->playback.internalBufferSizeInFrames*
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
11242 for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
11243 ma_uint32 fragmentSizeInBytes = ma_get_fragment_size_in_bytes(pDevice->playback.internalBufferSizeInFrames, pDevice->playback.internalPeriods, pDevice->playback.internalFormat, pDevice->playback.internalChannels);
11245 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferPlayback + (fragmentSizeInBytes*iPeriod));
11246 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwBufferLength = fragmentSizeInBytes;
11247 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwFlags = 0
L;
11248 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwLoops = 0
L;
11249 ((MA_PFN_waveOutPrepareHeader)pContext->
winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod],
sizeof(WAVEHDR));
11255 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwUser = 0;
11263 if (pDevice->winmm.pWAVEHDRCapture !=
NULL) {
11265 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
11266 ((MA_PFN_waveInUnprepareHeader)pContext->
winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod],
sizeof(WAVEHDR));
11270 ((MA_PFN_waveInClose)pContext->
winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
11274 if (pDevice->winmm.pWAVEHDRCapture !=
NULL) {
11276 for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
11277 ((MA_PFN_waveOutUnprepareHeader)pContext->
winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod],
sizeof(WAVEHDR));
11281 ((MA_PFN_waveOutClose)pContext->
winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
11284 ma_free(pDevice->winmm._pHeapData);
11292 ma_assert(pDevice !=
NULL);
11295 if (pDevice->winmm.hDeviceCapture ==
NULL) {
11299 resultMM = ((MA_PFN_waveInReset)pDevice->pContext->winmm.waveInReset)((HWAVEIN)pDevice->winmm.hDeviceCapture);
11300 if (resultMM != MMSYSERR_NOERROR) {
11301 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] WARNING: Failed to reset capture device.", ma_result_from_MMRESULT(resultMM));
11306 if (pDevice->winmm.hDevicePlayback ==
NULL) {
11310 resultMM = ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
11311 if (resultMM != MMSYSERR_NOERROR) {
11312 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] WARNING: Failed to reset playback device.", ma_result_from_MMRESULT(resultMM));
11316 ma_atomic_exchange_32(&pDevice->winmm.isStarted,
MA_FALSE);
11327 ma_assert(pDevice !=
NULL);
11328 ma_assert(pPCMFrames !=
NULL);
11330 pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback;
11333 totalFramesWritten = 0;
11334 while (totalFramesWritten < frameCount) {
11336 if (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser == 0) {
11342 ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedPlayback;
11344 ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesWritten));
11345 const void* pSrc = ma_offset_ptr(pPCMFrames, totalFramesWritten*bpf);
11346 void* pDst = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].lpData, pDevice->winmm.headerFramesConsumedPlayback*bpf);
11347 ma_copy_memory(pDst, pSrc, framesToCopy*bpf);
11349 pDevice->winmm.headerFramesConsumedPlayback += framesToCopy;
11350 totalFramesWritten += framesToCopy;
11353 if (pDevice->winmm.headerFramesConsumedPlayback == (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf)) {
11354 pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 1;
11355 pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags &= ~WHDR_DONE;
11358 ResetEvent((HANDLE)pDevice->winmm.hEventPlayback);
11361 resultMM = ((MA_PFN_waveOutWrite)pDevice->pContext->winmm.waveOutWrite)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &pWAVEHDR[pDevice->winmm.iNextHeaderPlayback],
sizeof(WAVEHDR));
11362 if (resultMM != MMSYSERR_NOERROR) {
11363 result = ma_result_from_MMRESULT(resultMM);
11364 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] waveOutWrite() failed.", result);
11367 ma_atomic_exchange_32(&pDevice->winmm.isStarted,
MA_TRUE);
11370 pDevice->winmm.iNextHeaderPlayback = (pDevice->winmm.iNextHeaderPlayback + 1) % pDevice->playback.internalPeriods;
11371 pDevice->winmm.headerFramesConsumedPlayback = 0;
11375 ma_assert(totalFramesWritten <= frameCount);
11376 if (totalFramesWritten == frameCount) {
11385 if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
11391 if ((pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags & WHDR_DONE) != 0) {
11392 pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 0;
11393 pDevice->winmm.headerFramesConsumedPlayback = 0;
11397 if (!pDevice->winmm.isStarted) {
11412 ma_assert(pDevice !=
NULL);
11413 ma_assert(pPCMFrames !=
NULL);
11415 pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
11418 if (!pDevice->winmm.isStarted) {
11422 ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
11425 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
11426 resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[iPeriod],
sizeof(WAVEHDR));
11427 if (resultMM != MMSYSERR_NOERROR) {
11428 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] Failed to attach input buffers to capture device in preparation for capture.", ma_result_from_MMRESULT(resultMM));
11432 pWAVEHDR[iPeriod].dwUser = 1;
11436 resultMM = ((MA_PFN_waveInStart)pDevice->pContext->winmm.waveInStart)((HWAVEIN)pDevice->winmm.hDeviceCapture);
11437 if (resultMM != MMSYSERR_NOERROR) {
11438 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] Failed to start backend device.", ma_result_from_MMRESULT(resultMM));
11441 ma_atomic_exchange_32(&pDevice->winmm.isStarted,
MA_TRUE);
11445 totalFramesRead = 0;
11446 while (totalFramesRead < frameCount) {
11448 if (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser == 0) {
11451 ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedCapture;
11453 ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesRead));
11454 const void* pSrc = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderCapture].lpData, pDevice->winmm.headerFramesConsumedCapture*bpf);
11455 void* pDst = ma_offset_ptr(pPCMFrames, totalFramesRead*bpf);
11456 ma_copy_memory(pDst, pSrc, framesToCopy*bpf);
11458 pDevice->winmm.headerFramesConsumedCapture += framesToCopy;
11459 totalFramesRead += framesToCopy;
11462 if (pDevice->winmm.headerFramesConsumedCapture == (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf)) {
11463 pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 1;
11464 pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags &= ~WHDR_DONE;
11467 ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
11470 resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[pDevice->winmm.iNextHeaderCapture],
sizeof(WAVEHDR));
11471 if (resultMM != MMSYSERR_NOERROR) {
11472 result = ma_result_from_MMRESULT(resultMM);
11473 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] waveInAddBuffer() failed.", result);
11478 pDevice->winmm.iNextHeaderCapture = (pDevice->winmm.iNextHeaderCapture + 1) % pDevice->capture.internalPeriods;
11479 pDevice->winmm.headerFramesConsumedCapture = 0;
11483 ma_assert(totalFramesRead <= frameCount);
11484 if (totalFramesRead == frameCount) {
11493 if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
11499 if ((pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags & WHDR_DONE) != 0) {
11500 pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 0;
11501 pDevice->winmm.headerFramesConsumedCapture = 0;
11505 if (!pDevice->winmm.isStarted) {
11515 ma_assert(pContext !=
NULL);
11518 ma_dlclose(pContext, pContext->
winmm.hWinMM);
11524 ma_assert(pContext !=
NULL);
11528 pContext->
winmm.hWinMM = ma_dlopen(pContext,
"winmm.dll");
11533 pContext->
winmm.waveOutGetNumDevs = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutGetNumDevs");
11534 pContext->
winmm.waveOutGetDevCapsA = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutGetDevCapsA");
11535 pContext->
winmm.waveOutOpen = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutOpen");
11536 pContext->
winmm.waveOutClose = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutClose");
11537 pContext->
winmm.waveOutPrepareHeader = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutPrepareHeader");
11538 pContext->
winmm.waveOutUnprepareHeader = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutUnprepareHeader");
11539 pContext->
winmm.waveOutWrite = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutWrite");
11540 pContext->
winmm.waveOutReset = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveOutReset");
11541 pContext->
winmm.waveInGetNumDevs = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInGetNumDevs");
11542 pContext->
winmm.waveInGetDevCapsA = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInGetDevCapsA");
11543 pContext->
winmm.waveInOpen = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInOpen");
11544 pContext->
winmm.waveInClose = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInClose");
11545 pContext->
winmm.waveInPrepareHeader = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInPrepareHeader");
11546 pContext->
winmm.waveInUnprepareHeader = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInUnprepareHeader");
11547 pContext->
winmm.waveInAddBuffer = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInAddBuffer");
11548 pContext->
winmm.waveInStart = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInStart");
11549 pContext->
winmm.waveInReset = ma_dlsym(pContext, pContext->
winmm.hWinMM,
"waveInReset");
11551 pContext->
onUninit = ma_context_uninit__winmm;
11553 pContext->
onEnumDevices = ma_context_enumerate_devices__winmm;
11576 #ifdef MA_NO_RUNTIME_LINKING
11577 #include <alsa/asoundlib.h>
11578 typedef snd_pcm_uframes_t ma_snd_pcm_uframes_t;
11579 typedef snd_pcm_sframes_t ma_snd_pcm_sframes_t;
11580 typedef snd_pcm_stream_t ma_snd_pcm_stream_t;
11581 typedef snd_pcm_format_t ma_snd_pcm_format_t;
11582 typedef snd_pcm_access_t ma_snd_pcm_access_t;
11583 typedef snd_pcm_t ma_snd_pcm_t;
11584 typedef snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
11585 typedef snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
11586 typedef snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
11587 typedef snd_pcm_info_t ma_snd_pcm_info_t;
11588 typedef snd_pcm_channel_area_t ma_snd_pcm_channel_area_t;
11589 typedef snd_pcm_chmap_t ma_snd_pcm_chmap_t;
11592 #define MA_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK
11593 #define MA_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE
11596 #define MA_SND_PCM_FORMAT_UNKNOWN SND_PCM_FORMAT_UNKNOWN
11597 #define MA_SND_PCM_FORMAT_U8 SND_PCM_FORMAT_U8
11598 #define MA_SND_PCM_FORMAT_S16_LE SND_PCM_FORMAT_S16_LE
11599 #define MA_SND_PCM_FORMAT_S16_BE SND_PCM_FORMAT_S16_BE
11600 #define MA_SND_PCM_FORMAT_S24_LE SND_PCM_FORMAT_S24_LE
11601 #define MA_SND_PCM_FORMAT_S24_BE SND_PCM_FORMAT_S24_BE
11602 #define MA_SND_PCM_FORMAT_S32_LE SND_PCM_FORMAT_S32_LE
11603 #define MA_SND_PCM_FORMAT_S32_BE SND_PCM_FORMAT_S32_BE
11604 #define MA_SND_PCM_FORMAT_FLOAT_LE SND_PCM_FORMAT_FLOAT_LE
11605 #define MA_SND_PCM_FORMAT_FLOAT_BE SND_PCM_FORMAT_FLOAT_BE
11606 #define MA_SND_PCM_FORMAT_FLOAT64_LE SND_PCM_FORMAT_FLOAT64_LE
11607 #define MA_SND_PCM_FORMAT_FLOAT64_BE SND_PCM_FORMAT_FLOAT64_BE
11608 #define MA_SND_PCM_FORMAT_MU_LAW SND_PCM_FORMAT_MU_LAW
11609 #define MA_SND_PCM_FORMAT_A_LAW SND_PCM_FORMAT_A_LAW
11610 #define MA_SND_PCM_FORMAT_S24_3LE SND_PCM_FORMAT_S24_3LE
11611 #define MA_SND_PCM_FORMAT_S24_3BE SND_PCM_FORMAT_S24_3BE
11614 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED SND_PCM_ACCESS_MMAP_INTERLEAVED
11615 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED SND_PCM_ACCESS_MMAP_NONINTERLEAVED
11616 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX SND_PCM_ACCESS_MMAP_COMPLEX
11617 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED SND_PCM_ACCESS_RW_INTERLEAVED
11618 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED SND_PCM_ACCESS_RW_NONINTERLEAVED
11621 #define MA_SND_CHMAP_UNKNOWN SND_CHMAP_UNKNOWN
11622 #define MA_SND_CHMAP_NA SND_CHMAP_NA
11623 #define MA_SND_CHMAP_MONO SND_CHMAP_MONO
11624 #define MA_SND_CHMAP_FL SND_CHMAP_FL
11625 #define MA_SND_CHMAP_FR SND_CHMAP_FR
11626 #define MA_SND_CHMAP_RL SND_CHMAP_RL
11627 #define MA_SND_CHMAP_RR SND_CHMAP_RR
11628 #define MA_SND_CHMAP_FC SND_CHMAP_FC
11629 #define MA_SND_CHMAP_LFE SND_CHMAP_LFE
11630 #define MA_SND_CHMAP_SL SND_CHMAP_SL
11631 #define MA_SND_CHMAP_SR SND_CHMAP_SR
11632 #define MA_SND_CHMAP_RC SND_CHMAP_RC
11633 #define MA_SND_CHMAP_FLC SND_CHMAP_FLC
11634 #define MA_SND_CHMAP_FRC SND_CHMAP_FRC
11635 #define MA_SND_CHMAP_RLC SND_CHMAP_RLC
11636 #define MA_SND_CHMAP_RRC SND_CHMAP_RRC
11637 #define MA_SND_CHMAP_FLW SND_CHMAP_FLW
11638 #define MA_SND_CHMAP_FRW SND_CHMAP_FRW
11639 #define MA_SND_CHMAP_FLH SND_CHMAP_FLH
11640 #define MA_SND_CHMAP_FCH SND_CHMAP_FCH
11641 #define MA_SND_CHMAP_FRH SND_CHMAP_FRH
11642 #define MA_SND_CHMAP_TC SND_CHMAP_TC
11643 #define MA_SND_CHMAP_TFL SND_CHMAP_TFL
11644 #define MA_SND_CHMAP_TFR SND_CHMAP_TFR
11645 #define MA_SND_CHMAP_TFC SND_CHMAP_TFC
11646 #define MA_SND_CHMAP_TRL SND_CHMAP_TRL
11647 #define MA_SND_CHMAP_TRR SND_CHMAP_TRR
11648 #define MA_SND_CHMAP_TRC SND_CHMAP_TRC
11649 #define MA_SND_CHMAP_TFLC SND_CHMAP_TFLC
11650 #define MA_SND_CHMAP_TFRC SND_CHMAP_TFRC
11651 #define MA_SND_CHMAP_TSL SND_CHMAP_TSL
11652 #define MA_SND_CHMAP_TSR SND_CHMAP_TSR
11653 #define MA_SND_CHMAP_LLFE SND_CHMAP_LLFE
11654 #define MA_SND_CHMAP_RLFE SND_CHMAP_RLFE
11655 #define MA_SND_CHMAP_BC SND_CHMAP_BC
11656 #define MA_SND_CHMAP_BLC SND_CHMAP_BLC
11657 #define MA_SND_CHMAP_BRC SND_CHMAP_BRC
11660 #define MA_SND_PCM_NO_AUTO_RESAMPLE SND_PCM_NO_AUTO_RESAMPLE
11661 #define MA_SND_PCM_NO_AUTO_CHANNELS SND_PCM_NO_AUTO_CHANNELS
11662 #define MA_SND_PCM_NO_AUTO_FORMAT SND_PCM_NO_AUTO_FORMAT
11665 typedef unsigned long ma_snd_pcm_uframes_t;
11666 typedef long ma_snd_pcm_sframes_t;
11667 typedef int ma_snd_pcm_stream_t;
11668 typedef int ma_snd_pcm_format_t;
11669 typedef int ma_snd_pcm_access_t;
11670 typedef struct ma_snd_pcm_t ma_snd_pcm_t;
11671 typedef struct ma_snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
11672 typedef struct ma_snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
11673 typedef struct ma_snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
11674 typedef struct ma_snd_pcm_info_t ma_snd_pcm_info_t;
11678 unsigned int first;
11680 } ma_snd_pcm_channel_area_t;
11684 unsigned int pos[1];
11685 } ma_snd_pcm_chmap_t;
11688 #define MA_SND_PCM_STATE_OPEN 0
11689 #define MA_SND_PCM_STATE_SETUP 1
11690 #define MA_SND_PCM_STATE_PREPARED 2
11691 #define MA_SND_PCM_STATE_RUNNING 3
11692 #define MA_SND_PCM_STATE_XRUN 4
11693 #define MA_SND_PCM_STATE_DRAINING 5
11694 #define MA_SND_PCM_STATE_PAUSED 6
11695 #define MA_SND_PCM_STATE_SUSPENDED 7
11696 #define MA_SND_PCM_STATE_DISCONNECTED 8
11699 #define MA_SND_PCM_STREAM_PLAYBACK 0
11700 #define MA_SND_PCM_STREAM_CAPTURE 1
11703 #define MA_SND_PCM_FORMAT_UNKNOWN -1
11704 #define MA_SND_PCM_FORMAT_U8 1
11705 #define MA_SND_PCM_FORMAT_S16_LE 2
11706 #define MA_SND_PCM_FORMAT_S16_BE 3
11707 #define MA_SND_PCM_FORMAT_S24_LE 6
11708 #define MA_SND_PCM_FORMAT_S24_BE 7
11709 #define MA_SND_PCM_FORMAT_S32_LE 10
11710 #define MA_SND_PCM_FORMAT_S32_BE 11
11711 #define MA_SND_PCM_FORMAT_FLOAT_LE 14
11712 #define MA_SND_PCM_FORMAT_FLOAT_BE 15
11713 #define MA_SND_PCM_FORMAT_FLOAT64_LE 16
11714 #define MA_SND_PCM_FORMAT_FLOAT64_BE 17
11715 #define MA_SND_PCM_FORMAT_MU_LAW 20
11716 #define MA_SND_PCM_FORMAT_A_LAW 21
11717 #define MA_SND_PCM_FORMAT_S24_3LE 32
11718 #define MA_SND_PCM_FORMAT_S24_3BE 33
11721 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED 0
11722 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED 1
11723 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX 2
11724 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED 3
11725 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED 4
11728 #define MA_SND_CHMAP_UNKNOWN 0
11729 #define MA_SND_CHMAP_NA 1
11730 #define MA_SND_CHMAP_MONO 2
11731 #define MA_SND_CHMAP_FL 3
11732 #define MA_SND_CHMAP_FR 4
11733 #define MA_SND_CHMAP_RL 5
11734 #define MA_SND_CHMAP_RR 6
11735 #define MA_SND_CHMAP_FC 7
11736 #define MA_SND_CHMAP_LFE 8
11737 #define MA_SND_CHMAP_SL 9
11738 #define MA_SND_CHMAP_SR 10
11739 #define MA_SND_CHMAP_RC 11
11740 #define MA_SND_CHMAP_FLC 12
11741 #define MA_SND_CHMAP_FRC 13
11742 #define MA_SND_CHMAP_RLC 14
11743 #define MA_SND_CHMAP_RRC 15
11744 #define MA_SND_CHMAP_FLW 16
11745 #define MA_SND_CHMAP_FRW 17
11746 #define MA_SND_CHMAP_FLH 18
11747 #define MA_SND_CHMAP_FCH 19
11748 #define MA_SND_CHMAP_FRH 20
11749 #define MA_SND_CHMAP_TC 21
11750 #define MA_SND_CHMAP_TFL 22
11751 #define MA_SND_CHMAP_TFR 23
11752 #define MA_SND_CHMAP_TFC 24
11753 #define MA_SND_CHMAP_TRL 25
11754 #define MA_SND_CHMAP_TRR 26
11755 #define MA_SND_CHMAP_TRC 27
11756 #define MA_SND_CHMAP_TFLC 28
11757 #define MA_SND_CHMAP_TFRC 29
11758 #define MA_SND_CHMAP_TSL 30
11759 #define MA_SND_CHMAP_TSR 31
11760 #define MA_SND_CHMAP_LLFE 32
11761 #define MA_SND_CHMAP_RLFE 33
11762 #define MA_SND_CHMAP_BC 34
11763 #define MA_SND_CHMAP_BLC 35
11764 #define MA_SND_CHMAP_BRC 36
11767 #define MA_SND_PCM_NO_AUTO_RESAMPLE 0x00010000
11768 #define MA_SND_PCM_NO_AUTO_CHANNELS 0x00020000
11769 #define MA_SND_PCM_NO_AUTO_FORMAT 0x00040000
11772 typedef int (* ma_snd_pcm_open_proc) (ma_snd_pcm_t **pcm,
const char *
name, ma_snd_pcm_stream_t stream,
int mode);
11773 typedef int (* ma_snd_pcm_close_proc) (ma_snd_pcm_t *pcm);
11774 typedef size_t (* ma_snd_pcm_hw_params_sizeof_proc) (
void);
11775 typedef int (* ma_snd_pcm_hw_params_any_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params);
11776 typedef int (* ma_snd_pcm_hw_params_set_format_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_t val);
11777 typedef int (* ma_snd_pcm_hw_params_set_format_first_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_t *
format);
11778 typedef void (* ma_snd_pcm_hw_params_get_format_mask_proc) (ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_mask_t *
mask);
11779 typedef int (* ma_snd_pcm_hw_params_set_channels_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int *val);
11780 typedef int (* ma_snd_pcm_hw_params_set_rate_resample_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int val);
11781 typedef int (* ma_snd_pcm_hw_params_set_rate_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int *val,
int *dir);
11782 typedef int (* ma_snd_pcm_hw_params_set_buffer_size_near_proc)(ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_uframes_t *val);
11783 typedef int (* ma_snd_pcm_hw_params_set_periods_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int *val,
int *dir);
11784 typedef int (* ma_snd_pcm_hw_params_set_access_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_access_t _access);
11785 typedef int (* ma_snd_pcm_hw_params_get_format_proc) (
const ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_t *
format);
11786 typedef int (* ma_snd_pcm_hw_params_get_channels_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *val);
11787 typedef int (* ma_snd_pcm_hw_params_get_channels_min_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *val);
11788 typedef int (* ma_snd_pcm_hw_params_get_channels_max_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *val);
11789 typedef int (* ma_snd_pcm_hw_params_get_rate_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *
rate,
int *dir);
11790 typedef int (* ma_snd_pcm_hw_params_get_rate_min_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *
rate,
int *dir);
11791 typedef int (* ma_snd_pcm_hw_params_get_rate_max_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *
rate,
int *dir);
11792 typedef int (* ma_snd_pcm_hw_params_get_buffer_size_proc) (
const ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_uframes_t *val);
11793 typedef int (* ma_snd_pcm_hw_params_get_periods_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *val,
int *dir);
11794 typedef int (* ma_snd_pcm_hw_params_get_access_proc) (
const ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_access_t *_access);
11795 typedef int (* ma_snd_pcm_hw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params);
11796 typedef size_t (* ma_snd_pcm_sw_params_sizeof_proc) (
void);
11797 typedef int (* ma_snd_pcm_sw_params_current_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params);
11798 typedef int (* ma_snd_pcm_sw_params_get_boundary_proc) (ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t* val);
11799 typedef int (* ma_snd_pcm_sw_params_set_avail_min_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t val);
11800 typedef int (* ma_snd_pcm_sw_params_set_start_threshold_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t val);
11801 typedef int (* ma_snd_pcm_sw_params_set_stop_threshold_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t val);
11802 typedef int (* ma_snd_pcm_sw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params);
11803 typedef size_t (* ma_snd_pcm_format_mask_sizeof_proc) (
void);
11804 typedef int (* ma_snd_pcm_format_mask_test_proc) (
const ma_snd_pcm_format_mask_t *
mask, ma_snd_pcm_format_t val);
11805 typedef ma_snd_pcm_chmap_t * (* ma_snd_pcm_get_chmap_proc) (ma_snd_pcm_t *pcm);
11806 typedef int (* ma_snd_pcm_state_proc) (ma_snd_pcm_t *pcm);
11807 typedef int (* ma_snd_pcm_prepare_proc) (ma_snd_pcm_t *pcm);
11808 typedef int (* ma_snd_pcm_start_proc) (ma_snd_pcm_t *pcm);
11809 typedef int (* ma_snd_pcm_drop_proc) (ma_snd_pcm_t *pcm);
11810 typedef int (* ma_snd_pcm_drain_proc) (ma_snd_pcm_t *pcm);
11811 typedef int (* ma_snd_device_name_hint_proc) (
int card,
const char *iface,
void ***hints);
11812 typedef char * (* ma_snd_device_name_get_hint_proc) (
const void *hint,
const char *id);
11813 typedef int (* ma_snd_card_get_index_proc) (
const char *
name);
11814 typedef int (* ma_snd_device_name_free_hint_proc) (
void **hints);
11815 typedef int (* ma_snd_pcm_mmap_begin_proc) (ma_snd_pcm_t *pcm,
const ma_snd_pcm_channel_area_t **areas, ma_snd_pcm_uframes_t *offset, ma_snd_pcm_uframes_t *frames);
11816 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_mmap_commit_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_uframes_t offset, ma_snd_pcm_uframes_t frames);
11817 typedef int (* ma_snd_pcm_recover_proc) (ma_snd_pcm_t *pcm,
int err,
int silent);
11818 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_readi_proc) (ma_snd_pcm_t *pcm,
void *
buffer, ma_snd_pcm_uframes_t size);
11819 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_writei_proc) (ma_snd_pcm_t *pcm,
const void *
buffer, ma_snd_pcm_uframes_t size);
11820 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_proc) (ma_snd_pcm_t *pcm);
11821 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_update_proc) (ma_snd_pcm_t *pcm);
11822 typedef int (* ma_snd_pcm_wait_proc) (ma_snd_pcm_t *pcm,
int timeout);
11823 typedef int (* ma_snd_pcm_info_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_info_t* info);
11824 typedef size_t (* ma_snd_pcm_info_sizeof_proc) ();
11825 typedef const char* (* ma_snd_pcm_info_get_name_proc) (
const ma_snd_pcm_info_t* info);
11826 typedef int (* ma_snd_config_update_free_global_proc) ();
11829 const char* g_maCommonDeviceNamesALSA[] = {
11837 const char* g_maBlacklistedPlaybackDeviceNamesALSA[] = {
11842 const char* g_maBlacklistedCaptureDeviceNamesALSA[] = {
11855 } g_maDefaultBufferSizeScalesALSA[] = {
11856 {
"bcm2835 IEC958/HDMI", 2.0f},
11857 {
"bcm2835 ALSA", 2.0f}
11860 float ma_find_default_buffer_size_scale__alsa(
const char* deviceName)
11864 if (deviceName ==
NULL) {
11868 for (
i = 0;
i < ma_countof(g_maDefaultBufferSizeScalesALSA); ++
i) {
11869 if (strstr(g_maDefaultBufferSizeScalesALSA[
i].
name, deviceName) !=
NULL) {
11870 return g_maDefaultBufferSizeScalesALSA[
i].scale;
11877 ma_snd_pcm_format_t ma_convert_ma_format_to_alsa_format(
ma_format format)
11879 ma_snd_pcm_format_t ALSAFormats[] = {
11880 MA_SND_PCM_FORMAT_UNKNOWN,
11881 MA_SND_PCM_FORMAT_U8,
11882 MA_SND_PCM_FORMAT_S16_LE,
11883 MA_SND_PCM_FORMAT_S24_3LE,
11884 MA_SND_PCM_FORMAT_S32_LE,
11885 MA_SND_PCM_FORMAT_FLOAT_LE
11888 if (ma_is_big_endian()) {
11889 ALSAFormats[0] = MA_SND_PCM_FORMAT_UNKNOWN;
11890 ALSAFormats[1] = MA_SND_PCM_FORMAT_U8;
11891 ALSAFormats[2] = MA_SND_PCM_FORMAT_S16_BE;
11892 ALSAFormats[3] = MA_SND_PCM_FORMAT_S24_3BE;
11893 ALSAFormats[4] = MA_SND_PCM_FORMAT_S32_BE;
11894 ALSAFormats[5] = MA_SND_PCM_FORMAT_FLOAT_BE;
11897 return ALSAFormats[
format];
11900 ma_format ma_format_from_alsa(ma_snd_pcm_format_t formatALSA)
11902 if (ma_is_little_endian()) {
11903 switch (formatALSA) {
11911 switch (formatALSA) {
11921 switch (formatALSA) {
11927 ma_channel ma_convert_alsa_channel_position_to_ma_channel(
unsigned int alsaChannelPos)
11929 switch (alsaChannelPos)
11943 case MA_SND_CHMAP_RLC:
return 0;
11944 case MA_SND_CHMAP_RRC:
return 0;
11945 case MA_SND_CHMAP_FLW:
return 0;
11946 case MA_SND_CHMAP_FRW:
return 0;
11947 case MA_SND_CHMAP_FLH:
return 0;
11948 case MA_SND_CHMAP_FCH:
return 0;
11949 case MA_SND_CHMAP_FRH:
return 0;
11966 for (iName = 0; iName < ma_countof(g_maCommonDeviceNamesALSA); ++iName) {
11967 if (ma_strcmp(
name, g_maCommonDeviceNamesALSA[iName]) == 0) {
11976 ma_bool32 ma_is_playback_device_blacklisted__alsa(
const char*
name)
11979 for (iName = 0; iName < ma_countof(g_maBlacklistedPlaybackDeviceNamesALSA); ++iName) {
11980 if (ma_strcmp(
name, g_maBlacklistedPlaybackDeviceNamesALSA[iName]) == 0) {
11988 ma_bool32 ma_is_capture_device_blacklisted__alsa(
const char*
name)
11991 for (iName = 0; iName < ma_countof(g_maBlacklistedCaptureDeviceNamesALSA); ++iName) {
11992 if (ma_strcmp(
name, g_maBlacklistedCaptureDeviceNamesALSA[iName]) == 0) {
12003 return ma_is_playback_device_blacklisted__alsa(
name);
12005 return ma_is_capture_device_blacklisted__alsa(
name);
12010 const char* ma_find_char(
const char* str,
char c,
int* index)
12014 if (str[
i] ==
'\0') {
12015 if (index) *index = -1;
12020 if (index) *index =
i;
12028 if (index) *index = -1;
12032 ma_bool32 ma_is_device_name_in_hw_format__alsa(
const char* hwid)
12040 if (hwid ==
NULL) {
12044 if (hwid[0] !=
'h' || hwid[1] !=
'w' || hwid[2] !=
':') {
12050 dev = ma_find_char(hwid,
',', &commaPos);
12058 for (
i = 0;
i < commaPos; ++
i) {
12059 if (hwid[
i] <
'0' || hwid[
i] >
'9') {
12066 while (dev[
i] !=
'\0') {
12067 if (dev[
i] <
'0' || dev[
i] >
'9') {
12076 int ma_convert_device_name_to_hw_format__alsa(
ma_context* pContext,
char* dst,
size_t dstSize,
const char* src)
12099 if (ma_is_device_name_in_hw_format__alsa(src)) {
12100 return ma_strcpy_s(dst, dstSize, src);
12103 src = ma_find_char(src,
':', &colonPos);
12108 dev = ma_find_char(src,
',', &commaPos);
12111 ma_strncpy_s(card,
sizeof(card), src+6, (
size_t)-1);
12114 ma_strncpy_s(card,
sizeof(card), src+6, commaPos-6);
12117 cardIndex = ((ma_snd_card_get_index_proc)pContext->alsa.snd_card_get_index)(card);
12118 if (cardIndex < 0) {
12126 dst[0] =
'h'; dst[1] =
'w'; dst[2] =
':';
12127 if (ma_itoa_s(cardIndex, dst+3, dstSize-3, 10) != 0) {
12130 if (ma_strcat_s(dst, dstSize,
",") != 0) {
12133 if (ma_strcat_s(dst, dstSize, dev) != 0) {
12144 ma_assert(pHWID !=
NULL);
12147 if (ma_strcmp(pUniqueIDs[
i].alsa, pHWID) == 0) {
12158 ma_snd_pcm_t* pPCM;
12159 ma_snd_pcm_stream_t stream;
12162 ma_assert(pContext !=
NULL);
12163 ma_assert(ppPCM !=
NULL);
12169 openMode = MA_SND_PCM_NO_AUTO_RESAMPLE | MA_SND_PCM_NO_AUTO_CHANNELS | MA_SND_PCM_NO_AUTO_FORMAT;
12171 if (pDeviceID ==
NULL) {
12179 const char* defaultDeviceNames[] = {
12190 defaultDeviceNames[1] =
"hw";
12191 defaultDeviceNames[2] =
"hw:0";
12192 defaultDeviceNames[3] =
"hw:0,0";
12195 defaultDeviceNames[1] =
"dmix";
12196 defaultDeviceNames[2] =
"dmix:0";
12197 defaultDeviceNames[3] =
"dmix:0,0";
12199 defaultDeviceNames[1] =
"dsnoop";
12200 defaultDeviceNames[2] =
"dsnoop:0";
12201 defaultDeviceNames[3] =
"dsnoop:0,0";
12203 defaultDeviceNames[4] =
"hw";
12204 defaultDeviceNames[5] =
"hw:0";
12205 defaultDeviceNames[6] =
"hw:0,0";
12209 for (
i = 0;
i < ma_countof(defaultDeviceNames); ++
i) {
12210 if (defaultDeviceNames[
i] !=
NULL && defaultDeviceNames[
i][0] !=
'\0') {
12211 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, defaultDeviceNames[
i], stream, openMode) == 0) {
12218 if (!isDeviceOpen) {
12234 if (deviceID.alsa[0] !=
':') {
12236 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, deviceID.alsa, stream, openMode) == 0) {
12243 if (deviceID.alsa[1] ==
'\0') {
12244 deviceID.alsa[0] =
'\0';
12249 ma_strcpy_s(hwid,
sizeof(hwid),
"dmix");
12251 ma_strcpy_s(hwid,
sizeof(hwid),
"dsnoop");
12254 if (ma_strcat_s(hwid,
sizeof(hwid), deviceID.alsa) == 0) {
12255 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid, stream, openMode) == 0) {
12262 if (!isDeviceOpen) {
12263 ma_strcpy_s(hwid,
sizeof(hwid),
"hw");
12264 if (ma_strcat_s(hwid,
sizeof(hwid), deviceID.alsa) == 0) {
12265 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid, stream, openMode) == 0) {
12272 if (!isDeviceOpen) {
12284 ma_assert(pContext !=
NULL);
12285 ma_assert(pID0 !=
NULL);
12286 ma_assert(pID1 !=
NULL);
12289 return ma_strcmp(pID0->alsa, pID1->alsa) == 0;
12295 char** ppDeviceHints;
12298 char** ppNextDeviceHint;
12300 ma_assert(pContext !=
NULL);
12301 ma_assert(callback !=
NULL);
12305 if (((ma_snd_device_name_hint_proc)pContext->alsa.snd_device_name_hint)(-1,
"pcm", (
void***)&ppDeviceHints) < 0) {
12310 ppNextDeviceHint = ppDeviceHints;
12311 while (*ppNextDeviceHint !=
NULL) {
12312 char* NAME = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"NAME");
12313 char* DESC = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"DESC");
12314 char* IOID = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"IOID");
12317 char hwid[
sizeof(pUniqueIDs->alsa)];
12320 if ((IOID ==
NULL || ma_strcmp(IOID,
"Output") == 0)) {
12323 if ((IOID !=
NULL && ma_strcmp(IOID,
"Input" ) == 0)) {
12327 if (NAME !=
NULL) {
12328 if (pContext->alsa.useVerboseDeviceEnumeration) {
12330 ma_strncpy_s(hwid,
sizeof(hwid), NAME, (
size_t)-1);
12333 if (ma_convert_device_name_to_hw_format__alsa(pContext, hwid,
sizeof(hwid), NAME) == 0) {
12341 char* src = hwid+2;
12342 while ((*dst++ = *src++));
12345 ma_strncpy_s(hwid,
sizeof(hwid), NAME, (
size_t)-1);
12348 if (ma_does_id_exist_in_list__alsa(pUniqueIDs, uniqueIDCount, hwid)) {
12353 if (pNewUniqueIDs ==
NULL) {
12357 pUniqueIDs = pNewUniqueIDs;
12358 ma_copy_memory(pUniqueIDs[uniqueIDCount].alsa, hwid,
sizeof(hwid));
12359 uniqueIDCount += 1;
12363 ma_zero_memory(hwid,
sizeof(hwid));
12366 ma_zero_object(&deviceInfo);
12367 ma_strncpy_s(deviceInfo.id.alsa,
sizeof(deviceInfo.id.alsa), hwid, (
size_t)-1);
12380 if (DESC !=
NULL) {
12382 const char* line2 = ma_find_char(DESC,
'\n', &lfPos);
12383 if (line2 !=
NULL) {
12386 if (pContext->alsa.useVerboseDeviceEnumeration) {
12388 ma_strncpy_s(deviceInfo.name,
sizeof(deviceInfo.name), DESC, lfPos);
12389 ma_strcat_s (deviceInfo.name,
sizeof(deviceInfo.name),
" (");
12390 ma_strcat_s (deviceInfo.name,
sizeof(deviceInfo.name), line2);
12391 ma_strcat_s (deviceInfo.name,
sizeof(deviceInfo.name),
")");
12394 ma_strncpy_s(deviceInfo.name,
sizeof(deviceInfo.name), DESC, lfPos);
12398 ma_strncpy_s(deviceInfo.name,
sizeof(deviceInfo.name), DESC, (
size_t)-1);
12402 if (!ma_is_device_blacklisted__alsa(deviceType, NAME)) {
12403 cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
12411 if (ma_is_common_device_name__alsa(NAME)) {
12413 if (!ma_is_capture_device_blacklisted__alsa(NAME)) {
12417 if (!ma_is_playback_device_blacklisted__alsa(NAME)) {
12432 ppNextDeviceHint += 1;
12435 if (stopEnumeration) {
12441 ((ma_snd_device_name_free_hint_proc)pContext->alsa.snd_device_name_free_hint)((
void**)ppDeviceHints);
12456 } ma_context_get_device_info_enum_callback_data__alsa;
12460 ma_context_get_device_info_enum_callback_data__alsa* pData = (ma_context_get_device_info_enum_callback_data__alsa*)pUserData;
12461 ma_assert(pData !=
NULL);
12463 if (pData->pDeviceID ==
NULL && ma_strcmp(pDeviceInfo->
id.alsa,
"default") == 0) {
12464 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pDeviceInfo->
name, (
size_t)-1);
12465 pData->foundDevice =
MA_TRUE;
12467 if (pData->deviceType == deviceType && ma_context_is_device_id_equal__alsa(pContext, pData->pDeviceID, &pDeviceInfo->
id)) {
12468 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pDeviceInfo->
name, (
size_t)-1);
12469 pData->foundDevice =
MA_TRUE;
12474 return !pData->foundDevice;
12479 ma_context_get_device_info_enum_callback_data__alsa data;
12481 ma_snd_pcm_t* pPCM;
12482 ma_snd_pcm_hw_params_t* pHWParams;
12483 ma_snd_pcm_format_mask_t* pFormatMask;
12484 int sampleRateDir = 0;
12486 ma_assert(pContext !=
NULL);
12489 data.deviceType = deviceType;
12490 data.pDeviceID = pDeviceID;
12491 data.shareMode = shareMode;
12492 data.pDeviceInfo = pDeviceInfo;
12494 result = ma_context_enumerate_devices__alsa(pContext, ma_context_get_device_info_enum_callback__alsa, &data);
12499 if (!data.foundDevice) {
12504 result = ma_context_open_pcm__alsa(pContext, shareMode, deviceType, pDeviceID, &pPCM);
12510 pHWParams = (ma_snd_pcm_hw_params_t*)calloc(1, ((ma_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
12511 if (pHWParams ==
NULL) {
12515 if (((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams) < 0) {
12519 ((ma_snd_pcm_hw_params_get_channels_min_proc)pContext->alsa.snd_pcm_hw_params_get_channels_min)(pHWParams, &pDeviceInfo->
minChannels);
12520 ((ma_snd_pcm_hw_params_get_channels_max_proc)pContext->alsa.snd_pcm_hw_params_get_channels_max)(pHWParams, &pDeviceInfo->
maxChannels);
12521 ((ma_snd_pcm_hw_params_get_rate_min_proc)pContext->alsa.snd_pcm_hw_params_get_rate_min)(pHWParams, &pDeviceInfo->
minSampleRate, &sampleRateDir);
12522 ((ma_snd_pcm_hw_params_get_rate_max_proc)pContext->alsa.snd_pcm_hw_params_get_rate_max)(pHWParams, &pDeviceInfo->
maxSampleRate, &sampleRateDir);
12525 pFormatMask = (ma_snd_pcm_format_mask_t*)calloc(1, ((ma_snd_pcm_format_mask_sizeof_proc)pContext->alsa.snd_pcm_format_mask_sizeof)());
12526 if (pFormatMask ==
NULL) {
12530 ((ma_snd_pcm_hw_params_get_format_mask_proc)pContext->alsa.snd_pcm_hw_params_get_format_mask)(pHWParams, pFormatMask);
12533 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_U8)) {
12536 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_S16_LE)) {
12539 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_S24_3LE)) {
12542 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_S32_LE)) {
12545 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_FLOAT_LE)) {
12552 ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
12566 ma_assert(pDevice !=
NULL);
12568 if (pRequiresRestart) *pRequiresRestart =
MA_FALSE;
12571 ma_uint32 periodSizeInFrames = pDevice->bufferSizeInFrames / pDevice->periods;
12572 while (!pDevice->alsa.breakFromMainLoop) {
12573 ma_snd_pcm_sframes_t framesAvailable = ((ma_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((ma_snd_pcm_t*)pDevice->alsa.pPCM);
12574 if (framesAvailable < 0) {
12575 if (framesAvailable == -EPIPE) {
12576 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, framesAvailable,
MA_TRUE) < 0) {
12581 if (pRequiresRestart) {
12586 framesAvailable = ((ma_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((ma_snd_pcm_t*)pDevice->alsa.pPCM);
12587 if (framesAvailable < 0) {
12593 if (framesAvailable >= periodSizeInFrames) {
12594 return periodSizeInFrames;
12597 if (framesAvailable < periodSizeInFrames) {
12599 int waitResult = ((ma_snd_pcm_wait_proc)pDevice->pContext->alsa.snd_pcm_wait)((ma_snd_pcm_t*)pDevice->alsa.pPCM, -1);
12600 if (waitResult < 0) {
12601 if (waitResult == -EPIPE) {
12602 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, waitResult,
MA_TRUE) < 0) {
12607 if (pRequiresRestart) {
12616 ma_snd_pcm_sframes_t framesAvailable = ((ma_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((ma_snd_pcm_t*)pDevice->alsa.pPCM);
12617 if (framesAvailable < 0) {
12621 return framesAvailable;
12626 ma_assert(pDevice !=
NULL);
12630 if (pDevice->alsa.breakFromMainLoop) {
12634 if (pDevice->alsa.isUsingMMap) {
12637 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice, &requiresRestart);
12638 if (framesAvailable == 0) {
12643 if (pDevice->alsa.breakFromMainLoop) {
12647 const ma_snd_pcm_channel_area_t* pAreas;
12648 ma_snd_pcm_uframes_t mappedOffset;
12649 ma_snd_pcm_uframes_t mappedFrames = framesAvailable;
12650 while (framesAvailable > 0) {
12651 int result = ((ma_snd_pcm_mmap_begin_proc)pDevice->pContext->alsa.snd_pcm_mmap_begin)((ma_snd_pcm_t*)pDevice->alsa.pPCM, &pAreas, &mappedOffset, &mappedFrames);
12656 if (mappedFrames > 0) {
12657 void* pBuffer = (
ma_uint8*)pAreas[0].addr + ((pAreas[0].
first + (mappedOffset * pAreas[0].step)) / 8);
12658 ma_device__read_frames_from_client(pDevice, mappedFrames, pBuffer);
12661 result = ((ma_snd_pcm_mmap_commit_proc)pDevice->pContext->alsa.snd_pcm_mmap_commit)((ma_snd_pcm_t*)pDevice->alsa.pPCM, mappedOffset, mappedFrames);
12662 if (result < 0 || (ma_snd_pcm_uframes_t)result != mappedFrames) {
12663 ((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, result,
MA_TRUE);
12667 if (requiresRestart) {
12668 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
12673 if (framesAvailable >= mappedFrames) {
12674 framesAvailable -= mappedFrames;
12676 framesAvailable = 0;
12681 while (!pDevice->alsa.breakFromMainLoop) {
12682 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice,
NULL);
12683 if (framesAvailable == 0) {
12688 if (pDevice->alsa.breakFromMainLoop) {
12692 ma_device__read_frames_from_client(pDevice, framesAvailable, pDevice->alsa.pIntermediaryBuffer);
12694 ma_snd_pcm_sframes_t framesWritten = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
12695 if (framesWritten < 0) {
12696 if (framesWritten == -EAGAIN) {
12698 }
else if (framesWritten == -EPIPE) {
12700 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, framesWritten,
MA_TRUE) < 0) {
12705 framesWritten = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
12706 if (framesWritten < 0) {
12727 ma_assert(pDevice !=
NULL);
12731 if (pDevice->alsa.breakFromMainLoop) {
12736 void* pBuffer =
NULL;
12737 if (pDevice->alsa.pIntermediaryBuffer ==
NULL) {
12740 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice, &requiresRestart);
12741 if (framesAvailable == 0) {
12745 const ma_snd_pcm_channel_area_t* pAreas;
12746 ma_snd_pcm_uframes_t mappedOffset;
12747 ma_snd_pcm_uframes_t mappedFrames = framesAvailable;
12748 while (framesAvailable > 0) {
12749 int result = ((ma_snd_pcm_mmap_begin_proc)pDevice->pContext->alsa.snd_pcm_mmap_begin)((ma_snd_pcm_t*)pDevice->alsa.pPCM, &pAreas, &mappedOffset, &mappedFrames);
12754 if (mappedFrames > 0) {
12755 void* pBuffer = (
ma_uint8*)pAreas[0].addr + ((pAreas[0].
first + (mappedOffset * pAreas[0].step)) / 8);
12756 ma_device__send_frames_to_client(pDevice, mappedFrames, pBuffer);
12759 result = ((ma_snd_pcm_mmap_commit_proc)pDevice->pContext->alsa.snd_pcm_mmap_commit)((ma_snd_pcm_t*)pDevice->alsa.pPCM, mappedOffset, mappedFrames);
12760 if (result < 0 || (ma_snd_pcm_uframes_t)result != mappedFrames) {
12761 ((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, result,
MA_TRUE);
12765 if (requiresRestart) {
12766 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
12771 if (framesAvailable >= mappedFrames) {
12772 framesAvailable -= mappedFrames;
12774 framesAvailable = 0;
12779 ma_snd_pcm_sframes_t framesRead = 0;
12780 while (!pDevice->alsa.breakFromMainLoop) {
12781 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice,
NULL);
12782 if (framesAvailable == 0) {
12786 framesRead = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
12787 if (framesRead < 0) {
12788 if (framesRead == -EAGAIN) {
12790 }
else if (framesRead == -EPIPE) {
12792 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, framesRead,
MA_TRUE) < 0) {
12797 framesRead = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
12798 if (framesRead < 0) {
12812 framesToSend = framesRead;
12813 pBuffer = pDevice->alsa.pIntermediaryBuffer;
12816 if (framesToSend > 0) {
12817 ma_device__send_frames_to_client(pDevice, framesToSend, pBuffer);
12824 void ma_device_uninit__alsa(
ma_device* pDevice)
12826 ma_assert(pDevice !=
NULL);
12828 if ((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) {
12829 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
12832 if ((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) {
12833 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
12840 ma_snd_pcm_t* pPCM;
12842 ma_snd_pcm_format_t formatALSA;
12851 ma_snd_pcm_hw_params_t* pHWParams;
12852 ma_snd_pcm_sw_params_t* pSWParams;
12853 ma_snd_pcm_uframes_t bufferBoundary;
12854 float bufferSizeScaleFactor;
12856 ma_assert(pContext !=
NULL);
12857 ma_assert(pConfig !=
NULL);
12859 ma_assert(pDevice !=
NULL);
12865 result = ma_context_open_pcm__alsa(pContext, shareMode, deviceType, pDeviceID, &pPCM);
12871 bufferSizeScaleFactor = 1;
12872 if (pDevice->usingDefaultBufferSize) {
12873 ma_snd_pcm_info_t* pInfo = (ma_snd_pcm_info_t*)calloc(1, ((ma_snd_pcm_info_sizeof_proc)pContext->alsa.snd_pcm_info_sizeof)());
12874 if (pInfo ==
NULL) {
12879 if (((ma_snd_pcm_info_proc)pContext->alsa.snd_pcm_info)(pPCM, pInfo) == 0) {
12880 const char* deviceName = ((ma_snd_pcm_info_get_name_proc)pContext->alsa.snd_pcm_info_get_name)(pInfo);
12881 if (deviceName !=
NULL) {
12882 if (ma_strcmp(deviceName,
"default") == 0) {
12883 char** ppDeviceHints;
12884 char** ppNextDeviceHint;
12887 if (((ma_snd_device_name_hint_proc)pContext->alsa.snd_device_name_hint)(-1,
"pcm", (
void***)&ppDeviceHints) < 0) {
12892 ppNextDeviceHint = ppDeviceHints;
12893 while (*ppNextDeviceHint !=
NULL) {
12894 char* NAME = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"NAME");
12895 char* DESC = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"DESC");
12896 char* IOID = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"IOID");
12901 if (ma_strcmp(NAME, deviceName) == 0) {
12902 bufferSizeScaleFactor = ma_find_default_buffer_size_scale__alsa(DESC);
12910 ppNextDeviceHint += 1;
12917 ((ma_snd_device_name_free_hint_proc)pContext->alsa.snd_device_name_free_hint)((
void**)ppDeviceHints);
12919 bufferSizeScaleFactor = ma_find_default_buffer_size_scale__alsa(deviceName);
12929 pHWParams = (ma_snd_pcm_hw_params_t*)calloc(1, ((ma_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
12930 if (pHWParams ==
NULL) {
12934 if (((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams) < 0) {
12936 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
12944 if (!pConfig->
alsa.
noMMap && ma_device__is_async(pDevice)) {
12945 if (((ma_snd_pcm_hw_params_set_access_proc)pContext->alsa.snd_pcm_hw_params_set_access)(pPCM, pHWParams, MA_SND_PCM_ACCESS_MMAP_INTERLEAVED) == 0) {
12946 pDevice->alsa.isUsingMMap =
MA_TRUE;
12952 if (!isUsingMMap) {
12953 if (((ma_snd_pcm_hw_params_set_access_proc)pContext->alsa.snd_pcm_hw_params_set_access)(pPCM, pHWParams, MA_SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
12955 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
12956 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[ALSA] Failed to set access mode to neither SND_PCM_ACCESS_MMAP_INTERLEAVED nor SND_PCM_ACCESS_RW_INTERLEAVED. snd_pcm_hw_params_set_access() failed.",
MA_FORMAT_NOT_SUPPORTED);
12967 ma_snd_pcm_format_mask_t* pFormatMask;
12970 pFormatMask = (ma_snd_pcm_format_mask_t*)calloc(1, ((ma_snd_pcm_format_mask_sizeof_proc)pContext->alsa.snd_pcm_format_mask_sizeof)());
12971 if (pFormatMask ==
NULL) {
12973 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
12977 ((ma_snd_pcm_hw_params_get_format_mask_proc)pContext->alsa.snd_pcm_hw_params_get_format_mask)(pHWParams, pFormatMask);
12983 if (!((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, formatALSA)) {
12987 ma_snd_pcm_format_t preferredFormatsALSA[] = {
12988 MA_SND_PCM_FORMAT_S16_LE,
12989 MA_SND_PCM_FORMAT_FLOAT_LE,
12990 MA_SND_PCM_FORMAT_S32_LE,
12991 MA_SND_PCM_FORMAT_S24_3LE,
12992 MA_SND_PCM_FORMAT_U8
12995 if (ma_is_big_endian()) {
12996 preferredFormatsALSA[0] = MA_SND_PCM_FORMAT_S16_BE;
12997 preferredFormatsALSA[1] = MA_SND_PCM_FORMAT_FLOAT_BE;
12998 preferredFormatsALSA[2] = MA_SND_PCM_FORMAT_S32_BE;
12999 preferredFormatsALSA[3] = MA_SND_PCM_FORMAT_S24_3BE;
13000 preferredFormatsALSA[4] = MA_SND_PCM_FORMAT_U8;
13003 formatALSA = MA_SND_PCM_FORMAT_UNKNOWN;
13004 for (
i = 0;
i < (
sizeof(preferredFormatsALSA) /
sizeof(preferredFormatsALSA[0])); ++
i) {
13005 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, preferredFormatsALSA[
i])) {
13006 formatALSA = preferredFormatsALSA[
i];
13011 if (formatALSA == MA_SND_PCM_FORMAT_UNKNOWN) {
13013 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13019 pFormatMask =
NULL;
13021 if (((ma_snd_pcm_hw_params_set_format_proc)pContext->alsa.snd_pcm_hw_params_set_format)(pPCM, pHWParams, formatALSA) < 0) {
13023 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13030 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13038 if (((ma_snd_pcm_hw_params_set_channels_near_proc)pContext->alsa.snd_pcm_hw_params_set_channels_near)(pPCM, pHWParams, &
channels) < 0) {
13040 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13048 unsigned int sampleRate;
13067 ((ma_snd_pcm_hw_params_set_rate_resample_proc)pContext->alsa.snd_pcm_hw_params_set_rate_resample)(pPCM, pHWParams, 0);
13070 if (((ma_snd_pcm_hw_params_set_rate_near_proc)pContext->alsa.snd_pcm_hw_params_set_rate_near)(pPCM, pHWParams, &sampleRate, 0) < 0) {
13072 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13075 internalSampleRate = (
ma_uint32)sampleRate;
13081 if (actualBufferSizeInFrames == 0) {
13085 if (((ma_snd_pcm_hw_params_set_buffer_size_near_proc)pContext->alsa.snd_pcm_hw_params_set_buffer_size_near)(pPCM, pHWParams, &actualBufferSizeInFrames) < 0) {
13087 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13090 internalBufferSizeInFrames = actualBufferSizeInFrames;
13096 if (((ma_snd_pcm_hw_params_set_periods_near_proc)pContext->alsa.snd_pcm_hw_params_set_periods_near)(pPCM, pHWParams, &periods,
NULL) < 0) {
13098 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13101 internalPeriods = periods;
13105 if (((ma_snd_pcm_hw_params_proc)pContext->alsa.snd_pcm_hw_params)(pPCM, pHWParams) < 0) {
13107 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13116 pSWParams = (ma_snd_pcm_sw_params_t*)calloc(1, ((ma_snd_pcm_sw_params_sizeof_proc)pContext->alsa.snd_pcm_sw_params_sizeof)());
13117 if (pSWParams ==
NULL) {
13118 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13122 if (((ma_snd_pcm_sw_params_current_proc)pContext->alsa.snd_pcm_sw_params_current)(pPCM, pSWParams) != 0) {
13124 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13129 if (((ma_snd_pcm_sw_params_set_avail_min_proc)pContext->alsa.snd_pcm_sw_params_set_avail_min)(pPCM, pSWParams, 1) != 0) {
13131 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13135 if (((ma_snd_pcm_sw_params_set_avail_min_proc)pContext->alsa.snd_pcm_sw_params_set_avail_min)(pPCM, pSWParams, 1) != 0) {
13137 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13143 if (((ma_snd_pcm_sw_params_get_boundary_proc)pContext->alsa.snd_pcm_sw_params_get_boundary)(pSWParams, &bufferBoundary) < 0) {
13144 bufferBoundary = internalBufferSizeInFrames;
13154 if (((ma_snd_pcm_sw_params_set_start_threshold_proc)pContext->alsa.snd_pcm_sw_params_set_start_threshold)(pPCM, pSWParams, internalBufferSizeInFrames) != 0) {
13156 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13159 if (((ma_snd_pcm_sw_params_set_stop_threshold_proc)pContext->alsa.snd_pcm_sw_params_set_stop_threshold)(pPCM, pSWParams, bufferBoundary) != 0) {
13161 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13166 if (((ma_snd_pcm_sw_params_proc)pContext->alsa.snd_pcm_sw_params)(pPCM, pSWParams) != 0) {
13168 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13178 ma_snd_pcm_chmap_t* pChmap = ((ma_snd_pcm_get_chmap_proc)pContext->alsa.snd_pcm_get_chmap)(pPCM);
13179 if (pChmap !=
NULL) {
13183 if (pChmap->channels >= internalChannels) {
13185 for (iChannel = 0; iChannel < internalChannels; ++iChannel) {
13186 internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
13201 for (iChannel = 0; iChannel < pChmap->channels; ++iChannel) {
13202 internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
13206 for (
i = 0;
i < internalChannels && isValid; ++
i) {
13208 for (
j =
i+1;
j < internalChannels; ++
j) {
13209 if (internalChannelMap[
i] == internalChannelMap[
j]) {
13232 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)(pPCM) < 0) {
13233 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13239 pDevice->alsa.pPCMCapture = (
ma_ptr)pPCM;
13240 pDevice->alsa.isUsingMMapCapture = isUsingMMap;
13242 pDevice->capture.internalChannels = internalChannels;
13243 pDevice->capture.internalSampleRate = internalSampleRate;
13244 ma_channel_map_copy(pDevice->capture.internalChannelMap, internalChannelMap, internalChannels);
13245 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
13246 pDevice->capture.internalPeriods = internalPeriods;
13248 pDevice->alsa.pPCMPlayback = (
ma_ptr)pPCM;
13249 pDevice->alsa.isUsingMMapPlayback = isUsingMMap;
13251 pDevice->playback.internalChannels = internalChannels;
13252 pDevice->playback.internalSampleRate = internalSampleRate;
13253 ma_channel_map_copy(pDevice->playback.internalChannelMap, internalChannelMap, internalChannels);
13254 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
13255 pDevice->playback.internalPeriods = internalPeriods;
13263 ma_assert(pDevice !=
NULL);
13265 ma_zero_object(&pDevice->alsa);
13287 ma_assert(pDevice !=
NULL);
13290 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
13299 if (!ma_device_read_from_client_and_write__alsa(pDevice)) {
13304 if (pDevice->alsa.isUsingMMap) {
13305 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
13310 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
13321 ma_assert(pDevice !=
NULL);
13324 ((ma_snd_pcm_drain_proc)pDevice->pContext->alsa.snd_pcm_drain)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
13327 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
13328 #ifdef MA_DEBUG_OUTPUT
13329 printf(
"[ALSA] Failed to prepare capture device after stopping.\n");
13336 ((ma_snd_pcm_drain_proc)pDevice->pContext->alsa.snd_pcm_drain)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
13339 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) < 0) {
13340 #ifdef MA_DEBUG_OUTPUT
13341 printf(
"[ALSA] Failed to prepare playback device after stopping.\n");
13353 ma_snd_pcm_sframes_t resultALSA;
13356 ma_assert(pDevice !=
NULL);
13357 ma_assert(pPCMFrames !=
NULL);
13361 totalPCMFramesProcessed = 0;
13362 while (totalPCMFramesProcessed < frameCount) {
13363 const void* pSrc = ma_offset_ptr(pPCMFrames, totalPCMFramesProcessed *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
13364 ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
13368 resultALSA = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, pSrc, framesRemaining);
13369 if (resultALSA < 0) {
13370 if (resultALSA == -EAGAIN) {
13373 }
else if (resultALSA == -EPIPE) {
13377 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, resultALSA,
MA_TRUE) < 0) {
13388 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) < 0) {
13392 resultALSA = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, pSrc, framesRemaining);
13393 if (resultALSA < 0) {
13399 totalPCMFramesProcessed += resultALSA;
13407 ma_snd_pcm_sframes_t resultALSA;
13410 ma_assert(pDevice !=
NULL);
13411 ma_assert(pPCMFrames !=
NULL);
13414 if (((ma_snd_pcm_state_proc)pDevice->pContext->alsa.snd_pcm_state)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) != MA_SND_PCM_STATE_RUNNING) {
13415 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
13420 totalPCMFramesProcessed = 0;
13421 while (totalPCMFramesProcessed < frameCount) {
13422 void* pDst = ma_offset_ptr(pPCMFrames, totalPCMFramesProcessed *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
13423 ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
13427 resultALSA = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, pDst, framesRemaining);
13428 if (resultALSA < 0) {
13429 if (resultALSA == -EAGAIN) {
13432 }
else if (resultALSA == -EPIPE) {
13436 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, resultALSA,
MA_TRUE) < 0) {
13440 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
13444 resultALSA = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, pDst, framesRemaining);
13445 if (resultALSA < 0) {
13451 totalPCMFramesProcessed += resultALSA;
13460 ma_assert(pDevice !=
NULL);
13462 pDevice->alsa.breakFromMainLoop =
MA_TRUE;
13468 ma_assert(pDevice !=
NULL);
13470 pDevice->alsa.breakFromMainLoop =
MA_FALSE;
13473 while (!pDevice->alsa.breakFromMainLoop && ma_device_read_from_client_and_write__alsa(pDevice)) {
13477 while (!pDevice->alsa.breakFromMainLoop && ma_device_read_and_send_to_client__alsa(pDevice)) {
13487 ma_assert(pContext !=
NULL);
13491 ((ma_snd_config_update_free_global_proc)pContext->alsa.snd_config_update_free_global)();
13493 #ifndef MA_NO_RUNTIME_LINKING
13494 ma_dlclose(pContext, pContext->alsa.asoundSO);
13504 #ifndef MA_NO_RUNTIME_LINKING
13505 const char* libasoundNames[] = {
13511 for (
i = 0;
i < ma_countof(libasoundNames); ++
i) {
13512 pContext->alsa.asoundSO = ma_dlopen(pContext, libasoundNames[
i]);
13513 if (pContext->alsa.asoundSO !=
NULL) {
13518 if (pContext->alsa.asoundSO ==
NULL) {
13519 #ifdef MA_DEBUG_OUTPUT
13520 printf(
"[ALSA] Failed to open shared object.\n");
13525 pContext->alsa.snd_pcm_open = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_open");
13526 pContext->alsa.snd_pcm_close = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_close");
13527 pContext->alsa.snd_pcm_hw_params_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_sizeof");
13528 pContext->alsa.snd_pcm_hw_params_any = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_any");
13529 pContext->alsa.snd_pcm_hw_params_set_format = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_format");
13530 pContext->alsa.snd_pcm_hw_params_set_format_first = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_format_first");
13531 pContext->alsa.snd_pcm_hw_params_get_format_mask = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_format_mask");
13532 pContext->alsa.snd_pcm_hw_params_set_channels_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_channels_near");
13533 pContext->alsa.snd_pcm_hw_params_set_rate_resample = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_rate_resample");
13534 pContext->alsa.snd_pcm_hw_params_set_rate_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_rate_near");
13535 pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_buffer_size_near");
13536 pContext->alsa.snd_pcm_hw_params_set_periods_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_periods_near");
13537 pContext->alsa.snd_pcm_hw_params_set_access = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_access");
13538 pContext->alsa.snd_pcm_hw_params_get_format = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_format");
13539 pContext->alsa.snd_pcm_hw_params_get_channels = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_channels");
13540 pContext->alsa.snd_pcm_hw_params_get_channels_min = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_channels_min");
13541 pContext->alsa.snd_pcm_hw_params_get_channels_max = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_channels_max");
13542 pContext->alsa.snd_pcm_hw_params_get_rate = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_rate");
13543 pContext->alsa.snd_pcm_hw_params_get_rate_min = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_rate_min");
13544 pContext->alsa.snd_pcm_hw_params_get_rate_max = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_rate_max");
13545 pContext->alsa.snd_pcm_hw_params_get_buffer_size = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_buffer_size");
13546 pContext->alsa.snd_pcm_hw_params_get_periods = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_periods");
13547 pContext->alsa.snd_pcm_hw_params_get_access = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_access");
13548 pContext->alsa.snd_pcm_hw_params = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params");
13549 pContext->alsa.snd_pcm_sw_params_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_sizeof");
13550 pContext->alsa.snd_pcm_sw_params_current = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_current");
13551 pContext->alsa.snd_pcm_sw_params_get_boundary = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_get_boundary");
13552 pContext->alsa.snd_pcm_sw_params_set_avail_min = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_set_avail_min");
13553 pContext->alsa.snd_pcm_sw_params_set_start_threshold = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_set_start_threshold");
13554 pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_set_stop_threshold");
13555 pContext->alsa.snd_pcm_sw_params = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params");
13556 pContext->alsa.snd_pcm_format_mask_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_format_mask_sizeof");
13557 pContext->alsa.snd_pcm_format_mask_test = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_format_mask_test");
13558 pContext->alsa.snd_pcm_get_chmap = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_get_chmap");
13559 pContext->alsa.snd_pcm_state = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_state");
13560 pContext->alsa.snd_pcm_prepare = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_prepare");
13561 pContext->alsa.snd_pcm_start = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_start");
13562 pContext->alsa.snd_pcm_drop = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_drop");
13563 pContext->alsa.snd_pcm_drain = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_drain");
13564 pContext->alsa.snd_device_name_hint = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_device_name_hint");
13565 pContext->alsa.snd_device_name_get_hint = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_device_name_get_hint");
13566 pContext->alsa.snd_card_get_index = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_card_get_index");
13567 pContext->alsa.snd_device_name_free_hint = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_device_name_free_hint");
13568 pContext->alsa.snd_pcm_mmap_begin = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_mmap_begin");
13569 pContext->alsa.snd_pcm_mmap_commit = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_mmap_commit");
13570 pContext->alsa.snd_pcm_recover = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_recover");
13571 pContext->alsa.snd_pcm_readi = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_readi");
13572 pContext->alsa.snd_pcm_writei = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_writei");
13573 pContext->alsa.snd_pcm_avail = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_avail");
13574 pContext->alsa.snd_pcm_avail_update = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_avail_update");
13575 pContext->alsa.snd_pcm_wait = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_wait");
13576 pContext->alsa.snd_pcm_info = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_info");
13577 pContext->alsa.snd_pcm_info_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_info_sizeof");
13578 pContext->alsa.snd_pcm_info_get_name = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_info_get_name");
13579 pContext->alsa.snd_config_update_free_global = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_config_update_free_global");
13582 ma_snd_pcm_open_proc _snd_pcm_open = snd_pcm_open;
13583 ma_snd_pcm_close_proc _snd_pcm_close = snd_pcm_close;
13584 ma_snd_pcm_hw_params_sizeof_proc _snd_pcm_hw_params_sizeof = snd_pcm_hw_params_sizeof;
13585 ma_snd_pcm_hw_params_any_proc _snd_pcm_hw_params_any = snd_pcm_hw_params_any;
13586 ma_snd_pcm_hw_params_set_format_proc _snd_pcm_hw_params_set_format = snd_pcm_hw_params_set_format;
13587 ma_snd_pcm_hw_params_set_format_first_proc _snd_pcm_hw_params_set_format_first = snd_pcm_hw_params_set_format_first;
13588 ma_snd_pcm_hw_params_get_format_mask_proc _snd_pcm_hw_params_get_format_mask = snd_pcm_hw_params_get_format_mask;
13589 ma_snd_pcm_hw_params_set_channels_near_proc _snd_pcm_hw_params_set_channels_near = snd_pcm_hw_params_set_channels_near;
13590 ma_snd_pcm_hw_params_set_rate_resample_proc _snd_pcm_hw_params_set_rate_resample = snd_pcm_hw_params_set_rate_resample;
13591 ma_snd_pcm_hw_params_set_rate_near_proc _snd_pcm_hw_params_set_rate_near = snd_pcm_hw_params_set_rate_near;
13592 ma_snd_pcm_hw_params_set_buffer_size_near_proc _snd_pcm_hw_params_set_buffer_size_near = snd_pcm_hw_params_set_buffer_size_near;
13593 ma_snd_pcm_hw_params_set_periods_near_proc _snd_pcm_hw_params_set_periods_near = snd_pcm_hw_params_set_periods_near;
13594 ma_snd_pcm_hw_params_set_access_proc _snd_pcm_hw_params_set_access = snd_pcm_hw_params_set_access;
13595 ma_snd_pcm_hw_params_get_format_proc _snd_pcm_hw_params_get_format = snd_pcm_hw_params_get_format;
13596 ma_snd_pcm_hw_params_get_channels_proc _snd_pcm_hw_params_get_channels = snd_pcm_hw_params_get_channels;
13597 ma_snd_pcm_hw_params_get_channels_min_proc _snd_pcm_hw_params_get_channels_min = snd_pcm_hw_params_get_channels_min;
13598 ma_snd_pcm_hw_params_get_channels_max_proc _snd_pcm_hw_params_get_channels_max = snd_pcm_hw_params_get_channels_max;
13599 ma_snd_pcm_hw_params_get_rate_proc _snd_pcm_hw_params_get_rate = snd_pcm_hw_params_get_rate;
13600 ma_snd_pcm_hw_params_get_rate_min_proc _snd_pcm_hw_params_get_rate_min = snd_pcm_hw_params_get_rate_min;
13601 ma_snd_pcm_hw_params_get_rate_max_proc _snd_pcm_hw_params_get_rate_max = snd_pcm_hw_params_get_rate_max;
13602 ma_snd_pcm_hw_params_get_buffer_size_proc _snd_pcm_hw_params_get_buffer_size = snd_pcm_hw_params_get_buffer_size;
13603 ma_snd_pcm_hw_params_get_periods_proc _snd_pcm_hw_params_get_periods = snd_pcm_hw_params_get_periods;
13604 ma_snd_pcm_hw_params_get_access_proc _snd_pcm_hw_params_get_access = snd_pcm_hw_params_get_access;
13605 ma_snd_pcm_hw_params_proc _snd_pcm_hw_params = snd_pcm_hw_params;
13606 ma_snd_pcm_sw_params_sizeof_proc _snd_pcm_sw_params_sizeof = snd_pcm_sw_params_sizeof;
13607 ma_snd_pcm_sw_params_current_proc _snd_pcm_sw_params_current = snd_pcm_sw_params_current;
13608 ma_snd_pcm_sw_params_get_boundary_proc _snd_pcm_sw_params_get_boundary = snd_pcm_sw_params_get_boundary;
13609 ma_snd_pcm_sw_params_set_avail_min_proc _snd_pcm_sw_params_set_avail_min = snd_pcm_sw_params_set_avail_min;
13610 ma_snd_pcm_sw_params_set_start_threshold_proc _snd_pcm_sw_params_set_start_threshold = snd_pcm_sw_params_set_start_threshold;
13611 ma_snd_pcm_sw_params_set_stop_threshold_proc _snd_pcm_sw_params_set_stop_threshold = snd_pcm_sw_params_set_stop_threshold;
13612 ma_snd_pcm_sw_params_proc _snd_pcm_sw_params = snd_pcm_sw_params;
13613 ma_snd_pcm_format_mask_sizeof_proc _snd_pcm_format_mask_sizeof = snd_pcm_format_mask_sizeof;
13614 ma_snd_pcm_format_mask_test_proc _snd_pcm_format_mask_test = snd_pcm_format_mask_test;
13615 ma_snd_pcm_get_chmap_proc _snd_pcm_get_chmap = snd_pcm_get_chmap;
13616 ma_snd_pcm_state_proc _snd_pcm_state = snd_pcm_state;
13617 ma_snd_pcm_prepare_proc _snd_pcm_prepare = snd_pcm_prepare;
13618 ma_snd_pcm_start_proc _snd_pcm_start = snd_pcm_start;
13619 ma_snd_pcm_drop_proc _snd_pcm_drop = snd_pcm_drop;
13620 ma_snd_pcm_drain_proc _snd_pcm_drain = snd_pcm_drain;
13621 ma_snd_device_name_hint_proc _snd_device_name_hint = snd_device_name_hint;
13622 ma_snd_device_name_get_hint_proc _snd_device_name_get_hint = snd_device_name_get_hint;
13623 ma_snd_card_get_index_proc _snd_card_get_index = snd_card_get_index;
13624 ma_snd_device_name_free_hint_proc _snd_device_name_free_hint = snd_device_name_free_hint;
13625 ma_snd_pcm_mmap_begin_proc _snd_pcm_mmap_begin = snd_pcm_mmap_begin;
13626 ma_snd_pcm_mmap_commit_proc _snd_pcm_mmap_commit = snd_pcm_mmap_commit;
13627 ma_snd_pcm_recover_proc _snd_pcm_recover = snd_pcm_recover;
13628 ma_snd_pcm_readi_proc _snd_pcm_readi = snd_pcm_readi;
13629 ma_snd_pcm_writei_proc _snd_pcm_writei = snd_pcm_writei;
13630 ma_snd_pcm_avail_proc _snd_pcm_avail = snd_pcm_avail;
13631 ma_snd_pcm_avail_update_proc _snd_pcm_avail_update = snd_pcm_avail_update;
13632 ma_snd_pcm_wait_proc _snd_pcm_wait = snd_pcm_wait;
13633 ma_snd_pcm_info_proc _snd_pcm_info = snd_pcm_info;
13634 ma_snd_pcm_info_sizeof_proc _snd_pcm_info_sizeof = snd_pcm_info_sizeof;
13635 ma_snd_pcm_info_get_name_proc _snd_pcm_info_get_name = snd_pcm_info_get_name;
13636 ma_snd_config_update_free_global_proc _snd_config_update_free_global = snd_config_update_free_global;
13638 pContext->alsa.snd_pcm_open = (
ma_proc)_snd_pcm_open;
13639 pContext->alsa.snd_pcm_close = (
ma_proc)_snd_pcm_close;
13640 pContext->alsa.snd_pcm_hw_params_sizeof = (
ma_proc)_snd_pcm_hw_params_sizeof;
13641 pContext->alsa.snd_pcm_hw_params_any = (
ma_proc)_snd_pcm_hw_params_any;
13642 pContext->alsa.snd_pcm_hw_params_set_format = (
ma_proc)_snd_pcm_hw_params_set_format;
13643 pContext->alsa.snd_pcm_hw_params_set_format_first = (
ma_proc)_snd_pcm_hw_params_set_format_first;
13644 pContext->alsa.snd_pcm_hw_params_get_format_mask = (
ma_proc)_snd_pcm_hw_params_get_format_mask;
13645 pContext->alsa.snd_pcm_hw_params_set_channels_near = (
ma_proc)_snd_pcm_hw_params_set_channels_near;
13646 pContext->alsa.snd_pcm_hw_params_set_rate_resample = (
ma_proc)_snd_pcm_hw_params_set_rate_resample;
13647 pContext->alsa.snd_pcm_hw_params_set_rate_near = (
ma_proc)_snd_pcm_hw_params_set_rate_near;
13648 pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (
ma_proc)_snd_pcm_hw_params_set_buffer_size_near;
13649 pContext->alsa.snd_pcm_hw_params_set_periods_near = (
ma_proc)_snd_pcm_hw_params_set_periods_near;
13650 pContext->alsa.snd_pcm_hw_params_set_access = (
ma_proc)_snd_pcm_hw_params_set_access;
13651 pContext->alsa.snd_pcm_hw_params_get_format = (
ma_proc)_snd_pcm_hw_params_get_format;
13652 pContext->alsa.snd_pcm_hw_params_get_channels = (
ma_proc)_snd_pcm_hw_params_get_channels;
13653 pContext->alsa.snd_pcm_hw_params_get_channels_min = (
ma_proc)_snd_pcm_hw_params_get_channels_min;
13654 pContext->alsa.snd_pcm_hw_params_get_channels_max = (
ma_proc)_snd_pcm_hw_params_get_channels_max;
13655 pContext->alsa.snd_pcm_hw_params_get_rate = (
ma_proc)_snd_pcm_hw_params_get_rate;
13656 pContext->alsa.snd_pcm_hw_params_get_buffer_size = (
ma_proc)_snd_pcm_hw_params_get_buffer_size;
13657 pContext->alsa.snd_pcm_hw_params_get_periods = (
ma_proc)_snd_pcm_hw_params_get_periods;
13658 pContext->alsa.snd_pcm_hw_params_get_access = (
ma_proc)_snd_pcm_hw_params_get_access;
13659 pContext->alsa.snd_pcm_hw_params = (
ma_proc)_snd_pcm_hw_params;
13660 pContext->alsa.snd_pcm_sw_params_sizeof = (
ma_proc)_snd_pcm_sw_params_sizeof;
13661 pContext->alsa.snd_pcm_sw_params_current = (
ma_proc)_snd_pcm_sw_params_current;
13662 pContext->alsa.snd_pcm_sw_params_get_boundary = (
ma_proc)_snd_pcm_sw_params_get_boundary;
13663 pContext->alsa.snd_pcm_sw_params_set_avail_min = (
ma_proc)_snd_pcm_sw_params_set_avail_min;
13664 pContext->alsa.snd_pcm_sw_params_set_start_threshold = (
ma_proc)_snd_pcm_sw_params_set_start_threshold;
13665 pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (
ma_proc)_snd_pcm_sw_params_set_stop_threshold;
13666 pContext->alsa.snd_pcm_sw_params = (
ma_proc)_snd_pcm_sw_params;
13667 pContext->alsa.snd_pcm_format_mask_sizeof = (
ma_proc)_snd_pcm_format_mask_sizeof;
13668 pContext->alsa.snd_pcm_format_mask_test = (
ma_proc)_snd_pcm_format_mask_test;
13669 pContext->alsa.snd_pcm_get_chmap = (
ma_proc)_snd_pcm_get_chmap;
13670 pContext->alsa.snd_pcm_state = (
ma_proc)_snd_pcm_state;
13671 pContext->alsa.snd_pcm_prepare = (
ma_proc)_snd_pcm_prepare;
13672 pContext->alsa.snd_pcm_start = (
ma_proc)_snd_pcm_start;
13673 pContext->alsa.snd_pcm_drop = (
ma_proc)_snd_pcm_drop;
13674 pContext->alsa.snd_pcm_drain = (
ma_proc)_snd_pcm_drain;
13675 pContext->alsa.snd_device_name_hint = (
ma_proc)_snd_device_name_hint;
13676 pContext->alsa.snd_device_name_get_hint = (
ma_proc)_snd_device_name_get_hint;
13677 pContext->alsa.snd_card_get_index = (
ma_proc)_snd_card_get_index;
13678 pContext->alsa.snd_device_name_free_hint = (
ma_proc)_snd_device_name_free_hint;
13679 pContext->alsa.snd_pcm_mmap_begin = (
ma_proc)_snd_pcm_mmap_begin;
13680 pContext->alsa.snd_pcm_mmap_commit = (
ma_proc)_snd_pcm_mmap_commit;
13681 pContext->alsa.snd_pcm_recover = (
ma_proc)_snd_pcm_recover;
13682 pContext->alsa.snd_pcm_readi = (
ma_proc)_snd_pcm_readi;
13683 pContext->alsa.snd_pcm_writei = (
ma_proc)_snd_pcm_writei;
13684 pContext->alsa.snd_pcm_avail = (
ma_proc)_snd_pcm_avail;
13685 pContext->alsa.snd_pcm_avail_update = (
ma_proc)_snd_pcm_avail_update;
13686 pContext->alsa.snd_pcm_wait = (
ma_proc)_snd_pcm_wait;
13687 pContext->alsa.snd_pcm_info = (
ma_proc)_snd_pcm_info;
13688 pContext->alsa.snd_pcm_info_sizeof = (
ma_proc)_snd_pcm_info_sizeof;
13689 pContext->alsa.snd_pcm_info_get_name = (
ma_proc)_snd_pcm_info_get_name;
13690 pContext->alsa.snd_config_update_free_global = (
ma_proc)_snd_config_update_free_global;
13696 ma_context_post_error(pContext,
NULL,
MA_LOG_LEVEL_ERROR,
"[ALSA] WARNING: Failed to initialize mutex for internal device enumeration.",
MA_ERROR);
13699 pContext->
onUninit = ma_context_uninit__alsa;
13701 pContext->
onEnumDevices = ma_context_enumerate_devices__alsa;
13721 #ifdef MA_HAS_PULSEAUDIO
13729 #ifdef MA_NO_RUNTIME_LINKING
13730 #include <pulse/pulseaudio.h>
13732 #define MA_PA_OK PA_OK
13733 #define MA_PA_ERR_ACCESS PA_ERR_ACCESS
13734 #define MA_PA_ERR_INVALID PA_ERR_INVALID
13735 #define MA_PA_ERR_NOENTITY PA_ERR_NOENTITY
13737 #define MA_PA_CHANNELS_MAX PA_CHANNELS_MAX
13738 #define MA_PA_RATE_MAX PA_RATE_MAX
13740 typedef pa_context_flags_t ma_pa_context_flags_t;
13741 #define MA_PA_CONTEXT_NOFLAGS PA_CONTEXT_NOFLAGS
13742 #define MA_PA_CONTEXT_NOAUTOSPAWN PA_CONTEXT_NOAUTOSPAWN
13743 #define MA_PA_CONTEXT_NOFAIL PA_CONTEXT_NOFAIL
13745 typedef pa_stream_flags_t ma_pa_stream_flags_t;
13746 #define MA_PA_STREAM_NOFLAGS PA_STREAM_NOFLAGS
13747 #define MA_PA_STREAM_START_CORKED PA_STREAM_START_CORKED
13748 #define MA_PA_STREAM_INTERPOLATE_TIMING PA_STREAM_INTERPOLATE_TIMING
13749 #define MA_PA_STREAM_NOT_MONOTONIC PA_STREAM_NOT_MONOTONIC
13750 #define MA_PA_STREAM_AUTO_TIMING_UPDATE PA_STREAM_AUTO_TIMING_UPDATE
13751 #define MA_PA_STREAM_NO_REMAP_CHANNELS PA_STREAM_NO_REMAP_CHANNELS
13752 #define MA_PA_STREAM_NO_REMIX_CHANNELS PA_STREAM_NO_REMIX_CHANNELS
13753 #define MA_PA_STREAM_FIX_FORMAT PA_STREAM_FIX_FORMAT
13754 #define MA_PA_STREAM_FIX_RATE PA_STREAM_FIX_RATE
13755 #define MA_PA_STREAM_FIX_CHANNELS PA_STREAM_FIX_CHANNELS
13756 #define MA_PA_STREAM_DONT_MOVE PA_STREAM_DONT_MOVE
13757 #define MA_PA_STREAM_VARIABLE_RATE PA_STREAM_VARIABLE_RATE
13758 #define MA_PA_STREAM_PEAK_DETECT PA_STREAM_PEAK_DETECT
13759 #define MA_PA_STREAM_START_MUTED PA_STREAM_START_MUTED
13760 #define MA_PA_STREAM_ADJUST_LATENCY PA_STREAM_ADJUST_LATENCY
13761 #define MA_PA_STREAM_EARLY_REQUESTS PA_STREAM_EARLY_REQUESTS
13762 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
13763 #define MA_PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED
13764 #define MA_PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
13765 #define MA_PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
13766 #define MA_PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH
13768 typedef pa_sink_flags_t ma_pa_sink_flags_t;
13769 #define MA_PA_SINK_NOFLAGS PA_SINK_NOFLAGS
13770 #define MA_PA_SINK_HW_VOLUME_CTRL PA_SINK_HW_VOLUME_CTRL
13771 #define MA_PA_SINK_LATENCY PA_SINK_LATENCY
13772 #define MA_PA_SINK_HARDWARE PA_SINK_HARDWARE
13773 #define MA_PA_SINK_NETWORK PA_SINK_NETWORK
13774 #define MA_PA_SINK_HW_MUTE_CTRL PA_SINK_HW_MUTE_CTRL
13775 #define MA_PA_SINK_DECIBEL_VOLUME PA_SINK_DECIBEL_VOLUME
13776 #define MA_PA_SINK_FLAT_VOLUME PA_SINK_FLAT_VOLUME
13777 #define MA_PA_SINK_DYNAMIC_LATENCY PA_SINK_DYNAMIC_LATENCY
13778 #define MA_PA_SINK_SET_FORMATS PA_SINK_SET_FORMATS
13780 typedef pa_source_flags_t ma_pa_source_flags_t;
13781 #define MA_PA_SOURCE_NOFLAGS PA_SOURCE_NOFLAGS
13782 #define MA_PA_SOURCE_HW_VOLUME_CTRL PA_SOURCE_HW_VOLUME_CTRL
13783 #define MA_PA_SOURCE_LATENCY PA_SOURCE_LATENCY
13784 #define MA_PA_SOURCE_HARDWARE PA_SOURCE_HARDWARE
13785 #define MA_PA_SOURCE_NETWORK PA_SOURCE_NETWORK
13786 #define MA_PA_SOURCE_HW_MUTE_CTRL PA_SOURCE_HW_MUTE_CTRL
13787 #define MA_PA_SOURCE_DECIBEL_VOLUME PA_SOURCE_DECIBEL_VOLUME
13788 #define MA_PA_SOURCE_DYNAMIC_LATENCY PA_SOURCE_DYNAMIC_LATENCY
13789 #define MA_PA_SOURCE_FLAT_VOLUME PA_SOURCE_FLAT_VOLUME
13791 typedef pa_context_state_t ma_pa_context_state_t;
13792 #define MA_PA_CONTEXT_UNCONNECTED PA_CONTEXT_UNCONNECTED
13793 #define MA_PA_CONTEXT_CONNECTING PA_CONTEXT_CONNECTING
13794 #define MA_PA_CONTEXT_AUTHORIZING PA_CONTEXT_AUTHORIZING
13795 #define MA_PA_CONTEXT_SETTING_NAME PA_CONTEXT_SETTING_NAME
13796 #define MA_PA_CONTEXT_READY PA_CONTEXT_READY
13797 #define MA_PA_CONTEXT_FAILED PA_CONTEXT_FAILED
13798 #define MA_PA_CONTEXT_TERMINATED PA_CONTEXT_TERMINATED
13800 typedef pa_stream_state_t ma_pa_stream_state_t;
13801 #define MA_PA_STREAM_UNCONNECTED PA_STREAM_UNCONNECTED
13802 #define MA_PA_STREAM_CREATING PA_STREAM_CREATING
13803 #define MA_PA_STREAM_READY PA_STREAM_READY
13804 #define MA_PA_STREAM_FAILED PA_STREAM_FAILED
13805 #define MA_PA_STREAM_TERMINATED PA_STREAM_TERMINATED
13807 typedef pa_operation_state_t ma_pa_operation_state_t;
13808 #define MA_PA_OPERATION_RUNNING PA_OPERATION_RUNNING
13809 #define MA_PA_OPERATION_DONE PA_OPERATION_DONE
13810 #define MA_PA_OPERATION_CANCELLED PA_OPERATION_CANCELLED
13812 typedef pa_sink_state_t ma_pa_sink_state_t;
13813 #define MA_PA_SINK_INVALID_STATE PA_SINK_INVALID_STATE
13814 #define MA_PA_SINK_RUNNING PA_SINK_RUNNING
13815 #define MA_PA_SINK_IDLE PA_SINK_IDLE
13816 #define MA_PA_SINK_SUSPENDED PA_SINK_SUSPENDED
13818 typedef pa_source_state_t ma_pa_source_state_t;
13819 #define MA_PA_SOURCE_INVALID_STATE PA_SOURCE_INVALID_STATE
13820 #define MA_PA_SOURCE_RUNNING PA_SOURCE_RUNNING
13821 #define MA_PA_SOURCE_IDLE PA_SOURCE_IDLE
13822 #define MA_PA_SOURCE_SUSPENDED PA_SOURCE_SUSPENDED
13824 typedef pa_seek_mode_t ma_pa_seek_mode_t;
13825 #define MA_PA_SEEK_RELATIVE PA_SEEK_RELATIVE
13826 #define MA_PA_SEEK_ABSOLUTE PA_SEEK_ABSOLUTE
13827 #define MA_PA_SEEK_RELATIVE_ON_READ PA_SEEK_RELATIVE_ON_READ
13828 #define MA_PA_SEEK_RELATIVE_END PA_SEEK_RELATIVE_END
13830 typedef pa_channel_position_t ma_pa_channel_position_t;
13831 #define MA_PA_CHANNEL_POSITION_INVALID PA_CHANNEL_POSITION_INVALID
13832 #define MA_PA_CHANNEL_POSITION_MONO PA_CHANNEL_POSITION_MONO
13833 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT PA_CHANNEL_POSITION_FRONT_LEFT
13834 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT PA_CHANNEL_POSITION_FRONT_RIGHT
13835 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER PA_CHANNEL_POSITION_FRONT_CENTER
13836 #define MA_PA_CHANNEL_POSITION_REAR_CENTER PA_CHANNEL_POSITION_REAR_CENTER
13837 #define MA_PA_CHANNEL_POSITION_REAR_LEFT PA_CHANNEL_POSITION_REAR_LEFT
13838 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT PA_CHANNEL_POSITION_REAR_RIGHT
13839 #define MA_PA_CHANNEL_POSITION_LFE PA_CHANNEL_POSITION_LFE
13840 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
13841 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
13842 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT PA_CHANNEL_POSITION_SIDE_LEFT
13843 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT PA_CHANNEL_POSITION_SIDE_RIGHT
13844 #define MA_PA_CHANNEL_POSITION_AUX0 PA_CHANNEL_POSITION_AUX0
13845 #define MA_PA_CHANNEL_POSITION_AUX1 PA_CHANNEL_POSITION_AUX1
13846 #define MA_PA_CHANNEL_POSITION_AUX2 PA_CHANNEL_POSITION_AUX2
13847 #define MA_PA_CHANNEL_POSITION_AUX3 PA_CHANNEL_POSITION_AUX3
13848 #define MA_PA_CHANNEL_POSITION_AUX4 PA_CHANNEL_POSITION_AUX4
13849 #define MA_PA_CHANNEL_POSITION_AUX5 PA_CHANNEL_POSITION_AUX5
13850 #define MA_PA_CHANNEL_POSITION_AUX6 PA_CHANNEL_POSITION_AUX6
13851 #define MA_PA_CHANNEL_POSITION_AUX7 PA_CHANNEL_POSITION_AUX7
13852 #define MA_PA_CHANNEL_POSITION_AUX8 PA_CHANNEL_POSITION_AUX8
13853 #define MA_PA_CHANNEL_POSITION_AUX9 PA_CHANNEL_POSITION_AUX9
13854 #define MA_PA_CHANNEL_POSITION_AUX10 PA_CHANNEL_POSITION_AUX10
13855 #define MA_PA_CHANNEL_POSITION_AUX11 PA_CHANNEL_POSITION_AUX11
13856 #define MA_PA_CHANNEL_POSITION_AUX12 PA_CHANNEL_POSITION_AUX12
13857 #define MA_PA_CHANNEL_POSITION_AUX13 PA_CHANNEL_POSITION_AUX13
13858 #define MA_PA_CHANNEL_POSITION_AUX14 PA_CHANNEL_POSITION_AUX14
13859 #define MA_PA_CHANNEL_POSITION_AUX15 PA_CHANNEL_POSITION_AUX15
13860 #define MA_PA_CHANNEL_POSITION_AUX16 PA_CHANNEL_POSITION_AUX16
13861 #define MA_PA_CHANNEL_POSITION_AUX17 PA_CHANNEL_POSITION_AUX17
13862 #define MA_PA_CHANNEL_POSITION_AUX18 PA_CHANNEL_POSITION_AUX18
13863 #define MA_PA_CHANNEL_POSITION_AUX19 PA_CHANNEL_POSITION_AUX19
13864 #define MA_PA_CHANNEL_POSITION_AUX20 PA_CHANNEL_POSITION_AUX20
13865 #define MA_PA_CHANNEL_POSITION_AUX21 PA_CHANNEL_POSITION_AUX21
13866 #define MA_PA_CHANNEL_POSITION_AUX22 PA_CHANNEL_POSITION_AUX22
13867 #define MA_PA_CHANNEL_POSITION_AUX23 PA_CHANNEL_POSITION_AUX23
13868 #define MA_PA_CHANNEL_POSITION_AUX24 PA_CHANNEL_POSITION_AUX24
13869 #define MA_PA_CHANNEL_POSITION_AUX25 PA_CHANNEL_POSITION_AUX25
13870 #define MA_PA_CHANNEL_POSITION_AUX26 PA_CHANNEL_POSITION_AUX26
13871 #define MA_PA_CHANNEL_POSITION_AUX27 PA_CHANNEL_POSITION_AUX27
13872 #define MA_PA_CHANNEL_POSITION_AUX28 PA_CHANNEL_POSITION_AUX28
13873 #define MA_PA_CHANNEL_POSITION_AUX29 PA_CHANNEL_POSITION_AUX29
13874 #define MA_PA_CHANNEL_POSITION_AUX30 PA_CHANNEL_POSITION_AUX30
13875 #define MA_PA_CHANNEL_POSITION_AUX31 PA_CHANNEL_POSITION_AUX31
13876 #define MA_PA_CHANNEL_POSITION_TOP_CENTER PA_CHANNEL_POSITION_TOP_CENTER
13877 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT PA_CHANNEL_POSITION_TOP_FRONT_LEFT
13878 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
13879 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER PA_CHANNEL_POSITION_TOP_FRONT_CENTER
13880 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT PA_CHANNEL_POSITION_TOP_REAR_LEFT
13881 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT PA_CHANNEL_POSITION_TOP_REAR_RIGHT
13882 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER PA_CHANNEL_POSITION_TOP_REAR_CENTER
13883 #define MA_PA_CHANNEL_POSITION_LEFT PA_CHANNEL_POSITION_LEFT
13884 #define MA_PA_CHANNEL_POSITION_RIGHT PA_CHANNEL_POSITION_RIGHT
13885 #define MA_PA_CHANNEL_POSITION_CENTER PA_CHANNEL_POSITION_CENTER
13886 #define MA_PA_CHANNEL_POSITION_SUBWOOFER PA_CHANNEL_POSITION_SUBWOOFER
13888 typedef pa_channel_map_def_t ma_pa_channel_map_def_t;
13889 #define MA_PA_CHANNEL_MAP_AIFF PA_CHANNEL_MAP_AIFF
13890 #define MA_PA_CHANNEL_MAP_ALSA PA_CHANNEL_MAP_ALSA
13891 #define MA_PA_CHANNEL_MAP_AUX PA_CHANNEL_MAP_AUX
13892 #define MA_PA_CHANNEL_MAP_WAVEEX PA_CHANNEL_MAP_WAVEEX
13893 #define MA_PA_CHANNEL_MAP_OSS PA_CHANNEL_MAP_OSS
13894 #define MA_PA_CHANNEL_MAP_DEFAULT PA_CHANNEL_MAP_DEFAULT
13896 typedef pa_sample_format_t ma_pa_sample_format_t;
13897 #define MA_PA_SAMPLE_INVALID PA_SAMPLE_INVALID
13898 #define MA_PA_SAMPLE_U8 PA_SAMPLE_U8
13899 #define MA_PA_SAMPLE_ALAW PA_SAMPLE_ALAW
13900 #define MA_PA_SAMPLE_ULAW PA_SAMPLE_ULAW
13901 #define MA_PA_SAMPLE_S16LE PA_SAMPLE_S16LE
13902 #define MA_PA_SAMPLE_S16BE PA_SAMPLE_S16BE
13903 #define MA_PA_SAMPLE_FLOAT32LE PA_SAMPLE_FLOAT32LE
13904 #define MA_PA_SAMPLE_FLOAT32BE PA_SAMPLE_FLOAT32BE
13905 #define MA_PA_SAMPLE_S32LE PA_SAMPLE_S32LE
13906 #define MA_PA_SAMPLE_S32BE PA_SAMPLE_S32BE
13907 #define MA_PA_SAMPLE_S24LE PA_SAMPLE_S24LE
13908 #define MA_PA_SAMPLE_S24BE PA_SAMPLE_S24BE
13909 #define MA_PA_SAMPLE_S24_32LE PA_SAMPLE_S24_32LE
13910 #define MA_PA_SAMPLE_S24_32BE PA_SAMPLE_S24_32BE
13912 typedef pa_mainloop ma_pa_mainloop;
13913 typedef pa_mainloop_api ma_pa_mainloop_api;
13914 typedef pa_context ma_pa_context;
13915 typedef pa_operation ma_pa_operation;
13916 typedef pa_stream ma_pa_stream;
13917 typedef pa_spawn_api ma_pa_spawn_api;
13918 typedef pa_buffer_attr ma_pa_buffer_attr;
13919 typedef pa_channel_map ma_pa_channel_map;
13920 typedef pa_cvolume ma_pa_cvolume;
13921 typedef pa_sample_spec ma_pa_sample_spec;
13922 typedef pa_sink_info ma_pa_sink_info;
13923 typedef pa_source_info ma_pa_source_info;
13925 typedef pa_context_notify_cb_t ma_pa_context_notify_cb_t;
13926 typedef pa_sink_info_cb_t ma_pa_sink_info_cb_t;
13927 typedef pa_source_info_cb_t ma_pa_source_info_cb_t;
13928 typedef pa_stream_success_cb_t ma_pa_stream_success_cb_t;
13929 typedef pa_stream_request_cb_t ma_pa_stream_request_cb_t;
13930 typedef pa_free_cb_t ma_pa_free_cb_t;
13933 #define MA_PA_ERR_ACCESS 1
13934 #define MA_PA_ERR_INVALID 2
13935 #define MA_PA_ERR_NOENTITY 5
13937 #define MA_PA_CHANNELS_MAX 32
13938 #define MA_PA_RATE_MAX 384000
13940 typedef int ma_pa_context_flags_t;
13941 #define MA_PA_CONTEXT_NOFLAGS 0x00000000
13942 #define MA_PA_CONTEXT_NOAUTOSPAWN 0x00000001
13943 #define MA_PA_CONTEXT_NOFAIL 0x00000002
13945 typedef int ma_pa_stream_flags_t;
13946 #define MA_PA_STREAM_NOFLAGS 0x00000000
13947 #define MA_PA_STREAM_START_CORKED 0x00000001
13948 #define MA_PA_STREAM_INTERPOLATE_TIMING 0x00000002
13949 #define MA_PA_STREAM_NOT_MONOTONIC 0x00000004
13950 #define MA_PA_STREAM_AUTO_TIMING_UPDATE 0x00000008
13951 #define MA_PA_STREAM_NO_REMAP_CHANNELS 0x00000010
13952 #define MA_PA_STREAM_NO_REMIX_CHANNELS 0x00000020
13953 #define MA_PA_STREAM_FIX_FORMAT 0x00000040
13954 #define MA_PA_STREAM_FIX_RATE 0x00000080
13955 #define MA_PA_STREAM_FIX_CHANNELS 0x00000100
13956 #define MA_PA_STREAM_DONT_MOVE 0x00000200
13957 #define MA_PA_STREAM_VARIABLE_RATE 0x00000400
13958 #define MA_PA_STREAM_PEAK_DETECT 0x00000800
13959 #define MA_PA_STREAM_START_MUTED 0x00001000
13960 #define MA_PA_STREAM_ADJUST_LATENCY 0x00002000
13961 #define MA_PA_STREAM_EARLY_REQUESTS 0x00004000
13962 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND 0x00008000
13963 #define MA_PA_STREAM_START_UNMUTED 0x00010000
13964 #define MA_PA_STREAM_FAIL_ON_SUSPEND 0x00020000
13965 #define MA_PA_STREAM_RELATIVE_VOLUME 0x00040000
13966 #define MA_PA_STREAM_PASSTHROUGH 0x00080000
13968 typedef int ma_pa_sink_flags_t;
13969 #define MA_PA_SINK_NOFLAGS 0x00000000
13970 #define MA_PA_SINK_HW_VOLUME_CTRL 0x00000001
13971 #define MA_PA_SINK_LATENCY 0x00000002
13972 #define MA_PA_SINK_HARDWARE 0x00000004
13973 #define MA_PA_SINK_NETWORK 0x00000008
13974 #define MA_PA_SINK_HW_MUTE_CTRL 0x00000010
13975 #define MA_PA_SINK_DECIBEL_VOLUME 0x00000020
13976 #define MA_PA_SINK_FLAT_VOLUME 0x00000040
13977 #define MA_PA_SINK_DYNAMIC_LATENCY 0x00000080
13978 #define MA_PA_SINK_SET_FORMATS 0x00000100
13980 typedef int ma_pa_source_flags_t;
13981 #define MA_PA_SOURCE_NOFLAGS 0x00000000
13982 #define MA_PA_SOURCE_HW_VOLUME_CTRL 0x00000001
13983 #define MA_PA_SOURCE_LATENCY 0x00000002
13984 #define MA_PA_SOURCE_HARDWARE 0x00000004
13985 #define MA_PA_SOURCE_NETWORK 0x00000008
13986 #define MA_PA_SOURCE_HW_MUTE_CTRL 0x00000010
13987 #define MA_PA_SOURCE_DECIBEL_VOLUME 0x00000020
13988 #define MA_PA_SOURCE_DYNAMIC_LATENCY 0x00000040
13989 #define MA_PA_SOURCE_FLAT_VOLUME 0x00000080
13991 typedef int ma_pa_context_state_t;
13992 #define MA_PA_CONTEXT_UNCONNECTED 0
13993 #define MA_PA_CONTEXT_CONNECTING 1
13994 #define MA_PA_CONTEXT_AUTHORIZING 2
13995 #define MA_PA_CONTEXT_SETTING_NAME 3
13996 #define MA_PA_CONTEXT_READY 4
13997 #define MA_PA_CONTEXT_FAILED 5
13998 #define MA_PA_CONTEXT_TERMINATED 6
14000 typedef int ma_pa_stream_state_t;
14001 #define MA_PA_STREAM_UNCONNECTED 0
14002 #define MA_PA_STREAM_CREATING 1
14003 #define MA_PA_STREAM_READY 2
14004 #define MA_PA_STREAM_FAILED 3
14005 #define MA_PA_STREAM_TERMINATED 4
14007 typedef int ma_pa_operation_state_t;
14008 #define MA_PA_OPERATION_RUNNING 0
14009 #define MA_PA_OPERATION_DONE 1
14010 #define MA_PA_OPERATION_CANCELLED 2
14012 typedef int ma_pa_sink_state_t;
14013 #define MA_PA_SINK_INVALID_STATE -1
14014 #define MA_PA_SINK_RUNNING 0
14015 #define MA_PA_SINK_IDLE 1
14016 #define MA_PA_SINK_SUSPENDED 2
14018 typedef int ma_pa_source_state_t;
14019 #define MA_PA_SOURCE_INVALID_STATE -1
14020 #define MA_PA_SOURCE_RUNNING 0
14021 #define MA_PA_SOURCE_IDLE 1
14022 #define MA_PA_SOURCE_SUSPENDED 2
14024 typedef int ma_pa_seek_mode_t;
14025 #define MA_PA_SEEK_RELATIVE 0
14026 #define MA_PA_SEEK_ABSOLUTE 1
14027 #define MA_PA_SEEK_RELATIVE_ON_READ 2
14028 #define MA_PA_SEEK_RELATIVE_END 3
14030 typedef int ma_pa_channel_position_t;
14031 #define MA_PA_CHANNEL_POSITION_INVALID -1
14032 #define MA_PA_CHANNEL_POSITION_MONO 0
14033 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT 1
14034 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT 2
14035 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER 3
14036 #define MA_PA_CHANNEL_POSITION_REAR_CENTER 4
14037 #define MA_PA_CHANNEL_POSITION_REAR_LEFT 5
14038 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT 6
14039 #define MA_PA_CHANNEL_POSITION_LFE 7
14040 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER 8
14041 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER 9
14042 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT 10
14043 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT 11
14044 #define MA_PA_CHANNEL_POSITION_AUX0 12
14045 #define MA_PA_CHANNEL_POSITION_AUX1 13
14046 #define MA_PA_CHANNEL_POSITION_AUX2 14
14047 #define MA_PA_CHANNEL_POSITION_AUX3 15
14048 #define MA_PA_CHANNEL_POSITION_AUX4 16
14049 #define MA_PA_CHANNEL_POSITION_AUX5 17
14050 #define MA_PA_CHANNEL_POSITION_AUX6 18
14051 #define MA_PA_CHANNEL_POSITION_AUX7 19
14052 #define MA_PA_CHANNEL_POSITION_AUX8 20
14053 #define MA_PA_CHANNEL_POSITION_AUX9 21
14054 #define MA_PA_CHANNEL_POSITION_AUX10 22
14055 #define MA_PA_CHANNEL_POSITION_AUX11 23
14056 #define MA_PA_CHANNEL_POSITION_AUX12 24
14057 #define MA_PA_CHANNEL_POSITION_AUX13 25
14058 #define MA_PA_CHANNEL_POSITION_AUX14 26
14059 #define MA_PA_CHANNEL_POSITION_AUX15 27
14060 #define MA_PA_CHANNEL_POSITION_AUX16 28
14061 #define MA_PA_CHANNEL_POSITION_AUX17 29
14062 #define MA_PA_CHANNEL_POSITION_AUX18 30
14063 #define MA_PA_CHANNEL_POSITION_AUX19 31
14064 #define MA_PA_CHANNEL_POSITION_AUX20 32
14065 #define MA_PA_CHANNEL_POSITION_AUX21 33
14066 #define MA_PA_CHANNEL_POSITION_AUX22 34
14067 #define MA_PA_CHANNEL_POSITION_AUX23 35
14068 #define MA_PA_CHANNEL_POSITION_AUX24 36
14069 #define MA_PA_CHANNEL_POSITION_AUX25 37
14070 #define MA_PA_CHANNEL_POSITION_AUX26 38
14071 #define MA_PA_CHANNEL_POSITION_AUX27 39
14072 #define MA_PA_CHANNEL_POSITION_AUX28 40
14073 #define MA_PA_CHANNEL_POSITION_AUX29 41
14074 #define MA_PA_CHANNEL_POSITION_AUX30 42
14075 #define MA_PA_CHANNEL_POSITION_AUX31 43
14076 #define MA_PA_CHANNEL_POSITION_TOP_CENTER 44
14077 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT 45
14078 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT 46
14079 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER 47
14080 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT 48
14081 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT 49
14082 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER 50
14083 #define MA_PA_CHANNEL_POSITION_LEFT MA_PA_CHANNEL_POSITION_FRONT_LEFT
14084 #define MA_PA_CHANNEL_POSITION_RIGHT MA_PA_CHANNEL_POSITION_FRONT_RIGHT
14085 #define MA_PA_CHANNEL_POSITION_CENTER MA_PA_CHANNEL_POSITION_FRONT_CENTER
14086 #define MA_PA_CHANNEL_POSITION_SUBWOOFER MA_PA_CHANNEL_POSITION_LFE
14088 typedef int ma_pa_channel_map_def_t;
14089 #define MA_PA_CHANNEL_MAP_AIFF 0
14090 #define MA_PA_CHANNEL_MAP_ALSA 1
14091 #define MA_PA_CHANNEL_MAP_AUX 2
14092 #define MA_PA_CHANNEL_MAP_WAVEEX 3
14093 #define MA_PA_CHANNEL_MAP_OSS 4
14094 #define MA_PA_CHANNEL_MAP_DEFAULT MA_PA_CHANNEL_MAP_AIFF
14096 typedef int ma_pa_sample_format_t;
14097 #define MA_PA_SAMPLE_INVALID -1
14098 #define MA_PA_SAMPLE_U8 0
14099 #define MA_PA_SAMPLE_ALAW 1
14100 #define MA_PA_SAMPLE_ULAW 2
14101 #define MA_PA_SAMPLE_S16LE 3
14102 #define MA_PA_SAMPLE_S16BE 4
14103 #define MA_PA_SAMPLE_FLOAT32LE 5
14104 #define MA_PA_SAMPLE_FLOAT32BE 6
14105 #define MA_PA_SAMPLE_S32LE 7
14106 #define MA_PA_SAMPLE_S32BE 8
14107 #define MA_PA_SAMPLE_S24LE 9
14108 #define MA_PA_SAMPLE_S24BE 10
14109 #define MA_PA_SAMPLE_S24_32LE 11
14110 #define MA_PA_SAMPLE_S24_32BE 12
14112 typedef struct ma_pa_mainloop ma_pa_mainloop;
14113 typedef struct ma_pa_mainloop_api ma_pa_mainloop_api;
14114 typedef struct ma_pa_context ma_pa_context;
14115 typedef struct ma_pa_operation ma_pa_operation;
14116 typedef struct ma_pa_stream ma_pa_stream;
14117 typedef struct ma_pa_spawn_api ma_pa_spawn_api;
14126 } ma_pa_buffer_attr;
14131 ma_pa_channel_position_t map[MA_PA_CHANNELS_MAX];
14132 } ma_pa_channel_map;
14142 ma_pa_sample_format_t
format;
14145 } ma_pa_sample_spec;
14151 const char* description;
14152 ma_pa_sample_spec sample_spec;
14153 ma_pa_channel_map channel_map;
14155 ma_pa_cvolume volume;
14158 const char* monitor_source_name;
14160 const char* driver;
14161 ma_pa_sink_flags_t flags;
14165 ma_pa_sink_state_t state;
14179 const char *description;
14180 ma_pa_sample_spec sample_spec;
14181 ma_pa_channel_map channel_map;
14183 ma_pa_cvolume volume;
14186 const char *monitor_of_sink_name;
14188 const char *driver;
14189 ma_pa_source_flags_t flags;
14193 ma_pa_source_state_t state;
14201 } ma_pa_source_info;
14203 typedef void (* ma_pa_context_notify_cb_t)(ma_pa_context* c,
void* userdata);
14204 typedef void (* ma_pa_sink_info_cb_t) (ma_pa_context* c,
const ma_pa_sink_info*
i,
int eol,
void* userdata);
14205 typedef void (* ma_pa_source_info_cb_t) (ma_pa_context* c,
const ma_pa_source_info*
i,
int eol,
void* userdata);
14206 typedef void (* ma_pa_stream_success_cb_t)(ma_pa_stream*
s,
int success,
void* userdata);
14207 typedef void (* ma_pa_stream_request_cb_t)(ma_pa_stream*
s,
size_t nbytes,
void* userdata);
14208 typedef void (* ma_pa_free_cb_t) (
void* p);
14212 typedef ma_pa_mainloop* (* ma_pa_mainloop_new_proc) ();
14213 typedef void (* ma_pa_mainloop_free_proc) (ma_pa_mainloop* m);
14214 typedef ma_pa_mainloop_api* (* ma_pa_mainloop_get_api_proc) (ma_pa_mainloop* m);
14215 typedef int (* ma_pa_mainloop_iterate_proc) (ma_pa_mainloop* m,
int block,
int* retval);
14216 typedef void (* ma_pa_mainloop_wakeup_proc) (ma_pa_mainloop* m);
14217 typedef ma_pa_context* (* ma_pa_context_new_proc) (ma_pa_mainloop_api* mainloop,
const char*
name);
14218 typedef void (* ma_pa_context_unref_proc) (ma_pa_context* c);
14219 typedef int (* ma_pa_context_connect_proc) (ma_pa_context* c,
const char* server, ma_pa_context_flags_t flags,
const ma_pa_spawn_api* api);
14220 typedef void (* ma_pa_context_disconnect_proc) (ma_pa_context* c);
14221 typedef void (* ma_pa_context_set_state_callback_proc) (ma_pa_context* c, ma_pa_context_notify_cb_t cb,
void* userdata);
14222 typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (ma_pa_context* c);
14223 typedef ma_pa_operation* (* ma_pa_context_get_sink_info_list_proc) (ma_pa_context* c, ma_pa_sink_info_cb_t cb,
void* userdata);
14224 typedef ma_pa_operation* (* ma_pa_context_get_source_info_list_proc) (ma_pa_context* c, ma_pa_source_info_cb_t cb,
void* userdata);
14225 typedef ma_pa_operation* (* ma_pa_context_get_sink_info_by_name_proc) (ma_pa_context* c,
const char*
name, ma_pa_sink_info_cb_t cb,
void* userdata);
14226 typedef ma_pa_operation* (* ma_pa_context_get_source_info_by_name_proc)(ma_pa_context* c,
const char*
name, ma_pa_source_info_cb_t cb,
void* userdata);
14227 typedef void (* ma_pa_operation_unref_proc) (ma_pa_operation* o);
14228 typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (ma_pa_operation* o);
14229 typedef ma_pa_channel_map* (* ma_pa_channel_map_init_extend_proc) (ma_pa_channel_map* m,
unsigned channels, ma_pa_channel_map_def_t def);
14230 typedef int (* ma_pa_channel_map_valid_proc) (
const ma_pa_channel_map* m);
14231 typedef int (* ma_pa_channel_map_compatible_proc) (
const ma_pa_channel_map* m,
const ma_pa_sample_spec* ss);
14232 typedef ma_pa_stream* (* ma_pa_stream_new_proc) (ma_pa_context* c,
const char*
name,
const ma_pa_sample_spec* ss,
const ma_pa_channel_map* map);
14233 typedef void (* ma_pa_stream_unref_proc) (ma_pa_stream*
s);
14234 typedef int (* ma_pa_stream_connect_playback_proc) (ma_pa_stream*
s,
const char* dev,
const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags,
const ma_pa_cvolume* volume, ma_pa_stream* sync_stream);
14235 typedef int (* ma_pa_stream_connect_record_proc) (ma_pa_stream*
s,
const char* dev,
const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags);
14236 typedef int (* ma_pa_stream_disconnect_proc) (ma_pa_stream*
s);
14237 typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (ma_pa_stream*
s);
14238 typedef const ma_pa_sample_spec* (* ma_pa_stream_get_sample_spec_proc) (ma_pa_stream*
s);
14239 typedef const ma_pa_channel_map* (* ma_pa_stream_get_channel_map_proc) (ma_pa_stream*
s);
14240 typedef const ma_pa_buffer_attr* (* ma_pa_stream_get_buffer_attr_proc) (ma_pa_stream*
s);
14241 typedef ma_pa_operation* (* ma_pa_stream_set_buffer_attr_proc) (ma_pa_stream*
s,
const ma_pa_buffer_attr* attr, ma_pa_stream_success_cb_t cb,
void* userdata);
14242 typedef const char* (* ma_pa_stream_get_device_name_proc) (ma_pa_stream*
s);
14243 typedef void (* ma_pa_stream_set_write_callback_proc) (ma_pa_stream*
s, ma_pa_stream_request_cb_t cb,
void* userdata);
14244 typedef void (* ma_pa_stream_set_read_callback_proc) (ma_pa_stream*
s, ma_pa_stream_request_cb_t cb,
void* userdata);
14245 typedef ma_pa_operation* (* ma_pa_stream_flush_proc) (ma_pa_stream*
s, ma_pa_stream_success_cb_t cb,
void* userdata);
14246 typedef ma_pa_operation* (* ma_pa_stream_drain_proc) (ma_pa_stream*
s, ma_pa_stream_success_cb_t cb,
void* userdata);
14247 typedef int (* ma_pa_stream_is_corked_proc) (ma_pa_stream*
s);
14248 typedef ma_pa_operation* (* ma_pa_stream_cork_proc) (ma_pa_stream*
s,
int b, ma_pa_stream_success_cb_t cb,
void* userdata);
14249 typedef ma_pa_operation* (* ma_pa_stream_trigger_proc) (ma_pa_stream*
s, ma_pa_stream_success_cb_t cb,
void* userdata);
14250 typedef int (* ma_pa_stream_begin_write_proc) (ma_pa_stream*
s,
void** data,
size_t* nbytes);
14251 typedef int (* ma_pa_stream_write_proc) (ma_pa_stream*
s,
const void* data,
size_t nbytes, ma_pa_free_cb_t free_cb, int64_t offset, ma_pa_seek_mode_t seek);
14252 typedef int (* ma_pa_stream_peek_proc) (ma_pa_stream*
s,
const void** data,
size_t* nbytes);
14253 typedef int (* ma_pa_stream_drop_proc) (ma_pa_stream*
s);
14254 typedef size_t (* ma_pa_stream_writable_size_proc) (ma_pa_stream*
s);
14255 typedef size_t (* ma_pa_stream_readable_size_proc) (ma_pa_stream*
s);
14262 } ma_pulse_device_enum_data;
14264 ma_result ma_result_from_pulse(
int result)
14278 if (ma_is_little_endian()) {
14299 default:
return MA_PA_SAMPLE_INVALID;
14306 if (ma_is_little_endian()) {
14331 ma_channel ma_channel_position_from_pulse(ma_pa_channel_position_t position)
14392 ma_pa_channel_position_t ma_channel_position_to_pulse(
ma_channel position)
14415 case MA_CHANNEL_19:
return MA_PA_CHANNEL_POSITION_AUX18;
14416 case MA_CHANNEL_20:
return MA_PA_CHANNEL_POSITION_AUX19;
14417 case MA_CHANNEL_21:
return MA_PA_CHANNEL_POSITION_AUX20;
14418 case MA_CHANNEL_22:
return MA_PA_CHANNEL_POSITION_AUX21;
14419 case MA_CHANNEL_23:
return MA_PA_CHANNEL_POSITION_AUX22;
14420 case MA_CHANNEL_24:
return MA_PA_CHANNEL_POSITION_AUX23;
14421 case MA_CHANNEL_25:
return MA_PA_CHANNEL_POSITION_AUX24;
14422 case MA_CHANNEL_26:
return MA_PA_CHANNEL_POSITION_AUX25;
14423 case MA_CHANNEL_27:
return MA_PA_CHANNEL_POSITION_AUX26;
14424 case MA_CHANNEL_28:
return MA_PA_CHANNEL_POSITION_AUX27;
14425 case MA_CHANNEL_29:
return MA_PA_CHANNEL_POSITION_AUX28;
14426 case MA_CHANNEL_30:
return MA_PA_CHANNEL_POSITION_AUX29;
14427 case MA_CHANNEL_31:
return MA_PA_CHANNEL_POSITION_AUX30;
14428 case MA_CHANNEL_32:
return MA_PA_CHANNEL_POSITION_AUX31;
14429 default:
return (ma_pa_channel_position_t)position;
14434 ma_result ma_wait_for_operation__pulse(
ma_context* pContext, ma_pa_mainloop* pMainLoop, ma_pa_operation* pOP)
14436 ma_assert(pContext !=
NULL);
14437 ma_assert(pMainLoop !=
NULL);
14438 ma_assert(pOP !=
NULL);
14440 while (((ma_pa_operation_get_state_proc)pContext->pulse.pa_operation_get_state)(pOP) == MA_PA_OPERATION_RUNNING) {
14441 int error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)(pMainLoop, 1,
NULL);
14443 return ma_result_from_pulse(
error);
14450 ma_result ma_device__wait_for_operation__pulse(
ma_device* pDevice, ma_pa_operation* pOP)
14452 ma_assert(pDevice !=
NULL);
14453 ma_assert(pOP !=
NULL);
14455 return ma_wait_for_operation__pulse(pDevice->pContext, (ma_pa_mainloop*)pDevice->pulse.pMainLoop, pOP);
14461 ma_assert(pContext !=
NULL);
14462 ma_assert(pID0 !=
NULL);
14463 ma_assert(pID1 !=
NULL);
14466 return ma_strcmp(pID0->pulse, pID1->pulse) == 0;
14476 } ma_context_enumerate_devices_callback_data__pulse;
14478 void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pSinkInfo,
int endOfList,
void* pUserData)
14480 ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
14483 ma_assert(pData !=
NULL);
14485 if (endOfList || pData->isTerminated) {
14489 ma_zero_object(&deviceInfo);
14492 if (pSinkInfo->name !=
NULL) {
14493 ma_strncpy_s(deviceInfo.
id.pulse,
sizeof(deviceInfo.
id.pulse), pSinkInfo->name, (
size_t)-1);
14497 if (pSinkInfo->description !=
NULL) {
14498 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), pSinkInfo->description, (
size_t)-1);
14501 pData->isTerminated = !pData->callback(pData->pContext,
ma_device_type_playback, &deviceInfo, pData->pUserData);
14503 (
void)pPulseContext;
14506 void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_source_info* pSinkInfo,
int endOfList,
void* pUserData)
14508 ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
14511 ma_assert(pData !=
NULL);
14513 if (endOfList || pData->isTerminated) {
14517 ma_zero_object(&deviceInfo);
14520 if (pSinkInfo->name !=
NULL) {
14521 ma_strncpy_s(deviceInfo.
id.pulse,
sizeof(deviceInfo.
id.pulse), pSinkInfo->name, (
size_t)-1);
14525 if (pSinkInfo->description !=
NULL) {
14526 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), pSinkInfo->description, (
size_t)-1);
14529 pData->isTerminated = !pData->callback(pData->pContext,
ma_device_type_capture, &deviceInfo, pData->pUserData);
14531 (
void)pPulseContext;
14537 ma_context_enumerate_devices_callback_data__pulse callbackData;
14538 ma_pa_operation* pOP =
NULL;
14539 ma_pa_mainloop* pMainLoop;
14540 ma_pa_mainloop_api* pAPI;
14541 ma_pa_context* pPulseContext;
14544 ma_assert(pContext !=
NULL);
14545 ma_assert(callback !=
NULL);
14547 callbackData.pContext = pContext;
14548 callbackData.callback = callback;
14550 callbackData.isTerminated =
MA_FALSE;
14552 pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
14553 if (pMainLoop ==
NULL) {
14557 pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
14558 if (pAPI ==
NULL) {
14559 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14563 pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->pulse.pApplicationName);
14564 if (pPulseContext ==
NULL) {
14565 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14569 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->pulse.pServerName, (pContext->pulse.tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN,
NULL);
14570 if (
error != MA_PA_OK) {
14571 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
14572 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14573 return ma_result_from_pulse(
error);
14577 ma_pa_context_state_t state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)(pPulseContext);
14578 if (state == MA_PA_CONTEXT_READY) {
14581 if (state == MA_PA_CONTEXT_CONNECTING || state == MA_PA_CONTEXT_AUTHORIZING || state == MA_PA_CONTEXT_SETTING_NAME) {
14582 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)(pMainLoop, 1,
NULL);
14584 result = ma_result_from_pulse(
error);
14588 #ifdef MA_DEBUG_OUTPUT
14589 printf(
"[PulseAudio] pa_context_get_state() returned %d. Waiting.\n", state);
14593 if (state == MA_PA_CONTEXT_UNCONNECTED || state == MA_PA_CONTEXT_FAILED || state == MA_PA_CONTEXT_TERMINATED) {
14594 #ifdef MA_DEBUG_OUTPUT
14595 printf(
"[PulseAudio] pa_context_get_state() returned %d. Failed.\n", state);
14603 if (!callbackData.isTerminated) {
14604 pOP = ((ma_pa_context_get_sink_info_list_proc)pContext->pulse.pa_context_get_sink_info_list)(pPulseContext, ma_context_enumerate_devices_sink_callback__pulse, &callbackData);
14610 result = ma_wait_for_operation__pulse(pContext, pMainLoop, pOP);
14611 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
14619 if (!callbackData.isTerminated) {
14620 pOP = ((ma_pa_context_get_source_info_list_proc)pContext->pulse.pa_context_get_source_info_list)(pPulseContext, ma_context_enumerate_devices_source_callback__pulse, &callbackData);
14626 result = ma_wait_for_operation__pulse(pContext, pMainLoop, pOP);
14627 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
14634 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
14635 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
14636 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14645 } ma_context_get_device_info_callback_data__pulse;
14647 void ma_context_get_device_info_sink_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pInfo,
int endOfList,
void* pUserData)
14649 ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
14651 if (endOfList > 0) {
14655 ma_assert(pData !=
NULL);
14656 pData->foundDevice =
MA_TRUE;
14658 if (pInfo->name !=
NULL) {
14659 ma_strncpy_s(pData->pDeviceInfo->id.pulse,
sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (
size_t)-1);
14662 if (pInfo->description !=
NULL) {
14663 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pInfo->description, (
size_t)-1);
14666 pData->pDeviceInfo->minChannels = pInfo->sample_spec.channels;
14667 pData->pDeviceInfo->maxChannels = pInfo->sample_spec.channels;
14668 pData->pDeviceInfo->minSampleRate = pInfo->sample_spec.rate;
14669 pData->pDeviceInfo->maxSampleRate = pInfo->sample_spec.rate;
14670 pData->pDeviceInfo->formatCount = 1;
14671 pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format);
14673 (
void)pPulseContext;
14676 void ma_context_get_device_info_source_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_source_info* pInfo,
int endOfList,
void* pUserData)
14678 ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
14680 if (endOfList > 0) {
14684 ma_assert(pData !=
NULL);
14685 pData->foundDevice =
MA_TRUE;
14687 if (pInfo->name !=
NULL) {
14688 ma_strncpy_s(pData->pDeviceInfo->id.pulse,
sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (
size_t)-1);
14691 if (pInfo->description !=
NULL) {
14692 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pInfo->description, (
size_t)-1);
14695 pData->pDeviceInfo->minChannels = pInfo->sample_spec.channels;
14696 pData->pDeviceInfo->maxChannels = pInfo->sample_spec.channels;
14697 pData->pDeviceInfo->minSampleRate = pInfo->sample_spec.rate;
14698 pData->pDeviceInfo->maxSampleRate = pInfo->sample_spec.rate;
14699 pData->pDeviceInfo->formatCount = 1;
14700 pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format);
14702 (
void)pPulseContext;
14708 ma_context_get_device_info_callback_data__pulse callbackData;
14709 ma_pa_operation* pOP =
NULL;
14710 ma_pa_mainloop* pMainLoop;
14711 ma_pa_mainloop_api* pAPI;
14712 ma_pa_context* pPulseContext;
14715 ma_assert(pContext !=
NULL);
14722 callbackData.pDeviceInfo = pDeviceInfo;
14723 callbackData.foundDevice =
MA_FALSE;
14725 pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
14726 if (pMainLoop ==
NULL) {
14730 pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
14731 if (pAPI ==
NULL) {
14732 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14736 pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->pulse.pApplicationName);
14737 if (pPulseContext ==
NULL) {
14738 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14742 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->pulse.pServerName, 0,
NULL);
14743 if (
error != MA_PA_OK) {
14744 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
14745 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14746 return ma_result_from_pulse(
error);
14750 ma_pa_context_state_t state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)(pPulseContext);
14751 if (state == MA_PA_CONTEXT_READY) {
14754 if (state == MA_PA_CONTEXT_CONNECTING || state == MA_PA_CONTEXT_AUTHORIZING || state == MA_PA_CONTEXT_SETTING_NAME) {
14755 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)(pMainLoop, 1,
NULL);
14757 result = ma_result_from_pulse(
error);
14761 #ifdef MA_DEBUG_OUTPUT
14762 printf(
"[PulseAudio] pa_context_get_state() returned %d. Waiting.\n", state);
14766 if (state == MA_PA_CONTEXT_UNCONNECTED || state == MA_PA_CONTEXT_FAILED || state == MA_PA_CONTEXT_TERMINATED) {
14767 #ifdef MA_DEBUG_OUTPUT
14768 printf(
"[PulseAudio] pa_context_get_state() returned %d. Failed.\n", state);
14775 pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)(pPulseContext, pDeviceID->pulse, ma_context_get_device_info_sink_callback__pulse, &callbackData);
14777 pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)(pPulseContext, pDeviceID->pulse, ma_context_get_device_info_source_callback__pulse, &callbackData);
14781 ma_wait_for_operation__pulse(pContext, pMainLoop, pOP);
14782 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
14788 if (!callbackData.foundDevice) {
14795 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
14796 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
14797 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
14802 void ma_pulse_device_state_callback(ma_pa_context* pPulseContext,
void* pUserData)
14808 ma_assert(pDevice !=
NULL);
14810 pContext = pDevice->pContext;
14811 ma_assert(pContext !=
NULL);
14813 pDevice->pulse.pulseContextState = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)(pPulseContext);
14816 void ma_device_sink_info_callback(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pInfo,
int endOfList,
void* pUserData)
14818 ma_pa_sink_info* pInfoOut;
14820 if (endOfList > 0) {
14824 pInfoOut = (ma_pa_sink_info*)pUserData;
14825 ma_assert(pInfoOut !=
NULL);
14827 *pInfoOut = *pInfo;
14829 (
void)pPulseContext;
14832 void ma_device_source_info_callback(ma_pa_context* pPulseContext,
const ma_pa_source_info* pInfo,
int endOfList,
void* pUserData)
14834 ma_pa_source_info* pInfoOut;
14836 if (endOfList > 0) {
14840 pInfoOut = (ma_pa_source_info*)pUserData;
14841 ma_assert(pInfoOut !=
NULL);
14843 *pInfoOut = *pInfo;
14845 (
void)pPulseContext;
14848 void ma_device_sink_name_callback(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pInfo,
int endOfList,
void* pUserData)
14852 if (endOfList > 0) {
14857 ma_assert(pDevice !=
NULL);
14859 ma_strncpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name), pInfo->description, (
size_t)-1);
14861 (
void)pPulseContext;
14864 void ma_device_source_name_callback(ma_pa_context* pPulseContext,
const ma_pa_source_info* pInfo,
int endOfList,
void* pUserData)
14868 if (endOfList > 0) {
14873 ma_assert(pDevice !=
NULL);
14875 ma_strncpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name), pInfo->description, (
size_t)-1);
14877 (
void)pPulseContext;
14880 void ma_device_uninit__pulse(
ma_device* pDevice)
14884 ma_assert(pDevice !=
NULL);
14886 pContext = pDevice->pContext;
14887 ma_assert(pContext !=
NULL);
14890 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
14891 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
14894 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
14895 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
14898 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pDevice->pulse.pPulseContext);
14899 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pDevice->pulse.pPulseContext);
14900 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)pDevice->pulse.pMainLoop);
14903 ma_pa_buffer_attr ma_device__pa_buffer_attr_new(
ma_uint32 bufferSizeInFrames,
ma_uint32 periods,
const ma_pa_sample_spec* ss)
14905 ma_pa_buffer_attr attr;
14906 attr.maxlength = bufferSizeInFrames *
ma_get_bytes_per_sample(ma_format_from_pulse(ss->format)) * ss->channels;
14907 attr.tlength = attr.maxlength / periods;
14909 attr.minreq = attr.maxlength / periods;
14910 attr.fragsize = attr.maxlength / periods;
14915 ma_pa_stream* ma_device__pa_stream_new__pulse(
ma_device* pDevice,
const char* pStreamName,
const ma_pa_sample_spec* ss,
const ma_pa_channel_map* cmap)
14917 static int g_StreamCounter = 0;
14918 char actualStreamName[256];
14920 if (pStreamName !=
NULL) {
14921 ma_strncpy_s(actualStreamName,
sizeof(actualStreamName), pStreamName, (
size_t)-1);
14923 ma_strcpy_s(actualStreamName,
sizeof(actualStreamName),
"miniaudio:");
14924 ma_itoa_s(g_StreamCounter, actualStreamName + 8,
sizeof(actualStreamName)-8, 10);
14926 g_StreamCounter += 1;
14928 return ((ma_pa_stream_new_proc)pDevice->pContext->pulse.pa_stream_new)((ma_pa_context*)pDevice->pulse.pPulseContext, actualStreamName, ss, cmap);
14935 const char* devPlayback =
NULL;
14936 const char* devCapture =
NULL;
14938 ma_pa_sink_info sinkInfo;
14939 ma_pa_source_info sourceInfo;
14940 ma_pa_operation* pOP =
NULL;
14941 ma_pa_sample_spec ss;
14942 ma_pa_channel_map cmap;
14943 ma_pa_buffer_attr attr;
14944 const ma_pa_sample_spec* pActualSS =
NULL;
14945 const ma_pa_channel_map* pActualCMap =
NULL;
14946 const ma_pa_buffer_attr* pActualAttr =
NULL;
14948 ma_pa_stream_flags_t streamFlags;
14950 ma_assert(pDevice !=
NULL);
14951 ma_zero_object(&pDevice->pulse);
14967 if (bufferSizeInMilliseconds == 0) {
14971 pDevice->pulse.pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
14972 if (pDevice->pulse.pMainLoop ==
NULL) {
14977 pDevice->pulse.pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)((ma_pa_mainloop*)pDevice->pulse.pMainLoop);
14978 if (pDevice->pulse.pAPI ==
NULL) {
14983 pDevice->pulse.pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)((ma_pa_mainloop_api*)pDevice->pulse.pAPI, pContext->pulse.pApplicationName);
14984 if (pDevice->pulse.pPulseContext ==
NULL) {
14989 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pDevice->pulse.pPulseContext, pContext->pulse.pServerName, (pContext->pulse.tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN,
NULL);
14990 if (
error != MA_PA_OK) {
14991 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to connect PulseAudio context.", ma_result_from_pulse(
error));
14996 pDevice->pulse.pulseContextState = MA_PA_CONTEXT_UNCONNECTED;
14997 ((ma_pa_context_set_state_callback_proc)pContext->pulse.pa_context_set_state_callback)((ma_pa_context*)pDevice->pulse.pPulseContext, ma_pulse_device_state_callback, pDevice);
15001 if (pDevice->pulse.pulseContextState == MA_PA_CONTEXT_READY) {
15006 if (pDevice->pulse.pulseContextState == MA_PA_CONTEXT_FAILED || pDevice->pulse.pulseContextState == MA_PA_CONTEXT_TERMINATED) {
15007 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] An error occurred while connecting the PulseAudio context.",
MA_ERROR);
15011 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
15013 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] The PulseAudio main loop returned an error while connecting the PulseAudio context.", ma_result_from_pulse(
error));
15019 pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devCapture, ma_device_source_info_callback, &sourceInfo);
15021 ma_device__wait_for_operation__pulse(pDevice, pOP);
15022 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15024 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to retrieve source info for capture device.", ma_result_from_pulse(
error));
15028 ss = sourceInfo.sample_spec;
15029 cmap = sourceInfo.channel_map;
15032 pDevice->capture.internalPeriods = pConfig->
periods;
15034 attr = ma_device__pa_buffer_attr_new(pDevice->capture.internalBufferSizeInFrames, pConfig->
periods, &ss);
15035 #ifdef MA_DEBUG_OUTPUT
15036 printf(
"[PulseAudio] Capture attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->capture.internalBufferSizeInFrames);
15039 pDevice->pulse.pStreamCapture = ma_device__pa_stream_new__pulse(pDevice, pConfig->
pulse.
pStreamNameCapture, &ss, &cmap);
15040 if (pDevice->pulse.pStreamCapture ==
NULL) {
15045 streamFlags = MA_PA_STREAM_START_CORKED | MA_PA_STREAM_FIX_FORMAT | MA_PA_STREAM_FIX_RATE | MA_PA_STREAM_FIX_CHANNELS;
15046 if (devCapture !=
NULL) {
15047 streamFlags |= MA_PA_STREAM_DONT_MOVE;
15050 error = ((ma_pa_stream_connect_record_proc)pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags);
15051 if (
error != MA_PA_OK) {
15052 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to connect PulseAudio capture stream.", ma_result_from_pulse(
error));
15056 while (((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)((ma_pa_stream*)pDevice->pulse.pStreamCapture) != MA_PA_STREAM_READY) {
15057 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
15059 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] The PulseAudio main loop returned an error while connecting the PulseAudio capture stream.", ma_result_from_pulse(
error));
15065 pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15066 if (pActualSS !=
NULL) {
15068 if (ss.format != pActualSS->format || ss.channels != pActualSS->channels || ss.rate != pActualSS->rate) {
15069 attr = ma_device__pa_buffer_attr_new(pDevice->capture.internalBufferSizeInFrames, pConfig->
periods, pActualSS);
15071 pOP = ((ma_pa_stream_set_buffer_attr_proc)pContext->pulse.pa_stream_set_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamCapture, &attr,
NULL,
NULL);
15073 ma_device__wait_for_operation__pulse(pDevice, pOP);
15074 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15081 pDevice->capture.internalFormat = ma_format_from_pulse(ss.format);
15082 pDevice->capture.internalChannels = ss.channels;
15083 pDevice->capture.internalSampleRate = ss.rate;
15086 pActualCMap = ((ma_pa_stream_get_channel_map_proc)pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15087 if (pActualCMap !=
NULL) {
15088 cmap = *pActualCMap;
15090 for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
15091 pDevice->capture.internalChannelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
15095 pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15096 if (pActualAttr !=
NULL) {
15097 attr = *pActualAttr;
15099 pDevice->capture.internalBufferSizeInFrames = attr.maxlength / (
ma_get_bytes_per_sample(pDevice->capture.internalFormat) * pDevice->capture.internalChannels);
15100 pDevice->capture.internalPeriods = attr.maxlength / attr.fragsize;
15101 #ifdef MA_DEBUG_OUTPUT
15102 printf(
"[PulseAudio] Capture actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->capture.internalBufferSizeInFrames);
15106 devCapture = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15107 if (devCapture !=
NULL) {
15108 ma_pa_operation* pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devCapture, ma_device_source_name_callback, pDevice);
15110 ma_device__wait_for_operation__pulse(pDevice, pOP);
15111 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15117 pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devPlayback, ma_device_sink_info_callback, &sinkInfo);
15119 ma_device__wait_for_operation__pulse(pDevice, pOP);
15120 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15122 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to retrieve sink info for playback device.", ma_result_from_pulse(
error));
15126 ss = sinkInfo.sample_spec;
15127 cmap = sinkInfo.channel_map;
15130 pDevice->playback.internalPeriods = pConfig->
periods;
15132 attr = ma_device__pa_buffer_attr_new(pDevice->playback.internalBufferSizeInFrames, pConfig->
periods, &ss);
15133 #ifdef MA_DEBUG_OUTPUT
15134 printf(
"[PulseAudio] Playback attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->playback.internalBufferSizeInFrames);
15137 pDevice->pulse.pStreamPlayback = ma_device__pa_stream_new__pulse(pDevice, pConfig->
pulse.
pStreamNamePlayback, &ss, &cmap);
15138 if (pDevice->pulse.pStreamPlayback ==
NULL) {
15143 streamFlags = MA_PA_STREAM_START_CORKED | MA_PA_STREAM_FIX_FORMAT | MA_PA_STREAM_FIX_RATE | MA_PA_STREAM_FIX_CHANNELS;
15144 if (devPlayback !=
NULL) {
15145 streamFlags |= MA_PA_STREAM_DONT_MOVE;
15148 error = ((ma_pa_stream_connect_playback_proc)pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, streamFlags,
NULL,
NULL);
15149 if (
error != MA_PA_OK) {
15150 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to connect PulseAudio playback stream.", ma_result_from_pulse(
error));
15154 while (((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)((ma_pa_stream*)pDevice->pulse.pStreamPlayback) != MA_PA_STREAM_READY) {
15155 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
15157 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] The PulseAudio main loop returned an error while connecting the PulseAudio playback stream.", ma_result_from_pulse(
error));
15163 pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
15164 if (pActualSS !=
NULL) {
15166 if (ss.format != pActualSS->format || ss.channels != pActualSS->channels || ss.rate != pActualSS->rate) {
15167 attr = ma_device__pa_buffer_attr_new(pDevice->playback.internalBufferSizeInFrames, pConfig->
periods, pActualSS);
15169 pOP = ((ma_pa_stream_set_buffer_attr_proc)pContext->pulse.pa_stream_set_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, &attr,
NULL,
NULL);
15171 ma_device__wait_for_operation__pulse(pDevice, pOP);
15172 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15179 pDevice->playback.internalFormat = ma_format_from_pulse(ss.format);
15180 pDevice->playback.internalChannels = ss.channels;
15181 pDevice->playback.internalSampleRate = ss.rate;
15184 pActualCMap = ((ma_pa_stream_get_channel_map_proc)pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
15185 if (pActualCMap !=
NULL) {
15186 cmap = *pActualCMap;
15188 for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
15189 pDevice->playback.internalChannelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
15193 pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
15194 if (pActualAttr !=
NULL) {
15195 attr = *pActualAttr;
15197 pDevice->playback.internalBufferSizeInFrames = attr.maxlength / (
ma_get_bytes_per_sample(pDevice->playback.internalFormat) * pDevice->playback.internalChannels);
15198 pDevice->playback.internalPeriods = attr.maxlength / attr.tlength;
15199 #ifdef MA_DEBUG_OUTPUT
15200 printf(
"[PulseAudio] Playback actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->playback.internalBufferSizeInFrames);
15204 devPlayback = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
15205 if (devPlayback !=
NULL) {
15206 ma_pa_operation* pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devPlayback, ma_device_sink_name_callback, pDevice);
15208 ma_device__wait_for_operation__pulse(pDevice, pOP);
15209 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15219 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
15223 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
15227 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15231 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15233 on_error3: ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pDevice->pulse.pPulseContext);
15234 on_error2: ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pDevice->pulse.pPulseContext);
15235 on_error1: ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)pDevice->pulse.pMainLoop);
15241 void ma_pulse_operation_complete_callback(ma_pa_stream* pStream,
int success,
void* pUserData)
15244 ma_assert(pIsSuccessful !=
NULL);
15255 ma_pa_stream* pStream;
15256 ma_pa_operation* pOP;
15266 pStream = (ma_pa_stream*)((deviceType ==
ma_device_type_capture) ? pDevice->pulse.pStreamCapture : pDevice->pulse.pStreamPlayback);
15267 ma_assert(pStream !=
NULL);
15269 pOP = ((ma_pa_stream_cork_proc)pContext->pulse.pa_stream_cork)(pStream, cork, ma_pulse_operation_complete_callback, &wasSuccessful);
15274 result = ma_device__wait_for_operation__pulse(pDevice, pOP);
15275 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15278 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] An error occurred while waiting for the PulseAudio stream to cork.", result);
15281 if (!wasSuccessful) {
15296 ma_pa_operation* pOP;
15298 ma_assert(pDevice !=
NULL);
15309 pOP = ((ma_pa_stream_drain_proc)pDevice->pContext->pulse.pa_stream_drain)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_pulse_operation_complete_callback, &wasSuccessful);
15311 ma_device__wait_for_operation__pulse(pDevice, pOP);
15312 ((ma_pa_operation_unref_proc)pDevice->pContext->pulse.pa_operation_unref)(pOP);
15328 ma_assert(pDevice !=
NULL);
15329 ma_assert(pPCMFrames !=
NULL);
15330 ma_assert(frameCount > 0);
15333 if (((ma_pa_stream_is_corked_proc)pDevice->pContext->pulse.pa_stream_is_corked)((ma_pa_stream*)pDevice->pulse.pStreamPlayback)) {
15340 totalFramesWritten = 0;
15341 while (totalFramesWritten < frameCount) {
15343 if (pDevice->pulse.pMappedBufferPlayback !=
NULL && pDevice->pulse.mappedBufferFramesRemainingPlayback > 0) {
15345 ma_uint32 mappedBufferFramesConsumed = pDevice->pulse.mappedBufferFramesCapacityPlayback - pDevice->pulse.mappedBufferFramesRemainingPlayback;
15347 void* pDst = (
ma_uint8*)pDevice->pulse.pMappedBufferPlayback + (mappedBufferFramesConsumed * bpf);
15348 const void* pSrc = (
const ma_uint8*)pPCMFrames + (totalFramesWritten * bpf);
15349 ma_uint32 framesToCopy = ma_min(pDevice->pulse.mappedBufferFramesRemainingPlayback, (frameCount - totalFramesWritten));
15350 ma_copy_memory(pDst, pSrc, framesToCopy * bpf);
15352 pDevice->pulse.mappedBufferFramesRemainingPlayback -= framesToCopy;
15353 totalFramesWritten += framesToCopy;
15360 if (pDevice->pulse.mappedBufferFramesCapacityPlayback > 0 && pDevice->pulse.mappedBufferFramesRemainingPlayback == 0) {
15361 size_t nbytes = pDevice->pulse.mappedBufferFramesCapacityPlayback *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
15363 int error = ((ma_pa_stream_write_proc)pDevice->pContext->pulse.pa_stream_write)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, pDevice->pulse.pMappedBufferPlayback, nbytes,
NULL, 0, MA_PA_SEEK_RELATIVE);
15365 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to write data to the PulseAudio stream.", ma_result_from_pulse(
error));
15368 pDevice->pulse.pMappedBufferPlayback =
NULL;
15369 pDevice->pulse.mappedBufferFramesRemainingPlayback = 0;
15370 pDevice->pulse.mappedBufferFramesCapacityPlayback = 0;
15373 ma_assert(totalFramesWritten <= frameCount);
15374 if (totalFramesWritten == frameCount) {
15380 size_t writableSizeInBytes;
15383 if (((ma_pa_stream_is_corked_proc)pDevice->pContext->pulse.pa_stream_is_corked)((ma_pa_stream*)pDevice->pulse.pStreamPlayback)) {
15387 writableSizeInBytes = ((ma_pa_stream_writable_size_proc)pDevice->pContext->pulse.pa_stream_writable_size)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
15388 if (writableSizeInBytes != (
size_t)-1) {
15390 if (writableSizeInBytes > 0) {
15392 size_t bytesToMap = writableSizeInBytes;
15393 int error = ((ma_pa_stream_begin_write_proc)pDevice->pContext->pulse.pa_stream_begin_write)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, &pDevice->pulse.pMappedBufferPlayback, &bytesToMap);
15395 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to map write buffer.", ma_result_from_pulse(
error));
15398 pDevice->pulse.mappedBufferFramesCapacityPlayback = bytesToMap /
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
15399 pDevice->pulse.mappedBufferFramesRemainingPlayback = pDevice->pulse.mappedBufferFramesCapacityPlayback;
15404 int error = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
15406 return ma_result_from_pulse(
error);
15424 ma_assert(pDevice !=
NULL);
15425 ma_assert(pPCMFrames !=
NULL);
15426 ma_assert(frameCount > 0);
15429 if (((ma_pa_stream_is_corked_proc)pDevice->pContext->pulse.pa_stream_is_corked)((ma_pa_stream*)pDevice->pulse.pStreamCapture)) {
15436 totalFramesRead = 0;
15437 while (totalFramesRead < frameCount) {
15438 if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
15443 if (pDevice->pulse.pMappedBufferCapture !=
NULL && pDevice->pulse.mappedBufferFramesRemainingCapture > 0) {
15445 ma_uint32 mappedBufferFramesConsumed = pDevice->pulse.mappedBufferFramesCapacityCapture - pDevice->pulse.mappedBufferFramesRemainingCapture;
15447 ma_uint32 framesToCopy = ma_min(pDevice->pulse.mappedBufferFramesRemainingCapture, (frameCount - totalFramesRead));
15448 void* pDst = (
ma_uint8*)pPCMFrames + (totalFramesRead * bpf);
15454 if (pDevice->pulse.pMappedBufferCapture !=
NULL) {
15455 const void* pSrc = (
const ma_uint8*)pDevice->pulse.pMappedBufferCapture + (mappedBufferFramesConsumed * bpf);
15456 ma_copy_memory(pDst, pSrc, framesToCopy * bpf);
15458 ma_zero_memory(pDst, framesToCopy * bpf);
15461 pDevice->pulse.mappedBufferFramesRemainingCapture -= framesToCopy;
15462 totalFramesRead += framesToCopy;
15469 if (pDevice->pulse.mappedBufferFramesCapacityCapture > 0 && pDevice->pulse.mappedBufferFramesRemainingCapture == 0) {
15470 int error = ((ma_pa_stream_drop_proc)pDevice->pContext->pulse.pa_stream_drop)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15472 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to drop fragment.", ma_result_from_pulse(
error));
15475 pDevice->pulse.pMappedBufferCapture =
NULL;
15476 pDevice->pulse.mappedBufferFramesRemainingCapture = 0;
15477 pDevice->pulse.mappedBufferFramesCapacityCapture = 0;
15480 ma_assert(totalFramesRead <= frameCount);
15481 if (totalFramesRead == frameCount) {
15487 size_t readableSizeInBytes;
15489 if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
15494 if (((ma_pa_stream_is_corked_proc)pDevice->pContext->pulse.pa_stream_is_corked)((ma_pa_stream*)pDevice->pulse.pStreamCapture)) {
15498 readableSizeInBytes = ((ma_pa_stream_readable_size_proc)pDevice->pContext->pulse.pa_stream_readable_size)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
15499 if (readableSizeInBytes != (
size_t)-1) {
15501 if (readableSizeInBytes > 0) {
15503 size_t bytesMapped = (size_t)-1;
15504 int error = ((ma_pa_stream_peek_proc)pDevice->pContext->pulse.pa_stream_peek)((ma_pa_stream*)pDevice->pulse.pStreamCapture, &pDevice->pulse.pMappedBufferCapture, &bytesMapped);
15506 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to peek capture buffer.", ma_result_from_pulse(
error));
15509 if (pDevice->pulse.pMappedBufferCapture ==
NULL && bytesMapped == 0) {
15511 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Nothing available after peeking capture buffer.",
MA_ERROR);
15514 pDevice->pulse.mappedBufferFramesCapacityCapture = bytesMapped /
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
15515 pDevice->pulse.mappedBufferFramesRemainingCapture = pDevice->pulse.mappedBufferFramesCapacityCapture;
15526 int error = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 0,
NULL);
15528 return ma_result_from_pulse(
error);
15550 ma_assert(pContext !=
NULL);
15553 ma_free(pContext->pulse.pServerName);
15554 pContext->pulse.pServerName =
NULL;
15556 ma_free(pContext->pulse.pApplicationName);
15557 pContext->pulse.pApplicationName =
NULL;
15559 #ifndef MA_NO_RUNTIME_LINKING
15560 ma_dlclose(pContext, pContext->pulse.pulseSO);
15568 #ifndef MA_NO_RUNTIME_LINKING
15569 const char* libpulseNames[] = {
15575 for (
i = 0;
i < ma_countof(libpulseNames); ++
i) {
15576 pContext->pulse.pulseSO = ma_dlopen(pContext, libpulseNames[
i]);
15577 if (pContext->pulse.pulseSO !=
NULL) {
15582 if (pContext->pulse.pulseSO ==
NULL) {
15586 pContext->pulse.pa_mainloop_new = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_new");
15587 pContext->pulse.pa_mainloop_free = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_free");
15588 pContext->pulse.pa_mainloop_get_api = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_get_api");
15589 pContext->pulse.pa_mainloop_iterate = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_iterate");
15590 pContext->pulse.pa_mainloop_wakeup = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_wakeup");
15591 pContext->pulse.pa_context_new = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_new");
15592 pContext->pulse.pa_context_unref = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_unref");
15593 pContext->pulse.pa_context_connect = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_connect");
15594 pContext->pulse.pa_context_disconnect = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_disconnect");
15595 pContext->pulse.pa_context_set_state_callback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_set_state_callback");
15596 pContext->pulse.pa_context_get_state = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_state");
15597 pContext->pulse.pa_context_get_sink_info_list = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_sink_info_list");
15598 pContext->pulse.pa_context_get_source_info_list = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_source_info_list");
15599 pContext->pulse.pa_context_get_sink_info_by_name = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_sink_info_by_name");
15600 pContext->pulse.pa_context_get_source_info_by_name = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_source_info_by_name");
15601 pContext->pulse.pa_operation_unref = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_operation_unref");
15602 pContext->pulse.pa_operation_get_state = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_operation_get_state");
15603 pContext->pulse.pa_channel_map_init_extend = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_channel_map_init_extend");
15604 pContext->pulse.pa_channel_map_valid = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_channel_map_valid");
15605 pContext->pulse.pa_channel_map_compatible = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_channel_map_compatible");
15606 pContext->pulse.pa_stream_new = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_new");
15607 pContext->pulse.pa_stream_unref = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_unref");
15608 pContext->pulse.pa_stream_connect_playback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_connect_playback");
15609 pContext->pulse.pa_stream_connect_record = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_connect_record");
15610 pContext->pulse.pa_stream_disconnect = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_disconnect");
15611 pContext->pulse.pa_stream_get_state = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_state");
15612 pContext->pulse.pa_stream_get_sample_spec = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_sample_spec");
15613 pContext->pulse.pa_stream_get_channel_map = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_channel_map");
15614 pContext->pulse.pa_stream_get_buffer_attr = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_buffer_attr");
15615 pContext->pulse.pa_stream_set_buffer_attr = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_set_buffer_attr");
15616 pContext->pulse.pa_stream_get_device_name = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_device_name");
15617 pContext->pulse.pa_stream_set_write_callback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_set_write_callback");
15618 pContext->pulse.pa_stream_set_read_callback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_set_read_callback");
15619 pContext->pulse.pa_stream_flush = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_flush");
15620 pContext->pulse.pa_stream_drain = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_drain");
15621 pContext->pulse.pa_stream_is_corked = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_is_corked");
15622 pContext->pulse.pa_stream_cork = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_cork");
15623 pContext->pulse.pa_stream_trigger = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_trigger");
15624 pContext->pulse.pa_stream_begin_write = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_begin_write");
15625 pContext->pulse.pa_stream_write = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_write");
15626 pContext->pulse.pa_stream_peek = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_peek");
15627 pContext->pulse.pa_stream_drop = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_drop");
15628 pContext->pulse.pa_stream_writable_size = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_writable_size");
15629 pContext->pulse.pa_stream_readable_size = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_readable_size");
15632 ma_pa_mainloop_new_proc _pa_mainloop_new = pa_mainloop_new;
15633 ma_pa_mainloop_free_proc _pa_mainloop_free = pa_mainloop_free;
15634 ma_pa_mainloop_get_api_proc _pa_mainloop_get_api = pa_mainloop_get_api;
15635 ma_pa_mainloop_iterate_proc _pa_mainloop_iterate = pa_mainloop_iterate;
15636 ma_pa_mainloop_wakeup_proc _pa_mainloop_wakeup = pa_mainloop_wakeup;
15637 ma_pa_context_new_proc _pa_context_new = pa_context_new;
15638 ma_pa_context_unref_proc _pa_context_unref = pa_context_unref;
15639 ma_pa_context_connect_proc _pa_context_connect = pa_context_connect;
15640 ma_pa_context_disconnect_proc _pa_context_disconnect = pa_context_disconnect;
15641 ma_pa_context_set_state_callback_proc _pa_context_set_state_callback = pa_context_set_state_callback;
15642 ma_pa_context_get_state_proc _pa_context_get_state = pa_context_get_state;
15643 ma_pa_context_get_sink_info_list_proc _pa_context_get_sink_info_list = pa_context_get_sink_info_list;
15644 ma_pa_context_get_source_info_list_proc _pa_context_get_source_info_list = pa_context_get_source_info_list;
15645 ma_pa_context_get_sink_info_by_name_proc _pa_context_get_sink_info_by_name = pa_context_get_sink_info_by_name;
15646 ma_pa_context_get_source_info_by_name_proc _pa_context_get_source_info_by_name= pa_context_get_source_info_by_name;
15647 ma_pa_operation_unref_proc _pa_operation_unref = pa_operation_unref;
15648 ma_pa_operation_get_state_proc _pa_operation_get_state = pa_operation_get_state;
15649 ma_pa_channel_map_init_extend_proc _pa_channel_map_init_extend = pa_channel_map_init_extend;
15650 ma_pa_channel_map_valid_proc _pa_channel_map_valid = pa_channel_map_valid;
15651 ma_pa_channel_map_compatible_proc _pa_channel_map_compatible = pa_channel_map_compatible;
15652 ma_pa_stream_new_proc _pa_stream_new = pa_stream_new;
15653 ma_pa_stream_unref_proc _pa_stream_unref = pa_stream_unref;
15654 ma_pa_stream_connect_playback_proc _pa_stream_connect_playback = pa_stream_connect_playback;
15655 ma_pa_stream_connect_record_proc _pa_stream_connect_record = pa_stream_connect_record;
15656 ma_pa_stream_disconnect_proc _pa_stream_disconnect = pa_stream_disconnect;
15657 ma_pa_stream_get_state_proc _pa_stream_get_state = pa_stream_get_state;
15658 ma_pa_stream_get_sample_spec_proc _pa_stream_get_sample_spec = pa_stream_get_sample_spec;
15659 ma_pa_stream_get_channel_map_proc _pa_stream_get_channel_map = pa_stream_get_channel_map;
15660 ma_pa_stream_get_buffer_attr_proc _pa_stream_get_buffer_attr = pa_stream_get_buffer_attr;
15661 ma_pa_stream_set_buffer_attr_proc _pa_stream_set_buffer_attr = pa_stream_set_buffer_attr;
15662 ma_pa_stream_get_device_name_proc _pa_stream_get_device_name = pa_stream_get_device_name;
15663 ma_pa_stream_set_write_callback_proc _pa_stream_set_write_callback = pa_stream_set_write_callback;
15664 ma_pa_stream_set_read_callback_proc _pa_stream_set_read_callback = pa_stream_set_read_callback;
15665 ma_pa_stream_flush_proc _pa_stream_flush = pa_stream_flush;
15666 ma_pa_stream_drain_proc _pa_stream_drain = pa_stream_drain;
15667 ma_pa_stream_is_corked_proc _pa_stream_is_corked = pa_stream_is_corked;
15668 ma_pa_stream_cork_proc _pa_stream_cork = pa_stream_cork;
15669 ma_pa_stream_trigger_proc _pa_stream_trigger = pa_stream_trigger;
15670 ma_pa_stream_begin_write_proc _pa_stream_begin_write = pa_stream_begin_write;
15671 ma_pa_stream_write_proc _pa_stream_write = pa_stream_write;
15672 ma_pa_stream_peek_proc _pa_stream_peek = pa_stream_peek;
15673 ma_pa_stream_drop_proc _pa_stream_drop = pa_stream_drop;
15674 ma_pa_stream_writable_size_proc _pa_stream_writable_size = pa_stream_writable_size;
15675 ma_pa_stream_readable_size_proc _pa_stream_readable_size = pa_stream_readable_size;
15677 pContext->pulse.pa_mainloop_new = (
ma_proc)_pa_mainloop_new;
15678 pContext->pulse.pa_mainloop_free = (
ma_proc)_pa_mainloop_free;
15679 pContext->pulse.pa_mainloop_get_api = (
ma_proc)_pa_mainloop_get_api;
15680 pContext->pulse.pa_mainloop_iterate = (
ma_proc)_pa_mainloop_iterate;
15681 pContext->pulse.pa_mainloop_wakeup = (
ma_proc)_pa_mainloop_wakeup;
15682 pContext->pulse.pa_context_new = (
ma_proc)_pa_context_new;
15683 pContext->pulse.pa_context_unref = (
ma_proc)_pa_context_unref;
15684 pContext->pulse.pa_context_connect = (
ma_proc)_pa_context_connect;
15685 pContext->pulse.pa_context_disconnect = (
ma_proc)_pa_context_disconnect;
15686 pContext->pulse.pa_context_set_state_callback = (
ma_proc)_pa_context_set_state_callback;
15687 pContext->pulse.pa_context_get_state = (
ma_proc)_pa_context_get_state;
15688 pContext->pulse.pa_context_get_sink_info_list = (
ma_proc)_pa_context_get_sink_info_list;
15689 pContext->pulse.pa_context_get_source_info_list = (
ma_proc)_pa_context_get_source_info_list;
15690 pContext->pulse.pa_context_get_sink_info_by_name = (
ma_proc)_pa_context_get_sink_info_by_name;
15691 pContext->pulse.pa_context_get_source_info_by_name = (
ma_proc)_pa_context_get_source_info_by_name;
15692 pContext->pulse.pa_operation_unref = (
ma_proc)_pa_operation_unref;
15693 pContext->pulse.pa_operation_get_state = (
ma_proc)_pa_operation_get_state;
15694 pContext->pulse.pa_channel_map_init_extend = (
ma_proc)_pa_channel_map_init_extend;
15695 pContext->pulse.pa_channel_map_valid = (
ma_proc)_pa_channel_map_valid;
15696 pContext->pulse.pa_channel_map_compatible = (
ma_proc)_pa_channel_map_compatible;
15697 pContext->pulse.pa_stream_new = (
ma_proc)_pa_stream_new;
15698 pContext->pulse.pa_stream_unref = (
ma_proc)_pa_stream_unref;
15699 pContext->pulse.pa_stream_connect_playback = (
ma_proc)_pa_stream_connect_playback;
15700 pContext->pulse.pa_stream_connect_record = (
ma_proc)_pa_stream_connect_record;
15701 pContext->pulse.pa_stream_disconnect = (
ma_proc)_pa_stream_disconnect;
15702 pContext->pulse.pa_stream_get_state = (
ma_proc)_pa_stream_get_state;
15703 pContext->pulse.pa_stream_get_sample_spec = (
ma_proc)_pa_stream_get_sample_spec;
15704 pContext->pulse.pa_stream_get_channel_map = (
ma_proc)_pa_stream_get_channel_map;
15705 pContext->pulse.pa_stream_get_buffer_attr = (
ma_proc)_pa_stream_get_buffer_attr;
15706 pContext->pulse.pa_stream_set_buffer_attr = (
ma_proc)_pa_stream_set_buffer_attr;
15707 pContext->pulse.pa_stream_get_device_name = (
ma_proc)_pa_stream_get_device_name;
15708 pContext->pulse.pa_stream_set_write_callback = (
ma_proc)_pa_stream_set_write_callback;
15709 pContext->pulse.pa_stream_set_read_callback = (
ma_proc)_pa_stream_set_read_callback;
15710 pContext->pulse.pa_stream_flush = (
ma_proc)_pa_stream_flush;
15711 pContext->pulse.pa_stream_drain = (
ma_proc)_pa_stream_drain;
15712 pContext->pulse.pa_stream_is_corked = (
ma_proc)_pa_stream_is_corked;
15713 pContext->pulse.pa_stream_cork = (
ma_proc)_pa_stream_cork;
15714 pContext->pulse.pa_stream_trigger = (
ma_proc)_pa_stream_trigger;
15715 pContext->pulse.pa_stream_begin_write = (
ma_proc)_pa_stream_begin_write;
15716 pContext->pulse.pa_stream_write = (
ma_proc)_pa_stream_write;
15717 pContext->pulse.pa_stream_peek = (
ma_proc)_pa_stream_peek;
15718 pContext->pulse.pa_stream_drop = (
ma_proc)_pa_stream_drop;
15719 pContext->pulse.pa_stream_writable_size = (
ma_proc)_pa_stream_writable_size;
15720 pContext->pulse.pa_stream_readable_size = (
ma_proc)_pa_stream_readable_size;
15723 pContext->
onUninit = ma_context_uninit__pulse;
15725 pContext->
onEnumDevices = ma_context_enumerate_devices__pulse;
15747 ma_pa_mainloop* pMainLoop;
15748 ma_pa_mainloop_api* pAPI;
15749 ma_pa_context* pPulseContext;
15752 pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
15753 if (pMainLoop ==
NULL) {
15754 ma_free(pContext->pulse.pServerName);
15755 ma_free(pContext->pulse.pApplicationName);
15756 #ifndef MA_NO_RUNTIME_LINKING
15757 ma_dlclose(pContext, pContext->pulse.pulseSO);
15762 pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
15763 if (pAPI ==
NULL) {
15764 ma_free(pContext->pulse.pServerName);
15765 ma_free(pContext->pulse.pApplicationName);
15766 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15767 #ifndef MA_NO_RUNTIME_LINKING
15768 ma_dlclose(pContext, pContext->pulse.pulseSO);
15773 pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->pulse.pApplicationName);
15774 if (pPulseContext ==
NULL) {
15775 ma_free(pContext->pulse.pServerName);
15776 ma_free(pContext->pulse.pApplicationName);
15777 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15778 #ifndef MA_NO_RUNTIME_LINKING
15779 ma_dlclose(pContext, pContext->pulse.pulseSO);
15784 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->pulse.pServerName, 0,
NULL);
15785 if (
error != MA_PA_OK) {
15786 ma_free(pContext->pulse.pServerName);
15787 ma_free(pContext->pulse.pApplicationName);
15788 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
15789 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15790 #ifndef MA_NO_RUNTIME_LINKING
15791 ma_dlclose(pContext, pContext->pulse.pulseSO);
15796 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
15797 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
15798 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15814 #ifdef MA_NO_RUNTIME_LINKING
15815 #include <jack/jack.h>
15817 typedef jack_nframes_t ma_jack_nframes_t;
15818 typedef jack_options_t ma_jack_options_t;
15819 typedef jack_status_t ma_jack_status_t;
15820 typedef jack_client_t ma_jack_client_t;
15821 typedef jack_port_t ma_jack_port_t;
15822 typedef JackProcessCallback ma_JackProcessCallback;
15823 typedef JackBufferSizeCallback ma_JackBufferSizeCallback;
15824 typedef JackShutdownCallback ma_JackShutdownCallback;
15825 #define MA_JACK_DEFAULT_AUDIO_TYPE JACK_DEFAULT_AUDIO_TYPE
15826 #define ma_JackNoStartServer JackNoStartServer
15827 #define ma_JackPortIsInput JackPortIsInput
15828 #define ma_JackPortIsOutput JackPortIsOutput
15829 #define ma_JackPortIsPhysical JackPortIsPhysical
15832 typedef int ma_jack_options_t;
15833 typedef int ma_jack_status_t;
15834 typedef struct ma_jack_client_t ma_jack_client_t;
15835 typedef struct ma_jack_port_t ma_jack_port_t;
15836 typedef int (* ma_JackProcessCallback) (ma_jack_nframes_t nframes,
void* arg);
15837 typedef int (* ma_JackBufferSizeCallback)(ma_jack_nframes_t nframes,
void* arg);
15838 typedef void (* ma_JackShutdownCallback) (
void* arg);
15839 #define MA_JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio"
15840 #define ma_JackNoStartServer 1
15841 #define ma_JackPortIsInput 1
15842 #define ma_JackPortIsOutput 2
15843 #define ma_JackPortIsPhysical 4
15846 typedef ma_jack_client_t* (* ma_jack_client_open_proc) (
const char* client_name, ma_jack_options_t options, ma_jack_status_t* status, ...);
15847 typedef int (* ma_jack_client_close_proc) (ma_jack_client_t* client);
15848 typedef int (* ma_jack_client_name_size_proc) ();
15849 typedef int (* ma_jack_set_process_callback_proc) (ma_jack_client_t* client, ma_JackProcessCallback process_callback,
void* arg);
15850 typedef int (* ma_jack_set_buffer_size_callback_proc)(ma_jack_client_t* client, ma_JackBufferSizeCallback bufsize_callback,
void* arg);
15851 typedef void (* ma_jack_on_shutdown_proc) (ma_jack_client_t* client, ma_JackShutdownCallback
function,
void* arg);
15852 typedef ma_jack_nframes_t (* ma_jack_get_sample_rate_proc) (ma_jack_client_t* client);
15853 typedef ma_jack_nframes_t (* ma_jack_get_buffer_size_proc) (ma_jack_client_t* client);
15854 typedef const char** (* ma_jack_get_ports_proc) (ma_jack_client_t* client,
const char* port_name_pattern,
const char* type_name_pattern,
unsigned long flags);
15855 typedef int (* ma_jack_activate_proc) (ma_jack_client_t* client);
15856 typedef int (* ma_jack_deactivate_proc) (ma_jack_client_t* client);
15857 typedef int (* ma_jack_connect_proc) (ma_jack_client_t* client,
const char* source_port,
const char* destination_port);
15858 typedef ma_jack_port_t* (* ma_jack_port_register_proc) (ma_jack_client_t* client,
const char* port_name,
const char* port_type,
unsigned long flags,
unsigned long buffer_size);
15859 typedef const char* (* ma_jack_port_name_proc) (
const ma_jack_port_t* port);
15860 typedef void* (* ma_jack_port_get_buffer_proc) (ma_jack_port_t* port, ma_jack_nframes_t nframes);
15861 typedef void (* ma_jack_free_proc) (
void* ptr);
15863 ma_result ma_context_open_client__jack(
ma_context* pContext, ma_jack_client_t** ppClient)
15865 size_t maxClientNameSize;
15866 char clientName[256];
15867 ma_jack_status_t status;
15868 ma_jack_client_t* pClient;
15870 ma_assert(pContext !=
NULL);
15871 ma_assert(ppClient !=
NULL);
15877 maxClientNameSize = ((ma_jack_client_name_size_proc)pContext->
jack.jack_client_name_size)();
15878 ma_strncpy_s(clientName, ma_min(
sizeof(clientName), maxClientNameSize), (pContext->
jack.pClientName !=
NULL) ? pContext->
jack.pClientName :
"miniaudio", (
size_t)-1);
15880 pClient = ((ma_jack_client_open_proc)pContext->
jack.jack_client_open)(clientName, (pContext->
jack.tryStartServer) ? 0 : ma_JackNoStartServer, &status,
NULL);
15881 if (pClient ==
NULL) {
15886 *ppClient = pClient;
15894 ma_assert(pContext !=
NULL);
15895 ma_assert(pID0 !=
NULL);
15896 ma_assert(pID1 !=
NULL);
15906 ma_assert(pContext !=
NULL);
15907 ma_assert(callback !=
NULL);
15912 ma_zero_object(&deviceInfo);
15913 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
15920 ma_zero_object(&deviceInfo);
15921 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
15930 ma_jack_client_t* pClient;
15932 const char** ppPorts;
15934 ma_assert(pContext !=
NULL);
15941 if (pDeviceID !=
NULL && pDeviceID->
jack != 0) {
15947 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
15949 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
15957 result = ma_context_open_client__jack(pContext, &pClient);
15962 pDeviceInfo->
minSampleRate = ((ma_jack_get_sample_rate_proc)pContext->
jack.jack_get_sample_rate)((ma_jack_client_t*)pClient);
15968 ppPorts = ((ma_jack_get_ports_proc)pContext->
jack.jack_get_ports)((ma_jack_client_t*)pClient,
NULL,
NULL, ma_JackPortIsPhysical | ((deviceType ==
ma_device_type_playback) ? ma_JackPortIsInput : ma_JackPortIsOutput));
15969 if (ppPorts ==
NULL) {
15970 ((ma_jack_client_close_proc)pContext->
jack.jack_client_close)((ma_jack_client_t*)pClient);
15979 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppPorts);
15980 ((ma_jack_client_close_proc)pContext->
jack.jack_client_close)((ma_jack_client_t*)pClient);
15987 void ma_device_uninit__jack(
ma_device* pDevice)
15991 ma_assert(pDevice !=
NULL);
15993 pContext = pDevice->pContext;
15994 ma_assert(pContext !=
NULL);
15996 if (pDevice->jack.pClient !=
NULL) {
15997 ((ma_jack_client_close_proc)pContext->
jack.jack_client_close)((ma_jack_client_t*)pDevice->jack.pClient);
16001 ma_free(pDevice->jack.pIntermediaryBufferCapture);
16005 ma_free(pDevice->jack.pIntermediaryBufferPlayback);
16013 void ma_device__jack_shutdown_callback(
void* pUserData)
16017 ma_assert(pDevice !=
NULL);
16022 int ma_device__jack_buffer_size_callback(ma_jack_nframes_t frameCount,
void* pUserData)
16025 ma_assert(pDevice !=
NULL);
16028 float* pNewBuffer = (
float*)
ma_realloc(pDevice->jack.pIntermediaryBufferCapture, frameCount * (pDevice->capture.internalChannels *
ma_get_bytes_per_sample(pDevice->capture.internalFormat)));
16029 if (pNewBuffer ==
NULL) {
16033 pDevice->jack.pIntermediaryBufferCapture = pNewBuffer;
16034 pDevice->playback.internalBufferSizeInFrames = frameCount * pDevice->capture.internalPeriods;
16038 float* pNewBuffer = (
float*)
ma_realloc(pDevice->jack.pIntermediaryBufferPlayback, frameCount * (pDevice->playback.internalChannels *
ma_get_bytes_per_sample(pDevice->playback.internalFormat)));
16039 if (pNewBuffer ==
NULL) {
16043 pDevice->jack.pIntermediaryBufferPlayback = pNewBuffer;
16044 pDevice->playback.internalBufferSizeInFrames = frameCount * pDevice->playback.internalPeriods;
16050 int ma_device__jack_process_callback(ma_jack_nframes_t frameCount,
void* pUserData)
16057 ma_assert(pDevice !=
NULL);
16059 pContext = pDevice->pContext;
16060 ma_assert(pContext !=
NULL);
16064 for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
16065 const float* pSrc = (
const float*)((ma_jack_port_get_buffer_proc)pContext->
jack.jack_port_get_buffer)((ma_jack_port_t*)pDevice->jack.pPortsCapture[iChannel], frameCount);
16066 if (pSrc !=
NULL) {
16067 float* pDst = pDevice->jack.pIntermediaryBufferCapture + iChannel;
16068 ma_jack_nframes_t iFrame;
16069 for (iFrame = 0; iFrame < frameCount; ++iFrame) {
16072 pDst += pDevice->capture.internalChannels;
16079 ma_device__handle_duplex_callback_capture(pDevice, frameCount, pDevice->jack.pIntermediaryBufferCapture, &pDevice->jack.duplexRB);
16081 ma_device__send_frames_to_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferCapture);
16087 ma_device__handle_duplex_callback_playback(pDevice, frameCount, pDevice->jack.pIntermediaryBufferPlayback, &pDevice->jack.duplexRB);
16089 ma_device__read_frames_from_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferPlayback);
16093 for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
16094 float* pDst = (
float*)((ma_jack_port_get_buffer_proc)pContext->
jack.jack_port_get_buffer)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[iChannel], frameCount);
16095 if (pDst !=
NULL) {
16096 const float* pSrc = pDevice->jack.pIntermediaryBufferPlayback + iChannel;
16097 ma_jack_nframes_t iFrame;
16098 for (iFrame = 0; iFrame < frameCount; ++iFrame) {
16102 pSrc += pDevice->playback.internalChannels;
16117 ma_assert(pContext !=
NULL);
16118 ma_assert(pConfig !=
NULL);
16119 ma_assert(pDevice !=
NULL);
16134 result = ma_context_open_client__jack(pContext, (ma_jack_client_t**)&pDevice->jack.pClient);
16140 if (((ma_jack_set_process_callback_proc)pContext->
jack.jack_set_process_callback)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_process_callback, pDevice) != 0) {
16143 if (((ma_jack_set_buffer_size_callback_proc)pContext->
jack.jack_set_buffer_size_callback)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_buffer_size_callback, pDevice) != 0) {
16147 ((ma_jack_on_shutdown_proc)pContext->
jack.jack_on_shutdown)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_shutdown_callback, pDevice);
16152 bufferSizeInFrames = ((ma_jack_get_buffer_size_proc)pContext->
jack.jack_get_buffer_size)((ma_jack_client_t*)pDevice->jack.pClient) * periods;
16155 const char** ppPorts;
16158 pDevice->capture.internalChannels = 0;
16159 pDevice->capture.internalSampleRate = ((ma_jack_get_sample_rate_proc)pContext->
jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
16162 ppPorts = ((ma_jack_get_ports_proc)pContext->
jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsOutput);
16163 if (ppPorts ==
NULL) {
16167 while (ppPorts[pDevice->capture.internalChannels] !=
NULL) {
16169 ma_strcpy_s(
name,
sizeof(
name),
"capture");
16170 ma_itoa_s((
int)pDevice->capture.internalChannels,
name+7,
sizeof(
name)-7, 10);
16172 pDevice->jack.pPortsCapture[pDevice->capture.internalChannels] = ((ma_jack_port_register_proc)pContext->
jack.jack_port_register)((ma_jack_client_t*)pDevice->jack.pClient,
name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsInput, 0);
16173 if (pDevice->jack.pPortsCapture[pDevice->capture.internalChannels] ==
NULL) {
16174 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppPorts);
16175 ma_device_uninit__jack(pDevice);
16179 pDevice->capture.internalChannels += 1;
16182 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppPorts);
16184 pDevice->capture.internalBufferSizeInFrames = bufferSizeInFrames;
16185 pDevice->capture.internalPeriods = periods;
16187 pDevice->jack.pIntermediaryBufferCapture = (
float*)
ma_malloc((pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods) * (pDevice->capture.internalChannels *
ma_get_bytes_per_sample(pDevice->capture.internalFormat)));
16188 if (pDevice->jack.pIntermediaryBufferCapture ==
NULL) {
16189 ma_device_uninit__jack(pDevice);
16195 const char** ppPorts;
16198 pDevice->playback.internalChannels = 0;
16199 pDevice->playback.internalSampleRate = ((ma_jack_get_sample_rate_proc)pContext->
jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
16202 ppPorts = ((ma_jack_get_ports_proc)pContext->
jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsInput);
16203 if (ppPorts ==
NULL) {
16207 while (ppPorts[pDevice->playback.internalChannels] !=
NULL) {
16209 ma_strcpy_s(
name,
sizeof(
name),
"playback");
16210 ma_itoa_s((
int)pDevice->playback.internalChannels,
name+8,
sizeof(
name)-8, 10);
16212 pDevice->jack.pPortsPlayback[pDevice->playback.internalChannels] = ((ma_jack_port_register_proc)pContext->
jack.jack_port_register)((ma_jack_client_t*)pDevice->jack.pClient,
name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsOutput, 0);
16213 if (pDevice->jack.pPortsPlayback[pDevice->playback.internalChannels] ==
NULL) {
16214 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppPorts);
16215 ma_device_uninit__jack(pDevice);
16219 pDevice->playback.internalChannels += 1;
16222 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppPorts);
16224 pDevice->playback.internalBufferSizeInFrames = bufferSizeInFrames;
16225 pDevice->playback.internalPeriods = periods;
16227 pDevice->jack.pIntermediaryBufferPlayback = (
float*)
ma_malloc((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods) * (pDevice->playback.internalChannels *
ma_get_bytes_per_sample(pDevice->playback.internalFormat)));
16228 if (pDevice->jack.pIntermediaryBufferPlayback ==
NULL) {
16229 ma_device_uninit__jack(pDevice);
16235 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
16236 result =
ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames,
NULL, &pDevice->jack.duplexRB);
16238 ma_device_uninit__jack(pDevice);
16239 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[JACK] Failed to initialize ring buffer.", result);
16253 resultJACK = ((ma_jack_activate_proc)pContext->
jack.jack_activate)((ma_jack_client_t*)pDevice->jack.pClient);
16254 if (resultJACK != 0) {
16259 const char** ppServerPorts = ((ma_jack_get_ports_proc)pContext->
jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsOutput);
16260 if (ppServerPorts ==
NULL) {
16261 ((ma_jack_deactivate_proc)pContext->
jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
16265 for (
i = 0; ppServerPorts[
i] !=
NULL; ++
i) {
16266 const char* pServerPort = ppServerPorts[
i];
16267 const char* pClientPort = ((ma_jack_port_name_proc)pContext->
jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsCapture[
i]);
16269 resultJACK = ((ma_jack_connect_proc)pContext->
jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pServerPort, pClientPort);
16270 if (resultJACK != 0) {
16271 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppServerPorts);
16272 ((ma_jack_deactivate_proc)pContext->
jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
16277 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppServerPorts);
16281 const char** ppServerPorts = ((ma_jack_get_ports_proc)pContext->
jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsInput);
16282 if (ppServerPorts ==
NULL) {
16283 ((ma_jack_deactivate_proc)pContext->
jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
16287 for (
i = 0; ppServerPorts[
i] !=
NULL; ++
i) {
16288 const char* pServerPort = ppServerPorts[
i];
16289 const char* pClientPort = ((ma_jack_port_name_proc)pContext->
jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[
i]);
16291 resultJACK = ((ma_jack_connect_proc)pContext->
jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pClientPort, pServerPort);
16292 if (resultJACK != 0) {
16293 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppServerPorts);
16294 ((ma_jack_deactivate_proc)pContext->
jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
16299 ((ma_jack_free_proc)pContext->
jack.jack_free)((
void*)ppServerPorts);
16310 if (((ma_jack_deactivate_proc)pContext->
jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient) != 0) {
16314 onStop = pDevice->onStop;
16325 ma_assert(pContext !=
NULL);
16329 pContext->
jack.pClientName =
NULL;
16331 #ifndef MA_NO_RUNTIME_LINKING
16332 ma_dlclose(pContext, pContext->
jack.jackSO);
16340 #ifndef MA_NO_RUNTIME_LINKING
16341 const char* libjackNames[] = {
16351 for (
i = 0;
i < ma_countof(libjackNames); ++
i) {
16352 pContext->
jack.jackSO = ma_dlopen(pContext, libjackNames[
i]);
16353 if (pContext->
jack.jackSO !=
NULL) {
16358 if (pContext->
jack.jackSO ==
NULL) {
16362 pContext->
jack.jack_client_open = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_client_open");
16363 pContext->
jack.jack_client_close = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_client_close");
16364 pContext->
jack.jack_client_name_size = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_client_name_size");
16365 pContext->
jack.jack_set_process_callback = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_set_process_callback");
16366 pContext->
jack.jack_set_buffer_size_callback = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_set_buffer_size_callback");
16367 pContext->
jack.jack_on_shutdown = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_on_shutdown");
16368 pContext->
jack.jack_get_sample_rate = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_get_sample_rate");
16369 pContext->
jack.jack_get_buffer_size = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_get_buffer_size");
16370 pContext->
jack.jack_get_ports = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_get_ports");
16371 pContext->
jack.jack_activate = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_activate");
16372 pContext->
jack.jack_deactivate = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_deactivate");
16373 pContext->
jack.jack_connect = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_connect");
16374 pContext->
jack.jack_port_register = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_port_register");
16375 pContext->
jack.jack_port_name = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_port_name");
16376 pContext->
jack.jack_port_get_buffer = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_port_get_buffer");
16377 pContext->
jack.jack_free = (
ma_proc)ma_dlsym(pContext, pContext->
jack.jackSO,
"jack_free");
16383 ma_jack_client_open_proc _jack_client_open = jack_client_open;
16384 ma_jack_client_close_proc _jack_client_close = jack_client_close;
16385 ma_jack_client_name_size_proc _jack_client_name_size = jack_client_name_size;
16386 ma_jack_set_process_callback_proc _jack_set_process_callback = jack_set_process_callback;
16387 ma_jack_set_buffer_size_callback_proc _jack_set_buffer_size_callback = jack_set_buffer_size_callback;
16388 ma_jack_on_shutdown_proc _jack_on_shutdown = jack_on_shutdown;
16389 ma_jack_get_sample_rate_proc _jack_get_sample_rate = jack_get_sample_rate;
16390 ma_jack_get_buffer_size_proc _jack_get_buffer_size = jack_get_buffer_size;
16391 ma_jack_get_ports_proc _jack_get_ports = jack_get_ports;
16392 ma_jack_activate_proc _jack_activate = jack_activate;
16393 ma_jack_deactivate_proc _jack_deactivate = jack_deactivate;
16394 ma_jack_connect_proc _jack_connect = jack_connect;
16395 ma_jack_port_register_proc _jack_port_register = jack_port_register;
16396 ma_jack_port_name_proc _jack_port_name = jack_port_name;
16397 ma_jack_port_get_buffer_proc _jack_port_get_buffer = jack_port_get_buffer;
16398 ma_jack_free_proc _jack_free = jack_free;
16400 pContext->
jack.jack_client_open = (
ma_proc)_jack_client_open;
16401 pContext->
jack.jack_client_close = (
ma_proc)_jack_client_close;
16402 pContext->
jack.jack_client_name_size = (
ma_proc)_jack_client_name_size;
16403 pContext->
jack.jack_set_process_callback = (
ma_proc)_jack_set_process_callback;
16404 pContext->
jack.jack_set_buffer_size_callback = (
ma_proc)_jack_set_buffer_size_callback;
16405 pContext->
jack.jack_on_shutdown = (
ma_proc)_jack_on_shutdown;
16406 pContext->
jack.jack_get_sample_rate = (
ma_proc)_jack_get_sample_rate;
16407 pContext->
jack.jack_get_buffer_size = (
ma_proc)_jack_get_buffer_size;
16408 pContext->
jack.jack_get_ports = (
ma_proc)_jack_get_ports;
16409 pContext->
jack.jack_activate = (
ma_proc)_jack_activate;
16410 pContext->
jack.jack_deactivate = (
ma_proc)_jack_deactivate;
16411 pContext->
jack.jack_connect = (
ma_proc)_jack_connect;
16412 pContext->
jack.jack_port_register = (
ma_proc)_jack_port_register;
16413 pContext->
jack.jack_port_name = (
ma_proc)_jack_port_name;
16414 pContext->
jack.jack_port_get_buffer = (
ma_proc)_jack_port_get_buffer;
16420 pContext->
onUninit = ma_context_uninit__jack;
16422 pContext->
onEnumDevices = ma_context_enumerate_devices__jack;
16439 ma_jack_client_t* pDummyClient;
16440 ma_result result = ma_context_open_client__jack(pContext, &pDummyClient);
16443 #ifndef MA_NO_RUNTIME_LINKING
16444 ma_dlclose(pContext, pContext->
jack.jackSO);
16449 ((ma_jack_client_close_proc)pContext->
jack.jack_client_close)((ma_jack_client_t*)pDummyClient);
16463 #ifdef MA_HAS_COREAUDIO
16464 #include <TargetConditionals.h>
16466 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1
16467 #define MA_APPLE_MOBILE
16469 #define MA_APPLE_DESKTOP
16472 #if defined(MA_APPLE_DESKTOP)
16473 #include <CoreAudio/CoreAudio.h>
16475 #include <AVFoundation/AVFoundation.h>
16478 #include <AudioToolbox/AudioToolbox.h>
16481 typedef Boolean (* ma_CFStringGetCString_proc)(CFStringRef theString,
char*
buffer, CFIndex bufferSize, CFStringEncoding encoding);
16484 #if defined(MA_APPLE_DESKTOP)
16485 typedef OSStatus (* ma_AudioObjectGetPropertyData_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* ioDataSize,
void* outData);
16486 typedef OSStatus (* ma_AudioObjectGetPropertyDataSize_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* outDataSize);
16487 typedef OSStatus (* ma_AudioObjectSetPropertyData_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32 inDataSize,
const void* inData);
16488 typedef OSStatus (* ma_AudioObjectAddPropertyListener_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener,
void* inClientData);
16492 typedef AudioComponent (* ma_AudioComponentFindNext_proc)(AudioComponent inComponent,
const AudioComponentDescription* inDesc);
16493 typedef OSStatus (* ma_AudioComponentInstanceDispose_proc)(AudioComponentInstance inInstance);
16494 typedef OSStatus (* ma_AudioComponentInstanceNew_proc)(AudioComponent inComponent, AudioComponentInstance* outInstance);
16495 typedef OSStatus (* ma_AudioOutputUnitStart_proc)(AudioUnit inUnit);
16496 typedef OSStatus (* ma_AudioOutputUnitStop_proc)(AudioUnit inUnit);
16497 typedef OSStatus (* ma_AudioUnitAddPropertyListener_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc,
void* inProcUserData);
16498 typedef OSStatus (* ma_AudioUnitGetPropertyInfo_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, UInt32* outDataSize, Boolean* outWriteable);
16499 typedef OSStatus (* ma_AudioUnitGetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32* ioDataSize);
16500 typedef OSStatus (* ma_AudioUnitSetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32 inDataSize);
16501 typedef OSStatus (* ma_AudioUnitInitialize_proc)(AudioUnit inUnit);
16502 typedef OSStatus (* ma_AudioUnitRender_proc)(AudioUnit inUnit, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData);
16505 #define MA_COREAUDIO_OUTPUT_BUS 0
16506 #define MA_COREAUDIO_INPUT_BUS 1
16543 ma_result ma_result_from_OSStatus(OSStatus status)
16548 #if defined(MA_APPLE_DESKTOP)
16550 case kAudioHardwareUnspecifiedError:
return MA_ERROR;
16566 ma_channel ma_channel_from_AudioChannelBitmap(AudioChannelBitmap bit)
16593 ma_channel ma_channel_from_AudioChannelLabel(AudioChannelLabel label)
16687 ma_result ma_format_from_AudioStreamBasicDescription(
const AudioStreamBasicDescription* pDescription,
ma_format* pFormatOut)
16689 ma_assert(pDescription !=
NULL);
16690 ma_assert(pFormatOut !=
NULL);
16695 if (pDescription->mFormatID != kAudioFormatLinearPCM) {
16700 if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) != 0) {
16705 if ((ma_is_little_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) || (ma_is_big_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) == 0)) {
16714 if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0) {
16715 if (pDescription->mBitsPerChannel == 32) {
16720 if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) != 0) {
16721 if (pDescription->mBitsPerChannel == 16) {
16724 }
else if (pDescription->mBitsPerChannel == 24) {
16725 if (pDescription->mBytesPerFrame == (pDescription->mBitsPerChannel/8 * pDescription->mChannelsPerFrame)) {
16729 if (pDescription->mBytesPerFrame/pDescription->mChannelsPerFrame ==
sizeof(
ma_int32)) {
16736 }
else if (pDescription->mBitsPerChannel == 32) {
16741 if (pDescription->mBitsPerChannel == 8) {
16754 ma_assert(pChannelLayout !=
NULL);
16756 if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
16758 for (iChannel = 0; iChannel < pChannelLayout->mNumberChannelDescriptions; ++iChannel) {
16759 channelMap[iChannel] = ma_channel_from_AudioChannelLabel(pChannelLayout->mChannelDescriptions[iChannel].mChannelLabel);
16763 if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
16765 UInt32 iChannel = 0;
16767 AudioChannelBitmap
bitmap = pChannelLayout->mChannelBitmap;
16768 for (iBit = 0; iBit < 32; ++iBit) {
16769 AudioChannelBitmap bit =
bitmap & (1 << iBit);
16771 channelMap[iChannel++] = ma_channel_from_AudioChannelBit(bit);
16781 UInt32 channelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
16782 switch (pChannelLayout->mChannelLayoutTag)
16784 case kAudioChannelLayoutTag_Mono:
16785 case kAudioChannelLayoutTag_Stereo:
16786 case kAudioChannelLayoutTag_StereoHeadphones:
16787 case kAudioChannelLayoutTag_MatrixStereo:
16788 case kAudioChannelLayoutTag_MidSide:
16789 case kAudioChannelLayoutTag_XY:
16790 case kAudioChannelLayoutTag_Binaural:
16791 case kAudioChannelLayoutTag_Ambisonic_B_Format:
16796 case kAudioChannelLayoutTag_Octagonal:
16801 case kAudioChannelLayoutTag_Hexagonal:
16805 case kAudioChannelLayoutTag_Pentagonal:
16809 case kAudioChannelLayoutTag_Quadraphonic:
16830 #if defined(MA_APPLE_DESKTOP)
16831 ma_result ma_get_device_object_ids__coreaudio(
ma_context* pContext, UInt32* pDeviceCount, AudioObjectID** ppDeviceObjectIDs)
16833 AudioObjectPropertyAddress propAddressDevices;
16834 UInt32 deviceObjectsDataSize;
16836 AudioObjectID* pDeviceObjectIDs;
16838 ma_assert(pContext !=
NULL);
16839 ma_assert(pDeviceCount !=
NULL);
16840 ma_assert(ppDeviceObjectIDs !=
NULL);
16844 *ppDeviceObjectIDs =
NULL;
16846 propAddressDevices.mSelector = kAudioHardwarePropertyDevices;
16847 propAddressDevices.mScope = kAudioObjectPropertyScopeGlobal;
16848 propAddressDevices.mElement = kAudioObjectPropertyElementMaster;
16850 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(kAudioObjectSystemObject, &propAddressDevices, 0,
NULL, &deviceObjectsDataSize);
16851 if (status != noErr) {
16852 return ma_result_from_OSStatus(status);
16855 pDeviceObjectIDs = (AudioObjectID*)
ma_malloc(deviceObjectsDataSize);
16856 if (pDeviceObjectIDs ==
NULL) {
16860 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDevices, 0,
NULL, &deviceObjectsDataSize, pDeviceObjectIDs);
16861 if (status != noErr) {
16863 return ma_result_from_OSStatus(status);
16866 *pDeviceCount = deviceObjectsDataSize /
sizeof(AudioObjectID);
16867 *ppDeviceObjectIDs = pDeviceObjectIDs;
16873 ma_result ma_get_AudioObject_uid_as_CFStringRef(
ma_context* pContext, AudioObjectID objectID, CFStringRef* pUID)
16875 AudioObjectPropertyAddress propAddress;
16879 ma_assert(pContext !=
NULL);
16881 propAddress.mSelector = kAudioDevicePropertyDeviceUID;
16882 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
16883 propAddress.mElement = kAudioObjectPropertyElementMaster;
16885 dataSize =
sizeof(*pUID);
16886 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0,
NULL, &dataSize, pUID);
16887 if (status != noErr) {
16888 return ma_result_from_OSStatus(status);
16894 ma_result ma_get_AudioObject_uid(
ma_context* pContext, AudioObjectID objectID,
size_t bufferSize,
char* bufferOut)
16899 ma_assert(pContext !=
NULL);
16901 result = ma_get_AudioObject_uid_as_CFStringRef(pContext, objectID, &uid);
16906 if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(uid, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
16913 ma_result ma_get_AudioObject_name(
ma_context* pContext, AudioObjectID objectID,
size_t bufferSize,
char* bufferOut)
16915 AudioObjectPropertyAddress propAddress;
16916 CFStringRef deviceName =
NULL;
16920 ma_assert(pContext !=
NULL);
16922 propAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
16923 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
16924 propAddress.mElement = kAudioObjectPropertyElementMaster;
16926 dataSize =
sizeof(deviceName);
16927 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0,
NULL, &dataSize, &deviceName);
16928 if (status != noErr) {
16929 return ma_result_from_OSStatus(status);
16932 if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(deviceName, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
16939 ma_bool32 ma_does_AudioObject_support_scope(
ma_context* pContext, AudioObjectID deviceObjectID, AudioObjectPropertyScope scope)
16941 AudioObjectPropertyAddress propAddress;
16944 AudioBufferList* pBufferList;
16947 ma_assert(pContext !=
NULL);
16950 propAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
16951 propAddress.mScope = scope;
16952 propAddress.mElement = kAudioObjectPropertyElementMaster;
16954 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &dataSize);
16955 if (status != noErr) {
16959 pBufferList = (AudioBufferList*)
ma_malloc(dataSize);
16960 if (pBufferList ==
NULL) {
16964 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &dataSize, pBufferList);
16965 if (status != noErr) {
16971 if (pBufferList->mNumberBuffers > 0) {
16976 return isSupported;
16979 ma_bool32 ma_does_AudioObject_support_playback(
ma_context* pContext, AudioObjectID deviceObjectID)
16981 return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeOutput);
16984 ma_bool32 ma_does_AudioObject_support_capture(
ma_context* pContext, AudioObjectID deviceObjectID)
16986 return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeInput);
16990 ma_result ma_get_AudioObject_stream_descriptions(
ma_context* pContext, AudioObjectID deviceObjectID,
ma_device_type deviceType, UInt32* pDescriptionCount, AudioStreamRangedDescription** ppDescriptions)
16992 AudioObjectPropertyAddress propAddress;
16995 AudioStreamRangedDescription* pDescriptions;
16997 ma_assert(pContext !=
NULL);
16998 ma_assert(pDescriptionCount !=
NULL);
16999 ma_assert(ppDescriptions !=
NULL);
17005 propAddress.mSelector = kAudioStreamPropertyAvailableVirtualFormats;
17006 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
17007 propAddress.mElement = kAudioObjectPropertyElementMaster;
17009 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &dataSize);
17010 if (status != noErr) {
17011 return ma_result_from_OSStatus(status);
17014 pDescriptions = (AudioStreamRangedDescription*)
ma_malloc(dataSize);
17015 if (pDescriptions ==
NULL) {
17019 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &dataSize, pDescriptions);
17020 if (status != noErr) {
17022 return ma_result_from_OSStatus(status);
17025 *pDescriptionCount = dataSize /
sizeof(*pDescriptions);
17026 *ppDescriptions = pDescriptions;
17031 ma_result ma_get_AudioObject_channel_layout(
ma_context* pContext, AudioObjectID deviceObjectID,
ma_device_type deviceType, AudioChannelLayout** ppChannelLayout)
17033 AudioObjectPropertyAddress propAddress;
17036 AudioChannelLayout* pChannelLayout;
17038 ma_assert(pContext !=
NULL);
17039 ma_assert(ppChannelLayout !=
NULL);
17041 *ppChannelLayout =
NULL;
17043 propAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout;
17044 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
17045 propAddress.mElement = kAudioObjectPropertyElementMaster;
17047 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &dataSize);
17048 if (status != noErr) {
17049 return ma_result_from_OSStatus(status);
17052 pChannelLayout = (AudioChannelLayout*)
ma_malloc(dataSize);
17053 if (pChannelLayout ==
NULL) {
17057 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &dataSize, pChannelLayout);
17058 if (status != noErr) {
17060 return ma_result_from_OSStatus(status);
17063 *ppChannelLayout = pChannelLayout;
17069 AudioChannelLayout* pChannelLayout;
17072 ma_assert(pContext !=
NULL);
17073 ma_assert(pChannelCount !=
NULL);
17075 *pChannelCount = 0;
17077 result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
17082 if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
17083 *pChannelCount = pChannelLayout->mNumberChannelDescriptions;
17084 }
else if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
17085 *pChannelCount = ma_count_set_bits(pChannelLayout->mChannelBitmap);
17087 *pChannelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
17096 AudioChannelLayout* pChannelLayout;
17099 ma_assert(pContext !=
NULL);
17101 result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
17106 result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, channelMap);
17116 ma_result ma_get_AudioObject_sample_rates(
ma_context* pContext, AudioObjectID deviceObjectID,
ma_device_type deviceType, UInt32* pSampleRateRangesCount, AudioValueRange** ppSampleRateRanges)
17118 AudioObjectPropertyAddress propAddress;
17121 AudioValueRange* pSampleRateRanges;
17123 ma_assert(pContext !=
NULL);
17124 ma_assert(pSampleRateRangesCount !=
NULL);
17125 ma_assert(ppSampleRateRanges !=
NULL);
17128 *pSampleRateRangesCount = 0;
17129 *ppSampleRateRanges =
NULL;
17131 propAddress.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
17132 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
17133 propAddress.mElement = kAudioObjectPropertyElementMaster;
17135 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &dataSize);
17136 if (status != noErr) {
17137 return ma_result_from_OSStatus(status);
17140 pSampleRateRanges = (AudioValueRange*)
ma_malloc(dataSize);
17141 if (pSampleRateRanges ==
NULL) {
17145 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &dataSize, pSampleRateRanges);
17146 if (status != noErr) {
17148 return ma_result_from_OSStatus(status);
17151 *pSampleRateRangesCount = dataSize /
sizeof(*pSampleRateRanges);
17152 *ppSampleRateRanges = pSampleRateRanges;
17158 UInt32 sampleRateRangeCount;
17159 AudioValueRange* pSampleRateRanges;
17162 ma_assert(pContext !=
NULL);
17163 ma_assert(pSampleRateOut !=
NULL);
17165 *pSampleRateOut = 0;
17167 result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
17172 if (sampleRateRangeCount == 0) {
17177 if (sampleRateIn == 0) {
17179 UInt32 iMALSampleRate;
17180 for (iMALSampleRate = 0; iMALSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iMALSampleRate) {
17181 ma_uint32 malSampleRate = g_maStandardSampleRatePriorities[iMALSampleRate];
17182 UInt32 iCASampleRate;
17183 for (iCASampleRate = 0; iCASampleRate < sampleRateRangeCount; ++iCASampleRate) {
17184 AudioValueRange caSampleRate = pSampleRateRanges[iCASampleRate];
17185 if (caSampleRate.mMinimum <= malSampleRate && caSampleRate.mMaximum >= malSampleRate) {
17186 *pSampleRateOut = malSampleRate;
17197 ma_assert(sampleRateRangeCount > 0);
17199 *pSampleRateOut = pSampleRateRanges[0].mMinimum;
17204 UInt32 currentAbsoluteDifference = INT32_MAX;
17205 UInt32 iCurrentClosestRange = (UInt32)-1;
17207 for (iRange = 0; iRange < sampleRateRangeCount; ++iRange) {
17208 if (pSampleRateRanges[iRange].mMinimum <= sampleRateIn && pSampleRateRanges[iRange].mMaximum >= sampleRateIn) {
17209 *pSampleRateOut = sampleRateIn;
17213 UInt32 absoluteDifference;
17214 if (pSampleRateRanges[iRange].mMinimum > sampleRateIn) {
17215 absoluteDifference = pSampleRateRanges[iRange].mMinimum - sampleRateIn;
17217 absoluteDifference = sampleRateIn - pSampleRateRanges[iRange].mMaximum;
17220 if (currentAbsoluteDifference > absoluteDifference) {
17221 currentAbsoluteDifference = absoluteDifference;
17222 iCurrentClosestRange = iRange;
17227 ma_assert(iCurrentClosestRange != (UInt32)-1);
17229 *pSampleRateOut = pSampleRateRanges[iCurrentClosestRange].mMinimum;
17242 AudioObjectPropertyAddress propAddress;
17243 AudioValueRange bufferSizeRange;
17247 ma_assert(pContext !=
NULL);
17248 ma_assert(pBufferSizeInFramesOut !=
NULL);
17250 *pBufferSizeInFramesOut = 0;
17252 propAddress.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
17253 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
17254 propAddress.mElement = kAudioObjectPropertyElementMaster;
17256 dataSize =
sizeof(bufferSizeRange);
17257 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &dataSize, &bufferSizeRange);
17258 if (status != noErr) {
17259 return ma_result_from_OSStatus(status);
17263 if (bufferSizeInFramesIn < bufferSizeRange.mMinimum) {
17264 *pBufferSizeInFramesOut = (
ma_uint32)bufferSizeRange.mMinimum;
17265 }
else if (bufferSizeInFramesIn > bufferSizeRange.mMaximum) {
17266 *pBufferSizeInFramesOut = (
ma_uint32)bufferSizeRange.mMaximum;
17268 *pBufferSizeInFramesOut = bufferSizeInFramesIn;
17278 AudioObjectPropertyAddress propAddress;
17282 ma_assert(pContext !=
NULL);
17284 result = ma_get_AudioObject_closest_buffer_size_in_frames(pContext, deviceObjectID, deviceType, *pBufferSizeInOut, &chosenBufferSizeInFrames);
17290 propAddress.mSelector = kAudioDevicePropertyBufferFrameSize;
17291 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
17292 propAddress.mElement = kAudioObjectPropertyElementMaster;
17294 ((ma_AudioObjectSetPropertyData_proc)pContext->coreaudio.AudioObjectSetPropertyData)(deviceObjectID, &propAddress, 0,
NULL,
sizeof(chosenBufferSizeInFrames), &chosenBufferSizeInFrames);
17297 dataSize =
sizeof(*pBufferSizeInOut);
17298 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &dataSize, &chosenBufferSizeInFrames);
17299 if (status != noErr) {
17300 return ma_result_from_OSStatus(status);
17303 *pBufferSizeInOut = chosenBufferSizeInFrames;
17310 ma_assert(pContext !=
NULL);
17311 ma_assert(pDeviceObjectID !=
NULL);
17314 *pDeviceObjectID = 0;
17316 if (pDeviceID ==
NULL) {
17318 AudioObjectPropertyAddress propAddressDefaultDevice;
17319 UInt32 defaultDeviceObjectIDSize =
sizeof(AudioObjectID);
17320 AudioObjectID defaultDeviceObjectID;
17323 propAddressDefaultDevice.mScope = kAudioObjectPropertyScopeGlobal;
17324 propAddressDefaultDevice.mElement = kAudioObjectPropertyElementMaster;
17326 propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
17328 propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultInputDevice;
17331 defaultDeviceObjectIDSize =
sizeof(AudioObjectID);
17332 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDefaultDevice, 0,
NULL, &defaultDeviceObjectIDSize, &defaultDeviceObjectID);
17333 if (status == noErr) {
17334 *pDeviceObjectID = defaultDeviceObjectID;
17339 UInt32 deviceCount;
17340 AudioObjectID* pDeviceObjectIDs;
17344 result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
17349 for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
17350 AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
17353 if (ma_get_AudioObject_uid(pContext, deviceObjectID,
sizeof(uid), uid) !=
MA_SUCCESS) {
17358 if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
17359 if (strcmp(uid, pDeviceID->coreaudio) == 0) {
17360 *pDeviceObjectID = deviceObjectID;
17365 if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
17366 if (strcmp(uid, pDeviceID->coreaudio) == 0) {
17367 *pDeviceObjectID = deviceObjectID;
17382 UInt32 deviceFormatDescriptionCount;
17383 AudioStreamRangedDescription* pDeviceFormatDescriptions;
17388 AudioStreamBasicDescription bestDeviceFormatSoFar;
17392 result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &deviceFormatDescriptionCount, &pDeviceFormatDescriptions);
17397 desiredSampleRate = sampleRate;
17398 if (usingDefaultSampleRate) {
17404 for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
17405 ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
17407 UInt32 iDeviceRate;
17409 for (iDeviceRate = 0; iDeviceRate < deviceFormatDescriptionCount; ++iDeviceRate) {
17410 ma_uint32 deviceRate = (
ma_uint32)pDeviceFormatDescriptions[iDeviceRate].mFormat.mSampleRate;
17412 if (deviceRate == standardRate) {
17413 desiredSampleRate = standardRate;
17426 if (usingDefaultChannels) {
17427 ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &desiredChannelCount);
17431 if (usingDefaultFormat) {
17432 desiredFormat = g_maFormatPriorities[0];
17439 ma_zero_object(&bestDeviceFormatSoFar);
17442 for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
17444 ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &
format);
17446 hasSupportedFormat =
MA_TRUE;
17447 bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat;
17452 if (!hasSupportedFormat) {
17457 for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
17458 AudioStreamBasicDescription thisDeviceFormat = pDeviceFormatDescriptions[iFormat].mFormat;
17464 formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &thisSampleFormat);
17469 ma_format_from_AudioStreamBasicDescription(&bestDeviceFormatSoFar, &bestSampleFormatSoFar);
17472 if (thisDeviceFormat.mSampleRate != desiredSampleRate) {
17477 if (bestDeviceFormatSoFar.mSampleRate == desiredSampleRate) {
17481 if (thisDeviceFormat.mChannelsPerFrame != desiredChannelCount) {
17483 if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
17490 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
17491 bestDeviceFormatSoFar = thisDeviceFormat;
17499 if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
17501 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
17502 bestDeviceFormatSoFar = thisDeviceFormat;
17509 bestDeviceFormatSoFar = thisDeviceFormat;
17519 if (bestDeviceFormatSoFar.mSampleRate != desiredSampleRate) {
17520 bestDeviceFormatSoFar = thisDeviceFormat;
17524 if (thisDeviceFormat.mChannelsPerFrame == desiredChannelCount) {
17529 if (bestDeviceFormatSoFar.mChannelsPerFrame != desiredChannelCount) {
17530 bestDeviceFormatSoFar = thisDeviceFormat;
17534 if (thisSampleFormat == desiredFormat) {
17535 bestDeviceFormatSoFar = thisDeviceFormat;
17539 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
17540 bestDeviceFormatSoFar = thisDeviceFormat;
17552 if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
17559 if (thisSampleFormat == bestSampleFormatSoFar) {
17560 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
17561 bestDeviceFormatSoFar = thisDeviceFormat;
17573 *pFormat = bestDeviceFormatSoFar;
17580 AudioUnitScope deviceScope;
17581 AudioUnitElement deviceBus;
17582 UInt32 channelLayoutSize;
17584 AudioChannelLayout* pChannelLayout;
17587 ma_assert(pContext !=
NULL);
17590 deviceScope = kAudioUnitScope_Output;
17591 deviceBus = MA_COREAUDIO_OUTPUT_BUS;
17593 deviceScope = kAudioUnitScope_Input;
17594 deviceBus = MA_COREAUDIO_INPUT_BUS;
17597 status = ((ma_AudioUnitGetPropertyInfo_proc)pContext->coreaudio.AudioUnitGetPropertyInfo)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, &channelLayoutSize,
NULL);
17598 if (status != noErr) {
17599 return ma_result_from_OSStatus(status);
17602 pChannelLayout = (AudioChannelLayout*)
ma_malloc(channelLayoutSize);
17603 if (pChannelLayout ==
NULL) {
17607 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, pChannelLayout, &channelLayoutSize);
17608 if (status != noErr) {
17610 return ma_result_from_OSStatus(status);
17613 result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, channelMap);
17625 ma_assert(pContext !=
NULL);
17626 ma_assert(pID0 !=
NULL);
17627 ma_assert(pID1 !=
NULL);
17630 return strcmp(pID0->coreaudio, pID1->coreaudio) == 0;
17635 #if defined(MA_APPLE_DESKTOP)
17636 UInt32 deviceCount;
17637 AudioObjectID* pDeviceObjectIDs;
17641 result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
17646 for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
17647 AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
17650 ma_zero_object(&info);
17651 if (ma_get_AudioObject_uid(pContext, deviceObjectID,
sizeof(info.
id.coreaudio), info.
id.coreaudio) !=
MA_SUCCESS) {
17654 if (ma_get_AudioObject_name(pContext, deviceObjectID,
sizeof(info.
name), info.
name) !=
MA_SUCCESS) {
17658 if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
17663 if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
17675 ma_zero_object(&info);
17676 ma_strncpy_s(info.
name,
sizeof(info.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
17681 ma_zero_object(&info);
17682 ma_strncpy_s(info.
name,
sizeof(info.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
17695 ma_assert(pContext !=
NULL);
17702 #if defined(MA_APPLE_DESKTOP)
17705 AudioObjectID deviceObjectID;
17706 UInt32 streamDescriptionCount;
17707 AudioStreamRangedDescription* pStreamDescriptions;
17708 UInt32 iStreamDescription;
17709 UInt32 sampleRateRangeCount;
17710 AudioValueRange* pSampleRateRanges;
17712 result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
17717 result = ma_get_AudioObject_uid(pContext, deviceObjectID,
sizeof(pDeviceInfo->
id.coreaudio), pDeviceInfo->
id.coreaudio);
17722 result = ma_get_AudioObject_name(pContext, deviceObjectID,
sizeof(pDeviceInfo->
name), pDeviceInfo->
name);
17728 result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &streamDescriptionCount, &pStreamDescriptions);
17733 for (iStreamDescription = 0; iStreamDescription < streamDescriptionCount; ++iStreamDescription) {
17738 result = ma_format_from_AudioStreamBasicDescription(&pStreamDescriptions[iStreamDescription].mFormat, &
format);
17746 for (iOutputFormat = 0; iOutputFormat < pDeviceInfo->
formatCount; ++iOutputFormat) {
17753 if (!formatExists) {
17758 ma_free(pStreamDescriptions);
17762 result = ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &pDeviceInfo->
minChannels);
17770 result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
17775 if (sampleRateRangeCount > 0) {
17776 UInt32 iSampleRate;
17779 for (iSampleRate = 0; iSampleRate < sampleRateRangeCount; ++iSampleRate) {
17780 if (pDeviceInfo->
minSampleRate > pSampleRateRanges[iSampleRate].mMinimum) {
17781 pDeviceInfo->
minSampleRate = pSampleRateRanges[iSampleRate].mMinimum;
17783 if (pDeviceInfo->
maxSampleRate < pSampleRateRanges[iSampleRate].mMaximum) {
17784 pDeviceInfo->
maxSampleRate = pSampleRateRanges[iSampleRate].mMaximum;
17792 AudioComponentDescription desc;
17793 AudioComponent component;
17794 AudioUnit audioUnit;
17796 AudioUnitScope formatScope;
17797 AudioUnitElement formatElement;
17798 AudioStreamBasicDescription bestFormat;
17802 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
17804 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
17812 desc.componentType = kAudioUnitType_Output;
17813 desc.componentSubType = kAudioUnitSubType_RemoteIO;
17814 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
17815 desc.componentFlags = 0;
17816 desc.componentFlagsMask = 0;
17818 component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(
NULL, &desc);
17819 if (component ==
NULL) {
17823 status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)(component, &audioUnit);
17824 if (status != noErr) {
17825 return ma_result_from_OSStatus(status);
17831 propSize =
sizeof(bestFormat);
17832 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
17833 if (status != noErr) {
17834 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
17835 return ma_result_from_OSStatus(status);
17838 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
17842 pDeviceInfo->
minChannels = bestFormat.mChannelsPerFrame;
17843 pDeviceInfo->
maxChannels = bestFormat.mChannelsPerFrame;
17846 result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pDeviceInfo->
formats[0]);
17856 AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
17857 ma_assert(pAudioSession !=
NULL);
17870 void ma_device_uninit__coreaudio(
ma_device* pDevice)
17872 ma_assert(pDevice !=
NULL);
17873 ma_assert(ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED);
17875 if (pDevice->coreaudio.audioUnitCapture !=
NULL) {
17876 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
17878 if (pDevice->coreaudio.audioUnitPlayback !=
NULL) {
17879 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
17882 if (pDevice->coreaudio.pAudioBufferList) {
17883 ma_free(pDevice->coreaudio.pAudioBufferList);
17892 OSStatus ma_on_output__coreaudio(
void* pUserData, AudioUnitRenderActionFlags* pActionFlags,
const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufferList)
17897 ma_assert(pDevice !=
NULL);
17899 #if defined(MA_DEBUG_OUTPUT)
17900 printf(
"INFO: Output Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pBufferList->mNumberBuffers);
17905 if (pBufferList->mBuffers[0].mNumberChannels != pDevice->playback.internalChannels) {
17912 for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
17913 if (pBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->playback.internalChannels) {
17914 ma_uint32 frameCountForThisBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize /
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
17915 if (frameCountForThisBuffer > 0) {
17917 ma_device__handle_duplex_callback_playback(pDevice, frameCountForThisBuffer, pBufferList->mBuffers[iBuffer].mData, &pDevice->coreaudio.duplexRB);
17919 ma_device__read_frames_from_client(pDevice, frameCountForThisBuffer, pBufferList->mBuffers[iBuffer].mData);
17923 #if defined(MA_DEBUG_OUTPUT)
17924 printf(
" frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pBufferList->mBuffers[iBuffer].mNumberChannels, pBufferList->mBuffers[iBuffer].mDataByteSize);
17932 ma_zero_memory(pBufferList->mBuffers[iBuffer].mData, pBufferList->mBuffers[iBuffer].mDataByteSize);
17934 #if defined(MA_DEBUG_OUTPUT)
17935 printf(
" WARNING: Outputting silence. frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pBufferList->mBuffers[iBuffer].mNumberChannels, pBufferList->mBuffers[iBuffer].mDataByteSize);
17943 for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; iBuffer += pDevice->playback.internalChannels) {
17945 ma_uint32 framesRemaining = frameCountPerBuffer;
17947 while (framesRemaining > 0) {
17951 if (framesToRead > framesRemaining) {
17952 framesToRead = framesRemaining;
17956 ma_device__handle_duplex_callback_playback(pDevice, framesToRead, tempBuffer, &pDevice->coreaudio.duplexRB);
17958 ma_device__read_frames_from_client(pDevice, framesToRead, tempBuffer);
17961 for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
17962 ppDeinterleavedBuffers[iChannel] = (
void*)ma_offset_ptr(pBufferList->mBuffers[iBuffer].mData, (frameCountPerBuffer - framesRemaining) *
ma_get_bytes_per_sample(pDevice->playback.internalFormat));
17965 ma_deinterleave_pcm_frames(pDevice->playback.internalFormat, pDevice->playback.internalChannels, framesToRead, tempBuffer, ppDeinterleavedBuffers);
17967 framesRemaining -= framesToRead;
17972 (
void)pActionFlags;
17979 OSStatus ma_on_input__coreaudio(
void* pUserData, AudioUnitRenderActionFlags* pActionFlags,
const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pUnusedBufferList)
17982 AudioBufferList* pRenderedBufferList;
17986 ma_assert(pDevice !=
NULL);
17988 pRenderedBufferList = (AudioBufferList*)pDevice->coreaudio.pAudioBufferList;
17989 ma_assert(pRenderedBufferList);
17993 if (pRenderedBufferList->mBuffers[0].mNumberChannels != pDevice->capture.internalChannels) {
17997 #if defined(MA_DEBUG_OUTPUT)
17998 printf(
"INFO: Input Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pRenderedBufferList->mNumberBuffers);
18001 status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList);
18002 if (status != noErr) {
18003 #if defined(MA_DEBUG_OUTPUT)
18004 printf(
" ERROR: AudioUnitRender() failed with %d\n", status);
18011 for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
18012 if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->capture.internalChannels) {
18014 ma_device__handle_duplex_callback_capture(pDevice, frameCount, pRenderedBufferList->mBuffers[iBuffer].mData, &pDevice->coreaudio.duplexRB);
18016 ma_device__send_frames_to_client(pDevice, frameCount, pRenderedBufferList->mBuffers[iBuffer].mData);
18018 #if defined(MA_DEBUG_OUTPUT)
18019 printf(
" mDataByteSize=%d\n", pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
18029 ma_zero_memory(silentBuffer,
sizeof(silentBuffer));
18031 framesRemaining = frameCount;
18032 while (framesRemaining > 0) {
18034 if (framesToSend > framesRemaining) {
18035 framesToSend = framesRemaining;
18039 ma_device__handle_duplex_callback_capture(pDevice, framesToSend, silentBuffer, &pDevice->coreaudio.duplexRB);
18041 ma_device__send_frames_to_client(pDevice, framesToSend, silentBuffer);
18044 framesRemaining -= framesToSend;
18047 #if defined(MA_DEBUG_OUTPUT)
18048 printf(
" WARNING: Outputting silence. frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pRenderedBufferList->mBuffers[iBuffer].mNumberChannels, pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
18056 for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; iBuffer += pDevice->capture.internalChannels) {
18057 ma_uint32 framesRemaining = frameCount;
18058 while (framesRemaining > 0) {
18062 if (framesToSend > framesRemaining) {
18063 framesToSend = framesRemaining;
18066 for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
18067 ppDeinterleavedBuffers[iChannel] = (
void*)ma_offset_ptr(pRenderedBufferList->mBuffers[iBuffer].mData, (frameCount - framesRemaining) *
ma_get_bytes_per_sample(pDevice->capture.internalFormat));
18070 ma_interleave_pcm_frames(pDevice->capture.internalFormat, pDevice->capture.internalChannels, framesToSend, (
const void**)ppDeinterleavedBuffers, tempBuffer);
18073 ma_device__handle_duplex_callback_capture(pDevice, framesToSend, tempBuffer, &pDevice->coreaudio.duplexRB);
18075 ma_device__send_frames_to_client(pDevice, framesToSend, tempBuffer);
18078 framesRemaining -= framesToSend;
18083 (
void)pActionFlags;
18087 (
void)pUnusedBufferList;
18092 void on_start_stop__coreaudio(
void* pUserData, AudioUnit audioUnit, AudioUnitPropertyID propertyID, AudioUnitScope scope, AudioUnitElement element)
18095 ma_assert(pDevice !=
NULL);
18103 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED || ma_device__get_state(pDevice) == MA_STATE_STOPPING || ma_device__get_state(pDevice) == MA_STATE_STOPPED) {
18109 ma_event_signal(&pDevice->coreaudio.stopEvent);
18112 UInt32 isRunningSize =
sizeof(isRunning);
18113 OSStatus status = ((ma_AudioUnitGetProperty_proc)pDevice->pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioOutputUnitProperty_IsRunning, scope, element, &isRunning, &isRunningSize);
18114 if (status != noErr) {
18129 if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isDefaultPlaybackDevice) ||
18130 ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isDefaultCaptureDevice)) {
18137 if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isSwitchingPlaybackDevice) ||
18138 ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isSwitchingCaptureDevice)) {
18153 onStop = pDevice->onStop;
18163 #if defined(MA_APPLE_DESKTOP)
18164 OSStatus ma_default_device_changed__coreaudio(AudioObjectID objectID, UInt32 addressCount,
const AudioObjectPropertyAddress* pAddresses,
void* pUserData)
18167 ma_assert(pDevice !=
NULL);
18170 if (addressCount == 0) {
18174 if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultOutputDevice) {
18177 pDevice->coreaudio.isSwitchingPlaybackDevice =
MA_TRUE;
18179 pDevice->coreaudio.isSwitchingPlaybackDevice =
MA_FALSE;
18185 if (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
18186 OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
18187 if (status != noErr) {
18189 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18191 ma_device__set_state(pDevice, MA_STATE_STOPPED);
18197 if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultInputDevice) {
18200 pDevice->coreaudio.isSwitchingPlaybackDevice =
MA_TRUE;
18202 pDevice->coreaudio.isSwitchingPlaybackDevice =
MA_FALSE;
18208 if (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
18209 OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18210 if (status != noErr) {
18212 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
18214 ma_device__set_state(pDevice, MA_STATE_STOPPED);
18243 #if defined(MA_APPLE_DESKTOP)
18244 AudioObjectID deviceObjectID;
18246 AudioComponent component;
18247 AudioUnit audioUnit;
18248 AudioBufferList* pAudioBufferList;
18255 char deviceName[256];
18256 } ma_device_init_internal_data__coreaudio;
18262 UInt32 enableIOFlag;
18263 AudioStreamBasicDescription bestFormat;
18265 AURenderCallbackStruct callbackInfo;
18266 #if defined(MA_APPLE_DESKTOP)
18267 AudioObjectID deviceObjectID;
18275 ma_assert(pContext !=
NULL);
18278 #if defined(MA_APPLE_DESKTOP)
18279 pData->deviceObjectID = 0;
18281 pData->component =
NULL;
18282 pData->audioUnit =
NULL;
18283 pData->pAudioBufferList =
NULL;
18285 #if defined(MA_APPLE_DESKTOP)
18286 result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
18291 pData->deviceObjectID = deviceObjectID;
18295 pData->periodsOut = pData->periodsIn;
18296 if (pData->periodsOut < 1) {
18297 pData->periodsOut = 1;
18299 if (pData->periodsOut > 16) {
18300 pData->periodsOut = 16;
18305 status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)((AudioComponent)pContext->coreaudio.component, (AudioUnit*)&pData->audioUnit);
18306 if (status != noErr) {
18307 return ma_result_from_OSStatus(status);
18317 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &enableIOFlag,
sizeof(enableIOFlag));
18318 if (status != noErr) {
18319 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18320 return ma_result_from_OSStatus(status);
18323 enableIOFlag = (enableIOFlag == 0) ? 1 : 0;
18324 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &enableIOFlag,
sizeof(enableIOFlag));
18325 if (status != noErr) {
18326 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18327 return ma_result_from_OSStatus(status);
18332 #if defined(MA_APPLE_DESKTOP)
18333 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, (deviceType ==
ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS, &deviceObjectID,
sizeof(AudioDeviceID));
18334 if (status != noErr) {
18335 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18336 return ma_result_from_OSStatus(result);
18353 AudioUnitScope formatScope = (deviceType ==
ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
18354 AudioUnitElement formatElement = (deviceType ==
ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
18356 #if defined(MA_APPLE_DESKTOP)
18357 AudioStreamBasicDescription origFormat;
18358 UInt32 origFormatSize;
18360 result = ma_find_best_format__coreaudio(pContext, deviceObjectID, deviceType, pData->formatIn, pData->channelsIn, pData->sampleRateIn, pData->usingDefaultFormat, pData->usingDefaultChannels, pData->usingDefaultSampleRate, &bestFormat);
18362 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18367 origFormatSize =
sizeof(origFormat);
18369 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &origFormat, &origFormatSize);
18371 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &origFormat, &origFormatSize);
18374 if (status != noErr) {
18375 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18379 bestFormat.mSampleRate = origFormat.mSampleRate;
18381 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat,
sizeof(bestFormat));
18382 if (status != noErr) {
18384 bestFormat = origFormat;
18387 UInt32 propSize =
sizeof(bestFormat);
18388 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
18389 if (status != noErr) {
18390 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18391 return ma_result_from_OSStatus(status);
18401 AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
18402 ma_assert(pAudioSession !=
NULL);
18404 [pAudioSession setPreferredSampleRate:(double)pData->sampleRateIn
error:nil];
18405 bestFormat.mSampleRate = pAudioSession.sampleRate;
18408 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat,
sizeof(bestFormat));
18409 if (status != noErr) {
18410 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18411 return ma_result_from_OSStatus(status);
18415 result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pData->formatOut);
18417 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18422 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18426 pData->channelsOut = bestFormat.mChannelsPerFrame;
18427 pData->sampleRateOut = bestFormat.mSampleRate;
18437 #if defined(MA_APPLE_DESKTOP)
18438 result = ma_get_AudioUnit_channel_map(pContext, pData->audioUnit, deviceType, pData->channelMapOut);
18442 result = ma_get_AudioObject_channel_map(pContext, deviceObjectID, deviceType, pData->channelMapOut);
18458 actualBufferSizeInFrames = pData->bufferSizeInFramesIn;
18460 #if defined(MA_APPLE_DESKTOP)
18461 if (actualBufferSizeInFrames == 0) {
18465 actualBufferSizeInFrames = actualBufferSizeInFrames / pData->periodsOut;
18466 result = ma_set_AudioObject_buffer_size_in_frames(pContext, deviceObjectID, deviceType, &actualBufferSizeInFrames);
18471 pData->bufferSizeInFramesOut = actualBufferSizeInFrames * pData->periodsOut;
18473 actualBufferSizeInFrames = 4096;
18474 pData->bufferSizeInFramesOut = actualBufferSizeInFrames;
18496 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &actualBufferSizeInFrames,
sizeof(actualBufferSizeInFrames));
18497 if (status != noErr) {
18498 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18499 return ma_result_from_OSStatus(status);
18505 ma_bool32 isInterleaved = (bestFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
18506 size_t allocationSize;
18507 AudioBufferList* pBufferList;
18509 allocationSize =
sizeof(AudioBufferList) -
sizeof(AudioBuffer);
18510 if (isInterleaved) {
18512 allocationSize +=
sizeof(AudioBuffer) * 1;
18513 allocationSize += actualBufferSizeInFrames *
ma_get_bytes_per_frame(pData->formatOut, pData->channelsOut);
18516 allocationSize +=
sizeof(AudioBuffer) * pData->channelsOut;
18520 pBufferList = (AudioBufferList*)
ma_malloc(allocationSize);
18521 if (pBufferList ==
NULL) {
18522 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18526 if (isInterleaved) {
18527 pBufferList->mNumberBuffers = 1;
18528 pBufferList->mBuffers[0].mNumberChannels = pData->channelsOut;
18529 pBufferList->mBuffers[0].mDataByteSize = actualBufferSizeInFrames *
ma_get_bytes_per_frame(pData->formatOut, pData->channelsOut);
18530 pBufferList->mBuffers[0].mData = (
ma_uint8*)pBufferList +
sizeof(AudioBufferList);
18533 pBufferList->mNumberBuffers = pData->channelsOut;
18534 for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
18535 pBufferList->mBuffers[iBuffer].mNumberChannels = 1;
18536 pBufferList->mBuffers[iBuffer].mDataByteSize = actualBufferSizeInFrames *
ma_get_bytes_per_sample(pData->formatOut);
18537 pBufferList->mBuffers[iBuffer].mData = (
ma_uint8*)pBufferList + ((
sizeof(AudioBufferList) -
sizeof(AudioBuffer)) + (
sizeof(AudioBuffer) * pData->channelsOut)) + (actualBufferSizeInFrames *
ma_get_bytes_per_sample(pData->formatOut) * iBuffer);
18541 pData->pAudioBufferList = pBufferList;
18545 callbackInfo.inputProcRefCon = pDevice_DoNotReference;
18547 callbackInfo.inputProc = ma_on_output__coreaudio;
18548 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, MA_COREAUDIO_OUTPUT_BUS, &callbackInfo,
sizeof(callbackInfo));
18549 if (status != noErr) {
18550 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18551 return ma_result_from_OSStatus(status);
18554 callbackInfo.inputProc = ma_on_input__coreaudio;
18555 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, MA_COREAUDIO_INPUT_BUS, &callbackInfo,
sizeof(callbackInfo));
18556 if (status != noErr) {
18557 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18558 return ma_result_from_OSStatus(status);
18563 if (pData->registerStopEvent) {
18564 status = ((ma_AudioUnitAddPropertyListener_proc)pContext->coreaudio.AudioUnitAddPropertyListener)(pData->audioUnit, kAudioOutputUnitProperty_IsRunning, on_start_stop__coreaudio, pDevice_DoNotReference);
18565 if (status != noErr) {
18566 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18567 return ma_result_from_OSStatus(status);
18572 status = ((ma_AudioUnitInitialize_proc)pContext->coreaudio.AudioUnitInitialize)(pData->audioUnit);
18573 if (status != noErr) {
18574 ma_free(pData->pAudioBufferList);
18575 pData->pAudioBufferList =
NULL;
18576 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
18577 return ma_result_from_OSStatus(status);
18581 #if defined(MA_APPLE_DESKTOP)
18582 ma_get_AudioObject_name(pContext, deviceObjectID,
sizeof(pData->deviceName), pData->deviceName);
18585 ma_strcpy_s(pData->deviceName,
sizeof(pData->deviceName), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
18587 ma_strcpy_s(pData->deviceName,
sizeof(pData->deviceName), MA_DEFAULT_CAPTURE_DEVICE_NAME);
18596 ma_device_init_internal_data__coreaudio data;
18605 data.formatIn = pDevice->capture.format;
18606 data.channelsIn = pDevice->capture.channels;
18607 data.sampleRateIn = pDevice->sampleRate;
18608 ma_copy_memory(data.channelMapIn, pDevice->capture.channelMap,
sizeof(pDevice->capture.channelMap));
18609 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
18610 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
18611 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
18612 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
18613 data.shareMode = pDevice->capture.shareMode;
18614 data.registerStopEvent =
MA_TRUE;
18616 if (disposePreviousAudioUnit) {
18617 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18618 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18620 if (pDevice->coreaudio.pAudioBufferList) {
18621 ma_free(pDevice->coreaudio.pAudioBufferList);
18624 #if defined(MA_APPLE_DESKTOP)
18625 pDevice->coreaudio.deviceObjectIDCapture = (
ma_uint32)data.deviceObjectID;
18627 pDevice->coreaudio.audioUnitCapture = (
ma_ptr)data.audioUnit;
18628 pDevice->coreaudio.pAudioBufferList = (
ma_ptr)data.pAudioBufferList;
18631 data.formatIn = pDevice->playback.format;
18632 data.channelsIn = pDevice->playback.channels;
18633 data.sampleRateIn = pDevice->sampleRate;
18634 ma_copy_memory(data.channelMapIn, pDevice->playback.channelMap,
sizeof(pDevice->playback.channelMap));
18635 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
18636 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
18637 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
18638 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
18639 data.shareMode = pDevice->playback.shareMode;
18642 if (disposePreviousAudioUnit) {
18643 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
18644 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
18647 #if defined(MA_APPLE_DESKTOP)
18648 pDevice->coreaudio.deviceObjectIDPlayback = (
ma_uint32)data.deviceObjectID;
18650 pDevice->coreaudio.audioUnitPlayback = (
ma_ptr)data.audioUnit;
18652 data.bufferSizeInFramesIn = pDevice->coreaudio.originalBufferSizeInFrames;
18653 data.bufferSizeInMillisecondsIn = pDevice->coreaudio.originalBufferSizeInMilliseconds;
18654 data.periodsIn = pDevice->coreaudio.originalPeriods;
18656 result = ma_device_init_internal__coreaudio(pDevice->pContext, deviceType,
NULL, &data, (
void*)pDevice);
18669 ma_assert(pContext !=
NULL);
18670 ma_assert(pConfig !=
NULL);
18671 ma_assert(pDevice !=
NULL);
18681 ma_device_init_internal_data__coreaudio data;
18686 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
18687 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
18688 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
18689 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
18693 data.registerStopEvent =
MA_TRUE;
18701 #if defined(MA_APPLE_DESKTOP)
18702 pDevice->coreaudio.deviceObjectIDCapture = (
ma_uint32)data.deviceObjectID;
18704 pDevice->coreaudio.audioUnitCapture = (
ma_ptr)data.audioUnit;
18705 pDevice->coreaudio.pAudioBufferList = (
ma_ptr)data.pAudioBufferList;
18707 pDevice->capture.internalFormat = data.formatOut;
18708 pDevice->capture.internalChannels = data.channelsOut;
18709 pDevice->capture.internalSampleRate = data.sampleRateOut;
18710 ma_copy_memory(pDevice->capture.internalChannelMap, data.channelMapOut,
sizeof(data.channelMapOut));
18711 pDevice->capture.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
18712 pDevice->capture.internalPeriods = data.periodsOut;
18715 #if defined(MA_APPLE_DESKTOP)
18721 AudioObjectPropertyAddress propAddress;
18722 propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
18723 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
18724 propAddress.mElement = kAudioObjectPropertyElementMaster;
18725 ((ma_AudioObjectAddPropertyListener_proc)pDevice->pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, pDevice);
18732 ma_device_init_internal_data__coreaudio data;
18737 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
18738 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
18739 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
18740 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
18745 data.bufferSizeInFramesIn = pDevice->capture.internalBufferSizeInFrames;
18746 data.periodsIn = pDevice->capture.internalPeriods;
18747 data.registerStopEvent =
MA_FALSE;
18751 data.periodsIn = pConfig->
periods;
18752 data.registerStopEvent =
MA_TRUE;
18758 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18759 if (pDevice->coreaudio.pAudioBufferList) {
18760 ma_free(pDevice->coreaudio.pAudioBufferList);
18767 #if defined(MA_APPLE_DESKTOP)
18768 pDevice->coreaudio.deviceObjectIDPlayback = (
ma_uint32)data.deviceObjectID;
18770 pDevice->coreaudio.audioUnitPlayback = (
ma_ptr)data.audioUnit;
18772 pDevice->playback.internalFormat = data.formatOut;
18773 pDevice->playback.internalChannels = data.channelsOut;
18774 pDevice->playback.internalSampleRate = data.sampleRateOut;
18775 ma_copy_memory(pDevice->playback.internalChannelMap, data.channelMapOut,
sizeof(data.channelMapOut));
18776 pDevice->playback.internalBufferSizeInFrames = data.bufferSizeInFramesOut;
18777 pDevice->playback.internalPeriods = data.periodsOut;
18780 #if defined(MA_APPLE_DESKTOP)
18786 AudioObjectPropertyAddress propAddress;
18787 propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
18788 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
18789 propAddress.mElement = kAudioObjectPropertyElementMaster;
18790 ((ma_AudioObjectAddPropertyListener_proc)pDevice->pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio, pDevice);
18797 pDevice->coreaudio.originalPeriods = pConfig->
periods;
18803 ma_event_init(pContext, &pDevice->coreaudio.stopEvent);
18807 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
18808 ma_result result =
ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames,
NULL, &pDevice->coreaudio.duplexRB);
18810 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[Core Audio] Failed to initialize ring buffer.", result);
18820 ma_assert(pDevice !=
NULL);
18823 OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18824 if (status != noErr) {
18825 return ma_result_from_OSStatus(status);
18830 OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
18831 if (status != noErr) {
18833 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18835 return ma_result_from_OSStatus(status);
18844 ma_assert(pDevice !=
NULL);
18847 OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
18848 if (status != noErr) {
18849 return ma_result_from_OSStatus(status);
18854 OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
18855 if (status != noErr) {
18856 return ma_result_from_OSStatus(status);
18861 ma_event_wait(&pDevice->coreaudio.stopEvent);
18868 ma_assert(pContext !=
NULL);
18871 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
18872 ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
18873 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
18874 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
18883 ma_assert(pContext !=
NULL);
18887 #if defined(MA_APPLE_MOBILE)
18889 AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
18890 ma_assert(pAudioSession !=
NULL);
18892 [pAudioSession setCategory: AVAudioSessionCategoryPlayAndRecord
error:nil];
18897 [pAudioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
error:nil];
18902 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
18903 pContext->coreaudio.hCoreFoundation = ma_dlopen(pContext,
"CoreFoundation.framework/CoreFoundation");
18904 if (pContext->coreaudio.hCoreFoundation ==
NULL) {
18908 pContext->coreaudio.CFStringGetCString = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation,
"CFStringGetCString");
18911 pContext->coreaudio.hCoreAudio = ma_dlopen(pContext,
"CoreAudio.framework/CoreAudio");
18912 if (pContext->coreaudio.hCoreAudio ==
NULL) {
18913 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
18917 pContext->coreaudio.AudioObjectGetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectGetPropertyData");
18918 pContext->coreaudio.AudioObjectGetPropertyDataSize = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectGetPropertyDataSize");
18919 pContext->coreaudio.AudioObjectSetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectSetPropertyData");
18920 pContext->coreaudio.AudioObjectAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectAddPropertyListener");
18928 pContext->coreaudio.hAudioUnit = ma_dlopen(pContext,
"AudioUnit.framework/AudioUnit");
18929 if (pContext->coreaudio.hAudioUnit ==
NULL) {
18930 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
18931 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
18935 if (ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentFindNext") ==
NULL) {
18937 ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
18938 pContext->coreaudio.hAudioUnit = ma_dlopen(pContext,
"AudioToolbox.framework/AudioToolbox");
18939 if (pContext->coreaudio.hAudioUnit ==
NULL) {
18940 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
18941 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
18946 pContext->coreaudio.AudioComponentFindNext = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentFindNext");
18947 pContext->coreaudio.AudioComponentInstanceDispose = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentInstanceDispose");
18948 pContext->coreaudio.AudioComponentInstanceNew = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentInstanceNew");
18949 pContext->coreaudio.AudioOutputUnitStart = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioOutputUnitStart");
18950 pContext->coreaudio.AudioOutputUnitStop = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioOutputUnitStop");
18951 pContext->coreaudio.AudioUnitAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitAddPropertyListener");
18952 pContext->coreaudio.AudioUnitGetPropertyInfo = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitGetPropertyInfo");
18953 pContext->coreaudio.AudioUnitGetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitGetProperty");
18954 pContext->coreaudio.AudioUnitSetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitSetProperty");
18955 pContext->coreaudio.AudioUnitInitialize = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitInitialize");
18956 pContext->coreaudio.AudioUnitRender = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitRender");
18958 pContext->coreaudio.CFStringGetCString = (
ma_proc)CFStringGetCString;
18960 #if defined(MA_APPLE_DESKTOP)
18961 pContext->coreaudio.AudioObjectGetPropertyData = (
ma_proc)AudioObjectGetPropertyData;
18962 pContext->coreaudio.AudioObjectGetPropertyDataSize = (
ma_proc)AudioObjectGetPropertyDataSize;
18963 pContext->coreaudio.AudioObjectSetPropertyData = (
ma_proc)AudioObjectSetPropertyData;
18964 pContext->coreaudio.AudioObjectAddPropertyListener = (
ma_proc)AudioObjectAddPropertyListener;
18967 pContext->coreaudio.AudioComponentFindNext = (
ma_proc)AudioComponentFindNext;
18968 pContext->coreaudio.AudioComponentInstanceDispose = (
ma_proc)AudioComponentInstanceDispose;
18969 pContext->coreaudio.AudioComponentInstanceNew = (
ma_proc)AudioComponentInstanceNew;
18970 pContext->coreaudio.AudioOutputUnitStart = (
ma_proc)AudioOutputUnitStart;
18971 pContext->coreaudio.AudioOutputUnitStop = (
ma_proc)AudioOutputUnitStop;
18972 pContext->coreaudio.AudioUnitAddPropertyListener = (
ma_proc)AudioUnitAddPropertyListener;
18973 pContext->coreaudio.AudioUnitGetPropertyInfo = (
ma_proc)AudioUnitGetPropertyInfo;
18974 pContext->coreaudio.AudioUnitGetProperty = (
ma_proc)AudioUnitGetProperty;
18975 pContext->coreaudio.AudioUnitSetProperty = (
ma_proc)AudioUnitSetProperty;
18976 pContext->coreaudio.AudioUnitInitialize = (
ma_proc)AudioUnitInitialize;
18977 pContext->coreaudio.AudioUnitRender = (
ma_proc)AudioUnitRender;
18982 pContext->
onUninit = ma_context_uninit__coreaudio;
18983 pContext->
onDeviceIDEqual = ma_context_is_device_id_equal__coreaudio;
18984 pContext->
onEnumDevices = ma_context_enumerate_devices__coreaudio;
18993 AudioComponentDescription desc;
18994 desc.componentType = kAudioUnitType_Output;
18995 #if defined(MA_APPLE_DESKTOP)
18996 desc.componentSubType = kAudioUnitSubType_HALOutput;
18998 desc.componentSubType = kAudioUnitSubType_RemoteIO;
19000 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
19001 desc.componentFlags = 0;
19002 desc.componentFlagsMask = 0;
19004 pContext->coreaudio.component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(
NULL, &desc);
19005 if (pContext->coreaudio.component ==
NULL) {
19006 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
19007 ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
19008 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
19009 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
19026 #ifdef MA_HAS_SNDIO
19028 #include <sys/stat.h>
19037 #if defined(__NetBSD__) || defined(__OpenBSD__)
19038 #include <sys/audioio.h>
19040 #if defined(__FreeBSD__) || defined(__DragonFly__)
19041 #include <sys/soundcard.h>
19045 #define MA_SIO_DEVANY "default"
19046 #define MA_SIO_PLAY 1
19047 #define MA_SIO_REC 2
19048 #define MA_SIO_NENC 8
19049 #define MA_SIO_NCHAN 8
19050 #define MA_SIO_NRATE 16
19051 #define MA_SIO_NCONF 4
19062 unsigned int rchan;
19063 unsigned int pchan;
19065 unsigned int bufsz;
19067 unsigned int round;
19068 unsigned int appbufsz;
19070 unsigned int __magic;
19085 unsigned int rchan;
19086 unsigned int pchan;
19092 struct ma_sio_enc enc[MA_SIO_NENC];
19093 unsigned int rchan[MA_SIO_NCHAN];
19094 unsigned int pchan[MA_SIO_NCHAN];
19095 unsigned int rate[MA_SIO_NRATE];
19097 unsigned int nconf;
19098 struct ma_sio_conf confs[MA_SIO_NCONF];
19101 typedef struct ma_sio_hdl* (* ma_sio_open_proc) (
const char*,
unsigned int,
int);
19102 typedef void (* ma_sio_close_proc) (
struct ma_sio_hdl*);
19103 typedef int (* ma_sio_setpar_proc) (
struct ma_sio_hdl*,
struct ma_sio_par*);
19104 typedef int (* ma_sio_getpar_proc) (
struct ma_sio_hdl*,
struct ma_sio_par*);
19105 typedef int (* ma_sio_getcap_proc) (
struct ma_sio_hdl*,
struct ma_sio_cap*);
19106 typedef size_t (* ma_sio_write_proc) (
struct ma_sio_hdl*,
const void*, size_t);
19107 typedef size_t (* ma_sio_read_proc) (
struct ma_sio_hdl*,
void*, size_t);
19108 typedef int (* ma_sio_start_proc) (
struct ma_sio_hdl*);
19109 typedef int (* ma_sio_stop_proc) (
struct ma_sio_hdl*);
19110 typedef int (* ma_sio_initpar_proc)(
struct ma_sio_par*);
19112 ma_format ma_format_from_sio_enc__sndio(
unsigned int bits,
unsigned int bps,
unsigned int sig,
unsigned int le,
unsigned int msb)
19115 if ((ma_is_little_endian() && le == 0) || (ma_is_big_endian() && le == 1)) {
19119 if (bits == 8 && bps == 1 && sig == 0) {
19122 if (bits == 16 && bps == 2 && sig == 1) {
19125 if (bits == 24 && bps == 3 && sig == 1) {
19128 if (bits == 24 && bps == 4 && sig == 1 && msb == 0) {
19131 if (bits == 32 && bps == 4 && sig == 1) {
19138 ma_format ma_find_best_format_from_sio_cap__sndio(
struct ma_sio_cap* caps)
19141 unsigned int iConfig;
19143 ma_assert(caps !=
NULL);
19146 for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
19147 unsigned int iEncoding;
19148 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
19156 if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
19160 bits = caps->enc[iEncoding].bits;
19161 bps = caps->enc[iEncoding].bps;
19162 sig = caps->enc[iEncoding].sig;
19163 le = caps->enc[iEncoding].le;
19164 msb = caps->enc[iEncoding].msb;
19165 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
19173 if (ma_get_format_priority_index(bestFormat) > ma_get_format_priority_index(
format)) {
19186 unsigned int iConfig;
19188 ma_assert(caps !=
NULL);
19193 for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
19195 unsigned int iEncoding;
19196 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
19197 unsigned int iChannel;
19205 if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
19209 bits = caps->enc[iEncoding].bits;
19210 bps = caps->enc[iEncoding].bps;
19211 sig = caps->enc[iEncoding].sig;
19212 le = caps->enc[iEncoding].le;
19213 msb = caps->enc[iEncoding].msb;
19214 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
19215 if (
format != requiredFormat) {
19220 for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
19221 unsigned int chan = 0;
19225 chan = caps->confs[iConfig].pchan;
19227 chan = caps->confs[iConfig].rchan;
19230 if ((chan & (1UL << iChannel)) == 0) {
19247 return maxChannels;
19254 unsigned int iConfig;
19256 ma_assert(caps !=
NULL);
19258 ma_assert(requiredChannels > 0);
19261 firstSampleRate = 0;
19262 bestSampleRate = 0;
19264 for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
19266 unsigned int iEncoding;
19267 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
19268 unsigned int iChannel;
19276 if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
19280 bits = caps->enc[iEncoding].bits;
19281 bps = caps->enc[iEncoding].bps;
19282 sig = caps->enc[iEncoding].sig;
19283 le = caps->enc[iEncoding].le;
19284 msb = caps->enc[iEncoding].msb;
19285 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
19286 if (
format != requiredFormat) {
19291 for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
19292 unsigned int chan = 0;
19294 unsigned int iRate;
19297 chan = caps->confs[iConfig].pchan;
19299 chan = caps->confs[iConfig].rchan;
19302 if ((chan & (1UL << iChannel)) == 0) {
19312 if (
channels != requiredChannels) {
19317 for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
19321 if (firstSampleRate == 0) {
19322 firstSampleRate =
rate;
19326 ratePriority = ma_get_standard_sample_rate_priority_index(
rate);
19331 if (ma_get_standard_sample_rate_priority_index(bestSampleRate) > ratePriority) {
19332 bestSampleRate =
rate;
19340 if (bestSampleRate == 0) {
19341 bestSampleRate = firstSampleRate;
19344 return bestSampleRate;
19350 ma_assert(pContext !=
NULL);
19351 ma_assert(pID0 !=
NULL);
19352 ma_assert(pID1 !=
NULL);
19355 return ma_strcmp(pID0->sndio, pID1->sndio) == 0;
19361 struct ma_sio_hdl* handle;
19363 ma_assert(pContext !=
NULL);
19364 ma_assert(callback !=
NULL);
19369 if (!isTerminating) {
19370 handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_PLAY, 0);
19371 if (handle !=
NULL) {
19374 ma_zero_object(&deviceInfo);
19375 ma_strcpy_s(deviceInfo.
id.sndio,
sizeof(deviceInfo.
id.sndio), MA_SIO_DEVANY);
19376 ma_strcpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
19380 ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
19385 if (!isTerminating) {
19386 handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_REC, 0);
19387 if (handle !=
NULL) {
19390 ma_zero_object(&deviceInfo);
19391 ma_strcpy_s(deviceInfo.
id.sndio,
sizeof(deviceInfo.
id.sndio),
"default");
19392 ma_strcpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME);
19396 ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
19406 struct ma_sio_hdl* handle;
19407 struct ma_sio_cap caps;
19408 unsigned int iConfig;
19410 ma_assert(pContext !=
NULL);
19414 if (pDeviceID ==
NULL) {
19415 ma_strcpy_s(devid,
sizeof(devid), MA_SIO_DEVANY);
19416 ma_strcpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), (deviceType ==
ma_device_type_playback) ? MA_DEFAULT_PLAYBACK_DEVICE_NAME : MA_DEFAULT_CAPTURE_DEVICE_NAME);
19418 ma_strcpy_s(devid,
sizeof(devid), pDeviceID->sndio);
19419 ma_strcpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), devid);
19422 handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(devid, (deviceType ==
ma_device_type_playback) ? MA_SIO_PLAY : MA_SIO_REC, 0);
19423 if (handle ==
NULL) {
19427 if (((ma_sio_getcap_proc)pContext->sndio.sio_getcap)(handle, &caps) == 0) {
19431 for (iConfig = 0; iConfig < caps.nconf; iConfig += 1) {
19436 unsigned int iEncoding;
19437 unsigned int iChannel;
19438 unsigned int iRate;
19440 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
19450 if ((caps.confs[iConfig].enc & (1UL << iEncoding)) == 0) {
19454 bits = caps.enc[iEncoding].bits;
19455 bps = caps.enc[iEncoding].bps;
19456 sig = caps.enc[iEncoding].sig;
19457 le = caps.enc[iEncoding].le;
19458 msb = caps.enc[iEncoding].msb;
19459 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
19465 for (iExistingFormat = 0; iExistingFormat < pDeviceInfo->
formatCount; iExistingFormat += 1) {
19472 if (!formatExists) {
19478 for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
19479 unsigned int chan = 0;
19483 chan = caps.confs[iConfig].pchan;
19485 chan = caps.confs[iConfig].rchan;
19488 if ((chan & (1UL << iChannel)) == 0) {
19507 for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
19508 if ((caps.confs[iConfig].rate & (1UL << iRate)) != 0) {
19509 unsigned int rate = caps.rate[iRate];
19520 ((ma_sio_close_proc)pContext->sndio.sio_close)(handle);
19524 void ma_device_uninit__sndio(
ma_device* pDevice)
19526 ma_assert(pDevice !=
NULL);
19529 ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture);
19533 ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
19539 const char* pDeviceName;
19542 struct ma_sio_cap caps;
19543 struct ma_sio_par par;
19554 ma_assert(pContext !=
NULL);
19555 ma_assert(pConfig !=
NULL);
19557 ma_assert(pDevice !=
NULL);
19560 openFlags = MA_SIO_REC;
19566 openFlags = MA_SIO_PLAY;
19573 pDeviceName = MA_SIO_DEVANY;
19574 if (pDeviceID !=
NULL) {
19575 pDeviceName = pDeviceID->sndio;
19578 handle = (
ma_ptr)((ma_sio_open_proc)pContext->sndio.sio_open)(pDeviceName, openFlags, 0);
19579 if (handle ==
NULL) {
19584 if (((ma_sio_getcap_proc)pContext->sndio.sio_getcap)((
struct ma_sio_hdl*)handle, &caps) == 0) {
19585 ((ma_sio_close_proc)pContext->sndio.sio_close)((
struct ma_sio_hdl*)handle);
19598 if (pDevice->capture.usingDefaultFormat) {
19599 format = ma_find_best_format_from_sio_cap__sndio(&caps);
19601 if (pDevice->capture.usingDefaultChannels) {
19602 if (strlen(pDeviceName) > strlen(
"rsnd/") && strncmp(pDeviceName,
"rsnd/", strlen(
"rsnd/")) == 0) {
19603 channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType,
format);
19607 if (pDevice->playback.usingDefaultFormat) {
19608 format = ma_find_best_format_from_sio_cap__sndio(&caps);
19610 if (pDevice->playback.usingDefaultChannels) {
19611 if (strlen(pDeviceName) > strlen(
"rsnd/") && strncmp(pDeviceName,
"rsnd/", strlen(
"rsnd/")) == 0) {
19612 channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType,
format);
19617 if (pDevice->usingDefaultSampleRate) {
19622 ((ma_sio_initpar_proc)pDevice->pContext->sndio.sio_initpar)(&par);
19624 par.le = ma_is_little_endian();
19664 par.rate = sampleRate;
19667 if (internalBufferSizeInFrames == 0) {
19671 par.round = internalBufferSizeInFrames / pConfig->
periods;
19672 par.appbufsz = par.round * pConfig->
periods;
19674 if (((ma_sio_setpar_proc)pContext->sndio.sio_setpar)((
struct ma_sio_hdl*)handle, &par) == 0) {
19675 ((ma_sio_close_proc)pContext->sndio.sio_close)((
struct ma_sio_hdl*)handle);
19678 if (((ma_sio_getpar_proc)pContext->sndio.sio_getpar)((
struct ma_sio_hdl*)handle, &par) == 0) {
19679 ((ma_sio_close_proc)pContext->sndio.sio_close)((
struct ma_sio_hdl*)handle);
19683 internalFormat = ma_format_from_sio_enc__sndio(par.bits, par.bps, par.sig, par.le, par.msb);
19685 internalSampleRate = par.rate;
19686 internalPeriods = par.appbufsz / par.round;
19687 internalBufferSizeInFrames = par.appbufsz;
19690 pDevice->sndio.handleCapture = handle;
19692 pDevice->capture.internalChannels = internalChannels;
19693 pDevice->capture.internalSampleRate = internalSampleRate;
19695 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
19696 pDevice->capture.internalPeriods = internalPeriods;
19698 pDevice->sndio.handlePlayback = handle;
19700 pDevice->playback.internalChannels = internalChannels;
19701 pDevice->playback.internalSampleRate = internalSampleRate;
19703 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
19704 pDevice->playback.internalPeriods = internalPeriods;
19707 #ifdef MA_DEBUG_OUTPUT
19708 printf(
"DEVICE INFO\n");
19710 printf(
" Channels: %d\n", internalChannels);
19711 printf(
" Sample Rate: %d\n", internalSampleRate);
19712 printf(
" Buffer Size: %d\n", internalBufferSizeInFrames);
19713 printf(
" Periods: %d\n", internalPeriods);
19714 printf(
" appbufsz: %d\n", par.appbufsz);
19715 printf(
" round: %d\n", par.round);
19723 ma_assert(pDevice !=
NULL);
19725 ma_zero_object(&pDevice->sndio);
19746 ma_assert(pDevice !=
NULL);
19749 ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture);
19750 ma_atomic_exchange_32(&pDevice->sndio.isStartedCapture,
MA_FALSE);
19754 ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
19755 ma_atomic_exchange_32(&pDevice->sndio.isStartedPlayback,
MA_FALSE);
19765 if (!pDevice->sndio.isStartedPlayback) {
19766 ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
19767 ma_atomic_exchange_32(&pDevice->sndio.isStartedPlayback,
MA_TRUE);
19770 result = ((ma_sio_write_proc)pDevice->pContext->sndio.sio_write)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback, pPCMFrames, frameCount *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
19782 if (!pDevice->sndio.isStartedCapture) {
19783 ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture);
19784 ma_atomic_exchange_32(&pDevice->sndio.isStartedCapture,
MA_TRUE);
19787 result = ((ma_sio_read_proc)pDevice->pContext->sndio.sio_read)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture, pPCMFrames, frameCount *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
19797 ma_assert(pContext !=
NULL);
19806 #ifndef MA_NO_RUNTIME_LINKING
19807 const char* libsndioNames[] = {
19812 for (
i = 0;
i < ma_countof(libsndioNames); ++
i) {
19813 pContext->sndio.sndioSO = ma_dlopen(pContext, libsndioNames[
i]);
19814 if (pContext->sndio.sndioSO !=
NULL) {
19819 if (pContext->sndio.sndioSO ==
NULL) {
19823 pContext->sndio.sio_open = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_open");
19824 pContext->sndio.sio_close = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_close");
19825 pContext->sndio.sio_setpar = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_setpar");
19826 pContext->sndio.sio_getpar = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_getpar");
19827 pContext->sndio.sio_getcap = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_getcap");
19828 pContext->sndio.sio_write = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_write");
19829 pContext->sndio.sio_read = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_read");
19830 pContext->sndio.sio_start = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_start");
19831 pContext->sndio.sio_stop = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_stop");
19832 pContext->sndio.sio_initpar = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_initpar");
19834 pContext->sndio.sio_open = sio_open;
19835 pContext->sndio.sio_close = sio_close;
19836 pContext->sndio.sio_setpar = sio_setpar;
19837 pContext->sndio.sio_getpar = sio_getpar;
19838 pContext->sndio.sio_getcap = sio_getcap;
19839 pContext->sndio.sio_write = sio_write;
19840 pContext->sndio.sio_read = sio_read;
19841 pContext->sndio.sio_start = sio_start;
19842 pContext->sndio.sio_stop = sio_stop;
19843 pContext->sndio.sio_initpar = sio_initpar;
19846 pContext->
onUninit = ma_context_uninit__sndio;
19848 pContext->
onEnumDevices = ma_context_enumerate_devices__sndio;
19869 #ifdef MA_HAS_AUDIO4
19873 #include <sys/stat.h>
19874 #include <sys/types.h>
19875 #include <sys/ioctl.h>
19876 #include <sys/audioio.h>
19878 #if defined(__OpenBSD__)
19879 #include <sys/param.h>
19880 #if defined(OpenBSD) && OpenBSD >= 201709
19881 #define MA_AUDIO4_USE_NEW_API
19885 void ma_construct_device_id__audio4(
char*
id,
size_t idSize,
const char* base,
int deviceIndex)
19889 ma_assert(
id !=
NULL);
19890 ma_assert(idSize > 0);
19891 ma_assert(deviceIndex >= 0);
19893 baseLen = strlen(base);
19894 ma_assert(idSize > baseLen);
19896 ma_strcpy_s(
id, idSize, base);
19897 ma_itoa_s(deviceIndex,
id+baseLen, idSize-baseLen, 10);
19900 ma_result ma_extract_device_index_from_id__audio4(
const char*
id,
const char* base,
int* pIndexOut)
19904 const char* deviceIndexStr;
19906 ma_assert(
id !=
NULL);
19907 ma_assert(base !=
NULL);
19908 ma_assert(pIndexOut !=
NULL);
19910 idLen = strlen(
id);
19911 baseLen = strlen(base);
19912 if (idLen <= baseLen) {
19916 if (strncmp(
id, base, baseLen) != 0) {
19920 deviceIndexStr =
id + baseLen;
19921 if (deviceIndexStr[0] ==
'\0') {
19926 *pIndexOut = atoi(deviceIndexStr);
19934 ma_assert(pContext !=
NULL);
19935 ma_assert(pID0 !=
NULL);
19936 ma_assert(pID1 !=
NULL);
19939 return ma_strcmp(pID0->audio4, pID1->audio4) == 0;
19942 #if !defined(MA_AUDIO4_USE_NEW_API)
19943 ma_format ma_format_from_encoding__audio4(
unsigned int encoding,
unsigned int precision)
19945 if (precision == 8 && (encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR_LE || encoding == AUDIO_ENCODING_ULINEAR_BE)) {
19948 if (ma_is_little_endian() && encoding == AUDIO_ENCODING_SLINEAR_LE) {
19949 if (precision == 16) {
19951 }
else if (precision == 24) {
19953 }
else if (precision == 32) {
19956 }
else if (ma_is_big_endian() && encoding == AUDIO_ENCODING_SLINEAR_BE) {
19957 if (precision == 16) {
19959 }
else if (precision == 24) {
19961 }
else if (precision == 32) {
19970 void ma_encoding_from_format__audio4(
ma_format format,
unsigned int* pEncoding,
unsigned int* pPrecision)
19973 ma_assert(pEncoding !=
NULL);
19974 ma_assert(pPrecision !=
NULL);
19980 *pEncoding = AUDIO_ENCODING_ULINEAR;
19986 *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
19992 *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
20000 *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
20006 ma_format ma_format_from_prinfo__audio4(
struct audio_prinfo* prinfo)
20008 return ma_format_from_encoding__audio4(prinfo->encoding, prinfo->precision);
20011 ma_format ma_format_from_swpar__audio4(
struct audio_swpar* par)
20013 if (par->bits == 8 && par->bps == 1 && par->sig == 0) {
20016 if (par->bits == 16 && par->bps == 2 && par->sig == 1 && par->le == ma_is_little_endian()) {
20019 if (par->bits == 24 && par->bps == 3 && par->sig == 1 && par->le == ma_is_little_endian()) {
20022 if (par->bits == 32 && par->bps == 4 && par->sig == 1 && par->le == ma_is_little_endian()) {
20033 audio_device_t fdDevice;
20034 #if !defined(MA_AUDIO4_USE_NEW_API)
20036 audio_info_t fdInfo;
20038 struct audio_swpar fdPar;
20042 ma_assert(pContext !=
NULL);
20043 ma_assert(fd >= 0);
20044 ma_assert(pInfoOut !=
NULL);
20049 if (ioctl(fd, AUDIO_GETDEV, &fdDevice) < 0) {
20054 ma_strcpy_s(pInfoOut->
name,
sizeof(pInfoOut->
name), fdDevice.name);
20056 #if !defined(MA_AUDIO4_USE_NEW_API)
20059 audio_encoding_t encoding;
20062 ma_zero_object(&encoding);
20063 encoding.index = counter;
20064 if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
20068 format = ma_format_from_encoding__audio4(encoding.encoding, encoding.precision);
20076 if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
20092 if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
20096 format = ma_format_from_swpar__audio4(&fdPar);
20119 const int maxDevices = 64;
20123 ma_assert(pContext !=
NULL);
20124 ma_assert(callback !=
NULL);
20130 for (iDevice = 0; iDevice < maxDevices; ++iDevice) {
20135 ma_strcpy_s(devpath,
sizeof(devpath),
"/dev/audioctl");
20136 ma_itoa_s(iDevice, devpath+strlen(devpath),
sizeof(devpath)-strlen(devpath), 10);
20138 if (stat(devpath, &
st) < 0) {
20145 if (!isTerminating) {
20146 fd = open(devpath, O_RDONLY, 0);
20150 ma_zero_object(&deviceInfo);
20151 ma_construct_device_id__audio4(deviceInfo.
id.audio4,
sizeof(deviceInfo.
id.audio4),
"/dev/audio", iDevice);
20161 if (!isTerminating) {
20162 fd = open(devpath, O_WRONLY, 0);
20166 ma_zero_object(&deviceInfo);
20167 ma_construct_device_id__audio4(deviceInfo.
id.audio4,
sizeof(deviceInfo.
id.audio4),
"/dev/audio", iDevice);
20176 if (isTerminating) {
20187 int deviceIndex = -1;
20191 ma_assert(pContext !=
NULL);
20198 if (pDeviceID ==
NULL) {
20200 ma_strcpy_s(ctlid,
sizeof(ctlid),
"/dev/audioctl");
20203 result = ma_extract_device_index_from_id__audio4(pDeviceID->audio4,
"/dev/audio", &deviceIndex);
20208 ma_construct_device_id__audio4(ctlid,
sizeof(ctlid),
"/dev/audioctl", deviceIndex);
20216 if (deviceIndex == -1) {
20217 ma_strcpy_s(pDeviceInfo->
id.audio4,
sizeof(pDeviceInfo->
id.audio4),
"/dev/audio");
20219 ma_construct_device_id__audio4(pDeviceInfo->
id.audio4,
sizeof(pDeviceInfo->
id.audio4),
"/dev/audio", deviceIndex);
20222 result = ma_context_get_device_info_from_fd__audio4(pContext, deviceType, fd, pDeviceInfo);
20228 void ma_device_uninit__audio4(
ma_device* pDevice)
20230 ma_assert(pDevice !=
NULL);
20233 close(pDevice->audio4.fdCapture);
20237 close(pDevice->audio4.fdPlayback);
20243 const char* pDefaultDeviceNames[] = {
20249 #if !defined(MA_AUDIO4_USE_NEW_API)
20250 audio_info_t fdInfo;
20252 struct audio_swpar fdPar;
20260 ma_assert(pContext !=
NULL);
20261 ma_assert(pConfig !=
NULL);
20263 ma_assert(pDevice !=
NULL);
20269 fdFlags = O_RDONLY;
20271 fdFlags = O_WRONLY;
20273 fdFlags |= O_NONBLOCK;
20278 for (iDevice = 0; iDevice < ma_countof(pDefaultDeviceNames); ++iDevice) {
20279 fd = open(pDefaultDeviceNames[iDevice], fdFlags, 0);
20293 #if !defined(MA_AUDIO4_USE_NEW_API)
20294 AUDIO_INITINFO(&fdInfo);
20298 fdInfo.mode = AUMODE_RECORD;
20299 ma_encoding_from_format__audio4(pConfig->
capture.
format, &fdInfo.record.encoding, &fdInfo.record.precision);
20301 fdInfo.record.sample_rate = pConfig->
sampleRate;
20303 fdInfo.mode = AUMODE_PLAY;
20304 ma_encoding_from_format__audio4(pConfig->
playback.
format, &fdInfo.play.encoding, &fdInfo.play.precision);
20306 fdInfo.play.sample_rate = pConfig->
sampleRate;
20309 if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
20314 if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
20321 internalChannels = fdInfo.record.channels;
20322 internalSampleRate = fdInfo.record.sample_rate;
20325 internalChannels = fdInfo.play.channels;
20326 internalSampleRate = fdInfo.play.sample_rate;
20339 if (internalBufferSizeInFrames == 0) {
20344 if (internalBufferSizeInBytes < 16) {
20345 internalBufferSizeInBytes = 16;
20348 internalPeriods = pConfig->
periods;
20349 if (internalPeriods < 2) {
20350 internalPeriods = 2;
20354 AUDIO_INITINFO(&fdInfo);
20355 fdInfo.hiwat = internalPeriods;
20356 fdInfo.lowat = internalPeriods-1;
20357 fdInfo.blocksize = internalBufferSizeInBytes / internalPeriods;
20358 if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
20363 internalPeriods = fdInfo.hiwat;
20368 if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
20375 internalSampleRate = fdPar.rate;
20387 if (internalBufferSizeInFrames == 0) {
20393 if (internalBufferSizeInBytes < 16) {
20394 internalBufferSizeInBytes = 16;
20397 fdPar.nblks = pConfig->
periods;
20398 fdPar.round = internalBufferSizeInBytes / fdPar.nblks;
20400 if (ioctl(fd, AUDIO_SETPAR, &fdPar) < 0) {
20405 if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
20413 internalSampleRate = fdPar.rate;
20414 internalPeriods = fdPar.nblks;
20424 pDevice->audio4.fdCapture = fd;
20426 pDevice->capture.internalChannels = internalChannels;
20427 pDevice->capture.internalSampleRate = internalSampleRate;
20429 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
20430 pDevice->capture.internalPeriods = internalPeriods;
20432 pDevice->audio4.fdPlayback = fd;
20434 pDevice->playback.internalChannels = internalChannels;
20435 pDevice->playback.internalSampleRate = internalSampleRate;
20437 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
20438 pDevice->playback.internalPeriods = internalPeriods;
20446 ma_assert(pDevice !=
NULL);
20448 ma_zero_object(&pDevice->audio4);
20450 pDevice->audio4.fdCapture = -1;
20451 pDevice->audio4.fdPlayback = -1;
20458 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 800000000
20479 close(pDevice->audio4.fdCapture);
20491 ma_assert(pDevice !=
NULL);
20494 if (pDevice->audio4.fdCapture == -1) {
20500 if (pDevice->audio4.fdPlayback == -1) {
20515 #if !defined(MA_AUDIO4_USE_NEW_API)
20516 if (ioctl(fd, AUDIO_FLUSH, 0) < 0) {
20520 if (ioctl(fd, AUDIO_STOP, 0) < 0) {
20530 ma_assert(pDevice !=
NULL);
20533 ma_result result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdCapture);
20540 ma_result result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdPlayback);
20551 int result = write(pDevice->audio4.fdPlayback, pPCMFrames, frameCount *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
20561 int result = read(pDevice->audio4.fdCapture, pPCMFrames, frameCount *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
20571 ma_assert(pContext !=
NULL);
20580 ma_assert(pContext !=
NULL);
20584 pContext->
onUninit = ma_context_uninit__audio4;
20586 pContext->
onEnumDevices = ma_context_enumerate_devices__audio4;
20606 #include <sys/ioctl.h>
20607 #include <unistd.h>
20609 #include <sys/soundcard.h>
20611 #ifndef SNDCTL_DSP_HALT
20612 #define SNDCTL_DSP_HALT SNDCTL_DSP_RESET
20615 int ma_open_temp_device__oss()
20618 int fd = open(
"/dev/mixer", O_RDONLY, 0);
20628 const char* deviceName;
20631 ma_assert(pContext !=
NULL);
20632 ma_assert(pfd !=
NULL);
20642 deviceName =
"/dev/dsp";
20643 if (pDeviceID !=
NULL) {
20644 deviceName = pDeviceID->oss;
20652 *pfd = open(deviceName, flags, 0);
20662 ma_assert(pContext !=
NULL);
20663 ma_assert(pID0 !=
NULL);
20664 ma_assert(pID1 !=
NULL);
20667 return ma_strcmp(pID0->oss, pID1->oss) == 0;
20676 ma_assert(pContext !=
NULL);
20677 ma_assert(callback !=
NULL);
20679 fd = ma_open_temp_device__oss();
20681 return ma_context_post_error(pContext,
NULL,
MA_LOG_LEVEL_ERROR,
"[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.",
MA_NO_BACKEND);
20684 result = ioctl(fd, SNDCTL_SYSINFO, &si);
20685 if (result != -1) {
20687 for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
20689 ai.dev = iAudioDevice;
20690 result = ioctl(fd, SNDCTL_AUDIOINFO, &ai);
20691 if (result != -1) {
20692 if (ai.devnode[0] !=
'\0') {
20696 ma_zero_object(&deviceInfo);
20699 ma_strncpy_s(deviceInfo.
id.oss,
sizeof(deviceInfo.
id.oss), ai.devnode, (
size_t)-1);
20706 if (ai.handle[0] !=
'\0') {
20707 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), ai.handle, (
size_t)-1);
20709 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), ai.name, (
size_t)-1);
20713 if (!isTerminating && (ai.caps & PCM_CAP_OUTPUT) != 0) {
20716 if (!isTerminating && (ai.caps & PCM_CAP_INPUT) != 0) {
20720 if (isTerminating) {
20742 ma_assert(pContext !=
NULL);
20746 if (pDeviceID ==
NULL) {
20748 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
20750 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
20760 fdTemp = ma_open_temp_device__oss();
20761 if (fdTemp == -1) {
20762 return ma_context_post_error(pContext,
NULL,
MA_LOG_LEVEL_ERROR,
"[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.",
MA_NO_BACKEND);
20765 result = ioctl(fdTemp, SNDCTL_SYSINFO, &si);
20766 if (result != -1) {
20768 for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
20770 ai.dev = iAudioDevice;
20771 result = ioctl(fdTemp, SNDCTL_AUDIOINFO, &ai);
20772 if (result != -1) {
20773 if (ma_strcmp(ai.devnode, pDeviceID->oss) == 0) {
20777 unsigned int formatMask;
20780 ma_strncpy_s(pDeviceInfo->
id.oss,
sizeof(pDeviceInfo->
id.oss), ai.devnode, (
size_t)-1);
20787 if (ai.handle[0] !=
'\0') {
20788 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), ai.handle, (
size_t)-1);
20790 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), ai.name, (
size_t)-1);
20800 formatMask = ai.oformats;
20802 formatMask = ai.iformats;
20805 if ((formatMask & AFMT_U8) != 0) {
20808 if (((formatMask & AFMT_S16_LE) != 0 && ma_is_little_endian()) || (AFMT_S16_BE && ma_is_big_endian())) {
20811 if (((formatMask & AFMT_S32_LE) != 0 && ma_is_little_endian()) || (AFMT_S32_BE && ma_is_big_endian())) {
20829 if (!foundDevice) {
20836 void ma_device_uninit__oss(
ma_device* pDevice)
20838 ma_assert(pDevice !=
NULL);
20841 close(pDevice->oss.fdCapture);
20845 close(pDevice->oss.fdPlayback);
20851 int ossFormat = AFMT_U8;
20853 case ma_format_s16: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE;
break;
20854 case ma_format_s24: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE;
break;
20855 case ma_format_s32: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE;
break;
20856 case ma_format_f32: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE;
break;
20858 default: ossFormat = AFMT_U8;
break;
20864 ma_format ma_format_from_oss(
int ossFormat)
20866 if (ossFormat == AFMT_U8) {
20869 if (ma_is_little_endian()) {
20870 switch (ossFormat) {
20876 switch (ossFormat) {
20899 ma_assert(pContext !=
NULL);
20900 ma_assert(pConfig !=
NULL);
20902 ma_assert(pDevice !=
NULL);
20920 result = ma_context_open_device__oss(pContext, deviceType, pDeviceID, shareMode, &fd);
20933 ossResult = ioctl(fd, SNDCTL_DSP_SETFMT, &ossFormat);
20934 if (ossResult == -1) {
20940 ossResult = ioctl(fd, SNDCTL_DSP_CHANNELS, &ossChannels);
20941 if (ossResult == -1) {
20947 ossResult = ioctl(fd, SNDCTL_DSP_SPEED, &ossSampleRate);
20948 if (ossResult == -1) {
20968 if (bufferSizeInFrames == 0) {
20972 fragmentSizeInBytes = ma_round_to_power_of_2((bufferSizeInFrames / pConfig->
periods) *
ma_get_bytes_per_frame(ma_format_from_oss(ossFormat), ossChannels));
20973 if (fragmentSizeInBytes < 16) {
20974 fragmentSizeInBytes = 16;
20977 ossFragmentSizePower = 4;
20978 fragmentSizeInBytes >>= 4;
20979 while (fragmentSizeInBytes >>= 1) {
20980 ossFragmentSizePower += 1;
20983 ossFragment = (
int)((pConfig->
periods << 16) | ossFragmentSizePower);
20984 ossResult = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossFragment);
20985 if (ossResult == -1) {
20993 pDevice->oss.fdCapture = fd;
20994 pDevice->capture.internalFormat = ma_format_from_oss(ossFormat);
20995 pDevice->capture.internalChannels = ossChannels;
20996 pDevice->capture.internalSampleRate = ossSampleRate;
20998 pDevice->capture.internalPeriods = (
ma_uint32)(ossFragment >> 16);
20999 pDevice->capture.internalBufferSizeInFrames = (((
ma_uint32)(1 << (ossFragment & 0xFFFF))) * pDevice->capture.internalPeriods) /
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
21005 pDevice->oss.fdPlayback = fd;
21006 pDevice->playback.internalFormat = ma_format_from_oss(ossFormat);
21007 pDevice->playback.internalChannels = ossChannels;
21008 pDevice->playback.internalSampleRate = ossSampleRate;
21010 pDevice->playback.internalPeriods = (
ma_uint32)(ossFragment >> 16);
21011 pDevice->playback.internalBufferSizeInFrames = (((
ma_uint32)(1 << (ossFragment & 0xFFFF))) * pDevice->playback.internalPeriods) /
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
21023 ma_assert(pContext !=
NULL);
21024 ma_assert(pConfig !=
NULL);
21025 ma_assert(pDevice !=
NULL);
21027 ma_zero_object(&pDevice->oss);
21048 ma_assert(pDevice !=
NULL);
21064 int result = ioctl(pDevice->oss.fdCapture, SNDCTL_DSP_HALT, 0);
21065 if (result == -1) {
21071 int result = ioctl(pDevice->oss.fdPlayback, SNDCTL_DSP_HALT, 0);
21072 if (result == -1) {
21082 int resultOSS = write(pDevice->oss.fdPlayback, pPCMFrames, frameCount *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
21083 if (resultOSS < 0) {
21092 int resultOSS = read(pDevice->oss.fdCapture, pPCMFrames, frameCount *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
21093 if (resultOSS < 0) {
21102 ma_assert(pContext !=
NULL);
21115 ma_assert(pContext !=
NULL);
21120 fd = ma_open_temp_device__oss();
21127 result = ioctl(fd, OSS_GETVERSION, &ossVersion);
21128 if (result == -1) {
21133 pContext->oss.versionMajor = ((ossVersion & 0xFF0000) >> 16);
21134 pContext->oss.versionMinor = ((ossVersion & 0x00FF00) >> 8);
21136 pContext->
onUninit = ma_context_uninit__oss;
21138 pContext->
onEnumDevices = ma_context_enumerate_devices__oss;
21158 #ifdef MA_HAS_AAUDIO
21161 #define MA_AAUDIO_UNSPECIFIED 0
21163 typedef int32_t ma_aaudio_result_t;
21164 typedef int32_t ma_aaudio_direction_t;
21165 typedef int32_t ma_aaudio_sharing_mode_t;
21166 typedef int32_t ma_aaudio_format_t;
21167 typedef int32_t ma_aaudio_stream_state_t;
21168 typedef int32_t ma_aaudio_performance_mode_t;
21169 typedef int32_t ma_aaudio_data_callback_result_t;
21172 #define MA_AAUDIO_OK 0
21175 #define MA_AAUDIO_DIRECTION_OUTPUT 0
21176 #define MA_AAUDIO_DIRECTION_INPUT 1
21179 #define MA_AAUDIO_SHARING_MODE_EXCLUSIVE 0
21180 #define MA_AAUDIO_SHARING_MODE_SHARED 1
21183 #define MA_AAUDIO_FORMAT_PCM_I16 1
21184 #define MA_AAUDIO_FORMAT_PCM_FLOAT 2
21187 #define MA_AAUDIO_STREAM_STATE_UNINITIALIZED 0
21188 #define MA_AAUDIO_STREAM_STATE_UNKNOWN 1
21189 #define MA_AAUDIO_STREAM_STATE_OPEN 2
21190 #define MA_AAUDIO_STREAM_STATE_STARTING 3
21191 #define MA_AAUDIO_STREAM_STATE_STARTED 4
21192 #define MA_AAUDIO_STREAM_STATE_PAUSING 5
21193 #define MA_AAUDIO_STREAM_STATE_PAUSED 6
21194 #define MA_AAUDIO_STREAM_STATE_FLUSHING 7
21195 #define MA_AAUDIO_STREAM_STATE_FLUSHED 8
21196 #define MA_AAUDIO_STREAM_STATE_STOPPING 9
21197 #define MA_AAUDIO_STREAM_STATE_STOPPED 10
21198 #define MA_AAUDIO_STREAM_STATE_CLOSING 11
21199 #define MA_AAUDIO_STREAM_STATE_CLOSED 12
21200 #define MA_AAUDIO_STREAM_STATE_DISCONNECTED 13
21203 #define MA_AAUDIO_PERFORMANCE_MODE_NONE 10
21204 #define MA_AAUDIO_PERFORMANCE_MODE_POWER_SAVING 11
21205 #define MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY 12
21208 #define MA_AAUDIO_CALLBACK_RESULT_CONTINUE 0
21209 #define MA_AAUDIO_CALLBACK_RESULT_STOP 1
21212 typedef struct ma_AAudioStreamBuilder_t* ma_AAudioStreamBuilder;
21213 typedef struct ma_AAudioStream_t* ma_AAudioStream;
21215 typedef ma_aaudio_data_callback_result_t (*ma_AAudioStream_dataCallback)(ma_AAudioStream* pStream,
void* pUserData,
void* pAudioData, int32_t numFrames);
21217 typedef ma_aaudio_result_t (* MA_PFN_AAudio_createStreamBuilder) (ma_AAudioStreamBuilder** ppBuilder);
21218 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_delete) (ma_AAudioStreamBuilder* pBuilder);
21219 typedef void (* MA_PFN_AAudioStreamBuilder_setDeviceId) (ma_AAudioStreamBuilder* pBuilder, int32_t deviceId);
21220 typedef void (* MA_PFN_AAudioStreamBuilder_setDirection) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_direction_t direction);
21221 typedef void (* MA_PFN_AAudioStreamBuilder_setSharingMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_sharing_mode_t sharingMode);
21222 typedef void (* MA_PFN_AAudioStreamBuilder_setFormat) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_format_t
format);
21223 typedef void (* MA_PFN_AAudioStreamBuilder_setChannelCount) (ma_AAudioStreamBuilder* pBuilder, int32_t channelCount);
21224 typedef void (* MA_PFN_AAudioStreamBuilder_setSampleRate) (ma_AAudioStreamBuilder* pBuilder, int32_t sampleRate);
21225 typedef void (* MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)(ma_AAudioStreamBuilder* pBuilder, int32_t numFrames);
21226 typedef void (* MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback) (ma_AAudioStreamBuilder* pBuilder, int32_t numFrames);
21227 typedef void (* MA_PFN_AAudioStreamBuilder_setDataCallback) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream_dataCallback callback,
void* pUserData);
21228 typedef void (* MA_PFN_AAudioStreamBuilder_setPerformanceMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_performance_mode_t
mode);
21229 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_openStream) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream** ppStream);
21230 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_close) (ma_AAudioStream* pStream);
21231 typedef ma_aaudio_stream_state_t (* MA_PFN_AAudioStream_getState) (ma_AAudioStream* pStream);
21232 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_waitForStateChange) (ma_AAudioStream* pStream, ma_aaudio_stream_state_t inputState, ma_aaudio_stream_state_t* pNextState, int64_t timeoutInNanoseconds);
21233 typedef ma_aaudio_format_t (* MA_PFN_AAudioStream_getFormat) (ma_AAudioStream* pStream);
21234 typedef int32_t (* MA_PFN_AAudioStream_getChannelCount) (ma_AAudioStream* pStream);
21235 typedef int32_t (* MA_PFN_AAudioStream_getSampleRate) (ma_AAudioStream* pStream);
21236 typedef int32_t (* MA_PFN_AAudioStream_getBufferCapacityInFrames) (ma_AAudioStream* pStream);
21237 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerDataCallback) (ma_AAudioStream* pStream);
21238 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerBurst) (ma_AAudioStream* pStream);
21239 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStart) (ma_AAudioStream* pStream);
21240 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStop) (ma_AAudioStream* pStream);
21242 ma_result ma_result_from_aaudio(ma_aaudio_result_t resultAA)
21253 ma_aaudio_data_callback_result_t ma_stream_data_callback_capture__aaudio(ma_AAudioStream* pStream,
void* pUserData,
void* pAudioData, int32_t frameCount)
21256 ma_assert(pDevice !=
NULL);
21259 ma_device__handle_duplex_callback_capture(pDevice, frameCount, pAudioData, &pDevice->aaudio.duplexRB);
21261 ma_device__send_frames_to_client(pDevice, frameCount, pAudioData);
21265 return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
21268 ma_aaudio_data_callback_result_t ma_stream_data_callback_playback__aaudio(ma_AAudioStream* pStream,
void* pUserData,
void* pAudioData, int32_t frameCount)
21271 ma_assert(pDevice !=
NULL);
21274 ma_device__handle_duplex_callback_playback(pDevice, frameCount, pAudioData, &pDevice->aaudio.duplexRB);
21276 ma_device__read_frames_from_client(pDevice, frameCount, pAudioData);
21280 return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
21285 ma_AAudioStreamBuilder* pBuilder;
21286 ma_aaudio_result_t resultAA;
21292 resultAA = ((MA_PFN_AAudio_createStreamBuilder)pContext->aaudio.AAudio_createStreamBuilder)(&pBuilder);
21293 if (resultAA != MA_AAUDIO_OK) {
21294 return ma_result_from_aaudio(resultAA);
21297 if (pDeviceID !=
NULL) {
21298 ((MA_PFN_AAudioStreamBuilder_setDeviceId)pContext->aaudio.AAudioStreamBuilder_setDeviceId)(pBuilder, pDeviceID->aaudio);
21301 ((MA_PFN_AAudioStreamBuilder_setDirection)pContext->aaudio.AAudioStreamBuilder_setDirection)(pBuilder, (deviceType ==
ma_device_type_playback) ? MA_AAUDIO_DIRECTION_OUTPUT : MA_AAUDIO_DIRECTION_INPUT);
21302 ((MA_PFN_AAudioStreamBuilder_setSharingMode)pContext->aaudio.AAudioStreamBuilder_setSharingMode)(pBuilder, (shareMode ==
ma_share_mode_shared) ? MA_AAUDIO_SHARING_MODE_SHARED : MA_AAUDIO_SHARING_MODE_EXCLUSIVE);
21304 if (pConfig !=
NULL) {
21307 if (pDevice ==
NULL || !pDevice->usingDefaultSampleRate) {
21308 ((MA_PFN_AAudioStreamBuilder_setSampleRate)pContext->aaudio.AAudioStreamBuilder_setSampleRate)(pBuilder, pConfig->
sampleRate);
21312 if (pDevice ==
NULL || !pDevice->capture.usingDefaultChannels) {
21313 ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pConfig->
capture.
channels);
21315 if (pDevice ==
NULL || !pDevice->capture.usingDefaultFormat) {
21316 ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pConfig->
capture.
format ==
ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
21319 if (pDevice ==
NULL || !pDevice->playback.usingDefaultChannels) {
21320 ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pConfig->
playback.
channels);
21322 if (pDevice ==
NULL || !pDevice->playback.usingDefaultFormat) {
21323 ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pConfig->
playback.
format ==
ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
21328 if (bufferCapacityInFrames == 0) {
21331 ((MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames)(pBuilder, bufferCapacityInFrames);
21333 ((MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback)pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback)(pBuilder, bufferCapacityInFrames / pConfig->
periods);
21336 ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_capture__aaudio, (
void*)pDevice);
21338 ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_playback__aaudio, (
void*)pDevice);
21342 ((MA_PFN_AAudioStreamBuilder_setPerformanceMode)pContext->aaudio.AAudioStreamBuilder_setPerformanceMode)(pBuilder, (pConfig->
performanceProfile ==
ma_performance_profile_low_latency) ? MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY : MA_AAUDIO_PERFORMANCE_MODE_NONE);
21345 resultAA = ((MA_PFN_AAudioStreamBuilder_openStream)pContext->aaudio.AAudioStreamBuilder_openStream)(pBuilder, ppStream);
21346 if (resultAA != MA_AAUDIO_OK) {
21348 ((MA_PFN_AAudioStreamBuilder_delete)pContext->aaudio.AAudioStreamBuilder_delete)(pBuilder);
21349 return ma_result_from_aaudio(resultAA);
21352 ((MA_PFN_AAudioStreamBuilder_delete)pContext->aaudio.AAudioStreamBuilder_delete)(pBuilder);
21358 return ma_result_from_aaudio(((MA_PFN_AAudioStream_close)pContext->aaudio.AAudioStream_close)(pStream));
21364 ma_AAudioStream* pStream;
21370 ma_close_stream__aaudio(pContext, pStream);
21374 ma_result ma_wait_for_simple_state_transition__aaudio(
ma_context* pContext, ma_AAudioStream* pStream, ma_aaudio_stream_state_t oldState, ma_aaudio_stream_state_t newState)
21376 ma_aaudio_stream_state_t actualNewState;
21377 ma_aaudio_result_t resultAA = ((MA_PFN_AAudioStream_waitForStateChange)pContext->aaudio.AAudioStream_waitForStateChange)(pStream, oldState, &actualNewState, 5000000000);
21378 if (resultAA != MA_AAUDIO_OK) {
21379 return ma_result_from_aaudio(resultAA);
21382 if (newState != actualNewState) {
21392 ma_assert(pContext !=
NULL);
21393 ma_assert(pID0 !=
NULL);
21394 ma_assert(pID1 !=
NULL);
21397 return pID0->aaudio == pID1->aaudio;
21404 ma_assert(pContext !=
NULL);
21405 ma_assert(callback !=
NULL);
21412 ma_zero_object(&deviceInfo);
21413 deviceInfo.
id.aaudio = MA_AAUDIO_UNSPECIFIED;
21414 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
21424 ma_zero_object(&deviceInfo);
21425 deviceInfo.
id.aaudio = MA_AAUDIO_UNSPECIFIED;
21426 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
21438 ma_AAudioStream* pStream;
21441 ma_assert(pContext !=
NULL);
21449 if (pDeviceID !=
NULL) {
21450 pDeviceInfo->
id.aaudio = pDeviceID->aaudio;
21452 pDeviceInfo->
id.aaudio = MA_AAUDIO_UNSPECIFIED;
21457 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
21459 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
21464 result = ma_open_stream__aaudio(pContext, deviceType, pDeviceID, shareMode,
NULL,
NULL, &pStream);
21469 pDeviceInfo->
minChannels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)(pStream);
21471 pDeviceInfo->
minSampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)(pStream);
21474 ma_close_stream__aaudio(pContext, pStream);
21487 void ma_device_uninit__aaudio(
ma_device* pDevice)
21489 ma_assert(pDevice !=
NULL);
21492 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21493 pDevice->aaudio.pStreamCapture =
NULL;
21497 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21498 pDevice->aaudio.pStreamPlayback =
NULL;
21510 ma_assert(pDevice !=
NULL);
21520 int32_t framesPerPeriod;
21527 pDevice->capture.internalFormat = (((MA_PFN_AAudioStream_getFormat)pContext->aaudio.AAudioStream_getFormat)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture) == MA_AAUDIO_FORMAT_PCM_I16) ?
ma_format_s16 :
ma_format_f32;
21528 pDevice->capture.internalChannels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21529 pDevice->capture.internalSampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21531 pDevice->capture.internalBufferSizeInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pContext->aaudio.AAudioStream_getBufferCapacityInFrames)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21537 framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21538 if (framesPerPeriod > 0) {
21539 pDevice->capture.internalPeriods = 1;
21541 pDevice->capture.internalPeriods = pDevice->capture.internalBufferSizeInFrames / framesPerPeriod;
21546 int32_t framesPerPeriod;
21553 pDevice->playback.internalFormat = (((MA_PFN_AAudioStream_getFormat)pContext->aaudio.AAudioStream_getFormat)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback) == MA_AAUDIO_FORMAT_PCM_I16) ?
ma_format_s16 :
ma_format_f32;
21554 pDevice->playback.internalChannels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21555 pDevice->playback.internalSampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21557 pDevice->playback.internalBufferSizeInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pContext->aaudio.AAudioStream_getBufferCapacityInFrames)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21559 framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21560 if (framesPerPeriod > 0) {
21561 pDevice->playback.internalPeriods = 1;
21563 pDevice->playback.internalPeriods = pDevice->playback.internalBufferSizeInFrames / framesPerPeriod;
21568 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
21569 ma_result result =
ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames,
NULL, &pDevice->aaudio.duplexRB);
21572 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21575 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21577 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[AAudio] Failed to initialize ring buffer.", result);
21584 ma_result ma_device_start_stream__aaudio(
ma_device* pDevice, ma_AAudioStream* pStream)
21586 ma_aaudio_result_t resultAA;
21587 ma_aaudio_stream_state_t currentState;
21589 ma_assert(pDevice !=
NULL);
21591 resultAA = ((MA_PFN_AAudioStream_requestStart)pDevice->pContext->aaudio.AAudioStream_requestStart)(pStream);
21592 if (resultAA != MA_AAUDIO_OK) {
21593 return ma_result_from_aaudio(resultAA);
21599 currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
21600 if (currentState != MA_AAUDIO_STREAM_STATE_STARTED) {
21603 if (currentState != MA_AAUDIO_STREAM_STATE_STARTING) {
21607 result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STARTED);
21616 ma_result ma_device_stop_stream__aaudio(
ma_device* pDevice, ma_AAudioStream* pStream)
21618 ma_aaudio_result_t resultAA;
21619 ma_aaudio_stream_state_t currentState;
21621 ma_assert(pDevice !=
NULL);
21623 resultAA = ((MA_PFN_AAudioStream_requestStop)pDevice->pContext->aaudio.AAudioStream_requestStop)(pStream);
21624 if (resultAA != MA_AAUDIO_OK) {
21625 return ma_result_from_aaudio(resultAA);
21629 currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
21630 if (currentState != MA_AAUDIO_STREAM_STATE_STOPPED) {
21633 if (currentState != MA_AAUDIO_STREAM_STATE_STOPPING) {
21637 result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STOPPED);
21648 ma_assert(pDevice !=
NULL);
21651 ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21658 ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21661 ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21674 ma_assert(pDevice !=
NULL);
21677 ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
21684 ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
21690 onStop = pDevice->onStop;
21701 ma_assert(pContext !=
NULL);
21704 ma_dlclose(pContext, pContext->aaudio.hAAudio);
21705 pContext->aaudio.hAAudio =
NULL;
21712 const char* libNames[] = {
21717 for (
i = 0;
i < ma_countof(libNames); ++
i) {
21718 pContext->aaudio.hAAudio = ma_dlopen(pContext, libNames[
i]);
21719 if (pContext->aaudio.hAAudio !=
NULL) {
21724 if (pContext->aaudio.hAAudio ==
NULL) {
21728 pContext->aaudio.AAudio_createStreamBuilder = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudio_createStreamBuilder");
21729 pContext->aaudio.AAudioStreamBuilder_delete = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_delete");
21730 pContext->aaudio.AAudioStreamBuilder_setDeviceId = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setDeviceId");
21731 pContext->aaudio.AAudioStreamBuilder_setDirection = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setDirection");
21732 pContext->aaudio.AAudioStreamBuilder_setSharingMode = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setSharingMode");
21733 pContext->aaudio.AAudioStreamBuilder_setFormat = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setFormat");
21734 pContext->aaudio.AAudioStreamBuilder_setChannelCount = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setChannelCount");
21735 pContext->aaudio.AAudioStreamBuilder_setSampleRate = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setSampleRate");
21736 pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setBufferCapacityInFrames");
21737 pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setFramesPerDataCallback");
21738 pContext->aaudio.AAudioStreamBuilder_setDataCallback = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setDataCallback");
21739 pContext->aaudio.AAudioStreamBuilder_setPerformanceMode = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setPerformanceMode");
21740 pContext->aaudio.AAudioStreamBuilder_openStream = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_openStream");
21741 pContext->aaudio.AAudioStream_close = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_close");
21742 pContext->aaudio.AAudioStream_getState = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getState");
21743 pContext->aaudio.AAudioStream_waitForStateChange = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_waitForStateChange");
21744 pContext->aaudio.AAudioStream_getFormat = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getFormat");
21745 pContext->aaudio.AAudioStream_getChannelCount = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getChannelCount");
21746 pContext->aaudio.AAudioStream_getSampleRate = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getSampleRate");
21747 pContext->aaudio.AAudioStream_getBufferCapacityInFrames = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getBufferCapacityInFrames");
21748 pContext->aaudio.AAudioStream_getFramesPerDataCallback = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getFramesPerDataCallback");
21749 pContext->aaudio.AAudioStream_getFramesPerBurst = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getFramesPerBurst");
21750 pContext->aaudio.AAudioStream_requestStart = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_requestStart");
21751 pContext->aaudio.AAudioStream_requestStop = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_requestStop");
21755 pContext->
onUninit = ma_context_uninit__aaudio;
21757 pContext->
onEnumDevices = ma_context_enumerate_devices__aaudio;
21775 #ifdef MA_HAS_OPENSL
21776 #include <SLES/OpenSLES.h>
21778 #include <SLES/OpenSLES_Android.h>
21782 SLObjectItf g_maEngineObjectSL =
NULL;
21783 SLEngineItf g_maEngineSL =
NULL;
21786 #define MA_OPENSL_OBJ(p) (*((SLObjectItf)(p)))
21787 #define MA_OPENSL_OUTPUTMIX(p) (*((SLOutputMixItf)(p)))
21788 #define MA_OPENSL_PLAY(p) (*((SLPlayItf)(p)))
21789 #define MA_OPENSL_RECORD(p) (*((SLRecordItf)(p)))
21792 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLAndroidSimpleBufferQueueItf)(p)))
21794 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLBufferQueueItf)(p)))
21798 ma_uint8 ma_channel_id_to_ma__opensl(SLuint32
id)
21825 SLuint32 ma_channel_id_to_opensl(
ma_uint8 id)
21855 SLuint32 channelMask = 0;
21857 for (iChannel = 0; iChannel <
channels; ++iChannel) {
21858 channelMask |= ma_channel_id_to_opensl(channelMap[iChannel]);
21861 return channelMask;
21867 if (
channels == 1 && channelMask == 0) {
21869 }
else if (
channels == 2 && channelMask == 0) {
21873 if (
channels == 1 && (channelMask & SL_SPEAKER_FRONT_CENTER) != 0) {
21879 for (iBit = 0; iBit < 32; ++iBit) {
21880 SLuint32 bitValue = (channelMask & (1UL << iBit));
21881 if (bitValue != 0) {
21883 channelMap[iChannel] = ma_channel_id_to_ma__opensl(bitValue);
21891 SLuint32 ma_round_to_standard_sample_rate__opensl(SLuint32 samplesPerSec)
21893 if (samplesPerSec <= SL_SAMPLINGRATE_8) {
21894 return SL_SAMPLINGRATE_8;
21896 if (samplesPerSec <= SL_SAMPLINGRATE_11_025) {
21897 return SL_SAMPLINGRATE_11_025;
21899 if (samplesPerSec <= SL_SAMPLINGRATE_12) {
21900 return SL_SAMPLINGRATE_12;
21902 if (samplesPerSec <= SL_SAMPLINGRATE_16) {
21903 return SL_SAMPLINGRATE_16;
21905 if (samplesPerSec <= SL_SAMPLINGRATE_22_05) {
21906 return SL_SAMPLINGRATE_22_05;
21908 if (samplesPerSec <= SL_SAMPLINGRATE_24) {
21909 return SL_SAMPLINGRATE_24;
21911 if (samplesPerSec <= SL_SAMPLINGRATE_32) {
21912 return SL_SAMPLINGRATE_32;
21914 if (samplesPerSec <= SL_SAMPLINGRATE_44_1) {
21915 return SL_SAMPLINGRATE_44_1;
21917 if (samplesPerSec <= SL_SAMPLINGRATE_48) {
21918 return SL_SAMPLINGRATE_48;
21923 if (samplesPerSec <= SL_SAMPLINGRATE_64) {
21924 return SL_SAMPLINGRATE_64;
21926 if (samplesPerSec <= SL_SAMPLINGRATE_88_2) {
21927 return SL_SAMPLINGRATE_88_2;
21929 if (samplesPerSec <= SL_SAMPLINGRATE_96) {
21930 return SL_SAMPLINGRATE_96;
21932 if (samplesPerSec <= SL_SAMPLINGRATE_192) {
21933 return SL_SAMPLINGRATE_192;
21937 return SL_SAMPLINGRATE_16;
21943 ma_assert(pContext !=
NULL);
21944 ma_assert(pID0 !=
NULL);
21945 ma_assert(pID1 !=
NULL);
21948 return pID0->opensl == pID1->opensl;
21955 ma_assert(pContext !=
NULL);
21956 ma_assert(callback !=
NULL);
21958 ma_assert(g_maOpenSLInitCounter > 0);
21959 if (g_maOpenSLInitCounter == 0) {
21968 #if 0 && !defined(MA_ANDROID)
21971 SLuint32 pDeviceIDs[128];
21972 SLint32 deviceCount =
sizeof(pDeviceIDs) /
sizeof(pDeviceIDs[0]);
21974 SLAudioIODeviceCapabilitiesItf deviceCaps;
21975 SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
21976 if (resultSL != SL_RESULT_SUCCESS) {
21978 goto return_default_device;
21982 if (!isTerminated) {
21983 resultSL = (*deviceCaps)->GetAvailableAudioOutputs(deviceCaps, &deviceCount, pDeviceIDs);
21984 if (resultSL != SL_RESULT_SUCCESS) {
21988 for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
21990 ma_zero_object(&deviceInfo);
21991 deviceInfo.
id.opensl = pDeviceIDs[iDevice];
21993 SLAudioOutputDescriptor desc;
21994 resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, deviceInfo.
id.opensl, &desc);
21995 if (resultSL == SL_RESULT_SUCCESS) {
21996 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), (
const char*)desc.pDeviceName, (
size_t)-1);
22008 if (!isTerminated) {
22009 resultSL = (*deviceCaps)->GetAvailableAudioInputs(deviceCaps, &deviceCount, pDeviceIDs);
22010 if (resultSL != SL_RESULT_SUCCESS) {
22014 for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
22016 ma_zero_object(&deviceInfo);
22017 deviceInfo.
id.opensl = pDeviceIDs[iDevice];
22019 SLAudioInputDescriptor desc;
22020 resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, deviceInfo.
id.opensl, &desc);
22021 if (resultSL == SL_RESULT_SUCCESS) {
22022 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), (
const char*)desc.deviceName, (
size_t)-1);
22035 goto return_default_device;
22038 return_default_device:;
22044 ma_zero_object(&deviceInfo);
22045 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
22052 ma_zero_object(&deviceInfo);
22053 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
22062 ma_assert(pContext !=
NULL);
22064 ma_assert(g_maOpenSLInitCounter > 0);
22065 if (g_maOpenSLInitCounter == 0) {
22079 #if 0 && !defined(MA_ANDROID)
22080 SLAudioIODeviceCapabilitiesItf deviceCaps;
22081 SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
22082 if (resultSL != SL_RESULT_SUCCESS) {
22084 goto return_default_device;
22088 SLAudioOutputDescriptor desc;
22089 resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
22090 if (resultSL != SL_RESULT_SUCCESS) {
22094 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), (
const char*)desc.pDeviceName, (
size_t)-1);
22096 SLAudioInputDescriptor desc;
22097 resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
22098 if (resultSL != SL_RESULT_SUCCESS) {
22102 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), (
const char*)desc.deviceName, (
size_t)-1);
22105 goto return_detailed_info;
22107 goto return_default_device;
22110 return_default_device:
22111 if (pDeviceID !=
NULL) {
22120 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
22122 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
22125 goto return_detailed_info;
22128 return_detailed_info:
22142 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
22153 void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue,
void* pUserData)
22156 size_t periodSizeInBytes;
22160 ma_assert(pDevice !=
NULL);
22162 (
void)pBufferQueue;
22171 if (pDevice->state != MA_STATE_STARTED) {
22175 periodSizeInBytes = (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods) *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22176 pBuffer = pDevice->opensl.pBufferCapture + (pDevice->opensl.currentBufferIndexCapture * periodSizeInBytes);
22179 ma_device__handle_duplex_callback_capture(pDevice, (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods), pBuffer, &pDevice->opensl.duplexRB);
22181 ma_device__send_frames_to_client(pDevice, (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods), pBuffer);
22184 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pBuffer, periodSizeInBytes);
22185 if (resultSL != SL_RESULT_SUCCESS) {
22189 pDevice->opensl.currentBufferIndexCapture = (pDevice->opensl.currentBufferIndexCapture + 1) % pDevice->capture.internalPeriods;
22192 void ma_buffer_queue_callback_playback__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue,
void* pUserData)
22195 size_t periodSizeInBytes;
22199 ma_assert(pDevice !=
NULL);
22201 (
void)pBufferQueue;
22204 if (pDevice->state != MA_STATE_STARTED) {
22208 periodSizeInBytes = (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods) *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22209 pBuffer = pDevice->opensl.pBufferPlayback + (pDevice->opensl.currentBufferIndexPlayback * periodSizeInBytes);
22212 ma_device__handle_duplex_callback_playback(pDevice, (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods), pBuffer, &pDevice->opensl.duplexRB);
22214 ma_device__read_frames_from_client(pDevice, (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods), pBuffer);
22217 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pBuffer, periodSizeInBytes);
22218 if (resultSL != SL_RESULT_SUCCESS) {
22222 pDevice->opensl.currentBufferIndexPlayback = (pDevice->opensl.currentBufferIndexPlayback + 1) % pDevice->playback.internalPeriods;
22226 void ma_device_uninit__opensl(
ma_device* pDevice)
22228 ma_assert(pDevice !=
NULL);
22230 ma_assert(g_maOpenSLInitCounter > 0);
22231 if (g_maOpenSLInitCounter == 0) {
22236 if (pDevice->opensl.pAudioRecorderObj) {
22237 MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioRecorderObj);
22240 ma_free(pDevice->opensl.pBufferCapture);
22244 if (pDevice->opensl.pAudioPlayerObj) {
22245 MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioPlayerObj);
22247 if (pDevice->opensl.pOutputMixObj) {
22248 MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Destroy((SLObjectItf)pDevice->opensl.pOutputMixObj);
22251 ma_free(pDevice->opensl.pBufferPlayback);
22259 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
22260 typedef SLAndroidDataFormat_PCM_EX ma_SLDataFormat_PCM;
22262 typedef SLDataFormat_PCM ma_SLDataFormat_PCM;
22267 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
22269 pDataFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
22270 pDataFormat->representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
22272 pDataFormat->formatType = SL_DATAFORMAT_PCM;
22275 pDataFormat->formatType = SL_DATAFORMAT_PCM;
22278 pDataFormat->numChannels =
channels;
22279 ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = ma_round_to_standard_sample_rate__opensl(sampleRate * 1000);
22281 pDataFormat->channelMask = ma_channel_map_to_channel_mask__opensl(channelMap,
channels);
22282 pDataFormat->endianness = (ma_is_little_endian()) ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
22291 if (pDataFormat->numChannels > 2) {
22292 pDataFormat->numChannels = 2;
22294 #if __ANDROID_API__ >= 21
22295 if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
22297 ma_assert(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
22298 if (pDataFormat->bitsPerSample > 32) {
22299 pDataFormat->bitsPerSample = 32;
22302 if (pDataFormat->bitsPerSample > 16) {
22303 pDataFormat->bitsPerSample = 16;
22307 if (pDataFormat->bitsPerSample > 16) {
22308 pDataFormat->bitsPerSample = 16;
22311 if (((SLDataFormat_PCM*)pDataFormat)->samplesPerSec > SL_SAMPLINGRATE_48) {
22312 ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = SL_SAMPLINGRATE_48;
22316 pDataFormat->containerSize = pDataFormat->bitsPerSample;
22324 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
22325 if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
22326 ma_assert(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
22330 if (isFloatingPoint) {
22331 if (pDataFormat->bitsPerSample == 32) {
22335 if (pDataFormat->bitsPerSample == 8) {
22337 }
else if (pDataFormat->bitsPerSample == 16) {
22339 }
else if (pDataFormat->bitsPerSample == 24) {
22341 }
else if (pDataFormat->bitsPerSample == 32) {
22346 *pChannels = pDataFormat->numChannels;
22347 *pSampleRate = ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec / 1000;
22348 ma_channel_mask_to_channel_map__opensl(pDataFormat->channelMask, pDataFormat->numChannels, pChannelMap);
22356 SLDataLocator_AndroidSimpleBufferQueue queue;
22359 size_t bufferSizeInBytes;
22360 const SLInterfaceID itfIDs1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
22361 const SLboolean itfIDsRequired1[] = {SL_BOOLEAN_TRUE};
22366 ma_assert(g_maOpenSLInitCounter > 0);
22367 if (g_maOpenSLInitCounter == 0) {
22384 ma_assert(pDevice !=
NULL);
22385 ma_zero_object(&pDevice->opensl);
22387 queue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
22388 queue.numBuffers = pConfig->
periods;
22392 ma_SLDataFormat_PCM pcm;
22393 SLDataLocator_IODevice locatorDevice;
22394 SLDataSource source;
22399 locatorDevice.locatorType = SL_DATALOCATOR_IODEVICE;
22400 locatorDevice.deviceType = SL_IODEVICE_AUDIOINPUT;
22402 locatorDevice.device =
NULL;
22404 source.pLocator = &locatorDevice;
22405 source.pFormat =
NULL;
22407 sink.pLocator = &queue;
22408 sink.pFormat = (SLDataFormat_PCM*)&pcm;
22410 resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &source, &sink, 1, itfIDs1, itfIDsRequired1);
22411 if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
22413 pcm.formatType = SL_DATAFORMAT_PCM;
22414 pcm.numChannels = 1;
22415 ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16;
22416 pcm.bitsPerSample = 16;
22417 pcm.containerSize = pcm.bitsPerSample;
22418 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
22419 resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &source, &sink, 1, itfIDs1, itfIDsRequired1);
22422 if (resultSL != SL_RESULT_SUCCESS) {
22423 ma_device_uninit__opensl(pDevice);
22427 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Realize((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
22428 ma_device_uninit__opensl(pDevice);
22432 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_IID_RECORD, &pDevice->opensl.pAudioRecorder) != SL_RESULT_SUCCESS) {
22433 ma_device_uninit__opensl(pDevice);
22437 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueueCapture) != SL_RESULT_SUCCESS) {
22438 ma_device_uninit__opensl(pDevice);
22442 if (MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, ma_buffer_queue_callback_capture__opensl_android, pDevice) != SL_RESULT_SUCCESS) {
22443 ma_device_uninit__opensl(pDevice);
22448 ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDevice->capture.internalFormat, &pDevice->capture.internalChannels, &pDevice->capture.internalSampleRate, pDevice->capture.internalChannelMap);
22452 if (bufferSizeInFrames == 0) {
22455 pDevice->capture.internalPeriods = pConfig->
periods;
22456 pDevice->capture.internalBufferSizeInFrames = (bufferSizeInFrames / pDevice->capture.internalPeriods) * pDevice->capture.internalPeriods;
22457 pDevice->opensl.currentBufferIndexCapture = 0;
22459 bufferSizeInBytes = pDevice->capture.internalBufferSizeInFrames *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22461 if (pDevice->opensl.pBufferCapture ==
NULL) {
22462 ma_device_uninit__opensl(pDevice);
22465 MA_ZERO_MEMORY(pDevice->opensl.pBufferCapture, bufferSizeInBytes);
22469 ma_SLDataFormat_PCM pcm;
22470 SLDataSource source;
22471 SLDataLocator_OutputMix outmixLocator;
22476 resultSL = (*g_maEngineSL)->CreateOutputMix(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pOutputMixObj, 0,
NULL,
NULL);
22477 if (resultSL != SL_RESULT_SUCCESS) {
22478 ma_device_uninit__opensl(pDevice);
22482 if (MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Realize((SLObjectItf)pDevice->opensl.pOutputMixObj, SL_BOOLEAN_FALSE)) {
22483 ma_device_uninit__opensl(pDevice);
22487 if (MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->GetInterface((SLObjectItf)pDevice->opensl.pOutputMixObj, SL_IID_OUTPUTMIX, &pDevice->opensl.pOutputMix) != SL_RESULT_SUCCESS) {
22488 ma_device_uninit__opensl(pDevice);
22495 MA_OPENSL_OUTPUTMIX(pDevice->opensl.pOutputMix)->ReRoute((SLOutputMixItf)pDevice->opensl.pOutputMix, 1, &deviceID_OpenSL);
22498 source.pLocator = &queue;
22499 source.pFormat = (SLDataFormat_PCM*)&pcm;
22501 outmixLocator.locatorType = SL_DATALOCATOR_OUTPUTMIX;
22502 outmixLocator.outputMix = (SLObjectItf)pDevice->opensl.pOutputMixObj;
22504 sink.pLocator = &outmixLocator;
22505 sink.pFormat =
NULL;
22507 resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &source, &sink, 1, itfIDs1, itfIDsRequired1);
22508 if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
22510 pcm.formatType = SL_DATAFORMAT_PCM;
22511 pcm.numChannels = 2;
22512 ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16;
22513 pcm.bitsPerSample = 16;
22514 pcm.containerSize = pcm.bitsPerSample;
22515 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
22516 resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &source, &sink, 1, itfIDs1, itfIDsRequired1);
22519 if (resultSL != SL_RESULT_SUCCESS) {
22520 ma_device_uninit__opensl(pDevice);
22524 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Realize((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
22525 ma_device_uninit__opensl(pDevice);
22529 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_IID_PLAY, &pDevice->opensl.pAudioPlayer) != SL_RESULT_SUCCESS) {
22530 ma_device_uninit__opensl(pDevice);
22534 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueuePlayback) != SL_RESULT_SUCCESS) {
22535 ma_device_uninit__opensl(pDevice);
22539 if (MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, ma_buffer_queue_callback_playback__opensl_android, pDevice) != SL_RESULT_SUCCESS) {
22540 ma_device_uninit__opensl(pDevice);
22545 ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDevice->playback.internalFormat, &pDevice->playback.internalChannels, &pDevice->playback.internalSampleRate, pDevice->playback.internalChannelMap);
22549 if (bufferSizeInFrames == 0) {
22552 pDevice->playback.internalPeriods = pConfig->
periods;
22553 pDevice->playback.internalBufferSizeInFrames = (bufferSizeInFrames / pDevice->playback.internalPeriods) * pDevice->playback.internalPeriods;
22554 pDevice->opensl.currentBufferIndexPlayback = 0;
22556 bufferSizeInBytes = pDevice->playback.internalBufferSizeInFrames *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22558 if (pDevice->opensl.pBufferPlayback ==
NULL) {
22559 ma_device_uninit__opensl(pDevice);
22562 MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, bufferSizeInBytes);
22566 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
22567 ma_result result =
ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames,
NULL, &pDevice->opensl.duplexRB);
22569 ma_device_uninit__opensl(pDevice);
22570 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[OpenSL] Failed to initialize ring buffer.", result);
22583 size_t periodSizeInBytes;
22586 ma_assert(pDevice !=
NULL);
22588 ma_assert(g_maOpenSLInitCounter > 0);
22589 if (g_maOpenSLInitCounter == 0) {
22594 resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_RECORDING);
22595 if (resultSL != SL_RESULT_SUCCESS) {
22599 periodSizeInBytes = (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods) *
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22600 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
22601 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pDevice->opensl.pBufferCapture + (periodSizeInBytes * iPeriod), periodSizeInBytes);
22602 if (resultSL != SL_RESULT_SUCCESS) {
22603 MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
22610 resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_PLAYING);
22611 if (resultSL != SL_RESULT_SUCCESS) {
22617 MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, pDevice->playback.internalBufferSizeInFrames *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
22619 ma_device__read_frames_from_client(pDevice, pDevice->playback.internalBufferSizeInFrames, pDevice->opensl.pBufferPlayback);
22622 periodSizeInBytes = (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods) *
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22623 for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
22624 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pDevice->opensl.pBufferPlayback + (periodSizeInBytes * iPeriod), periodSizeInBytes);
22625 if (resultSL != SL_RESULT_SUCCESS) {
22626 MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
22640 ma_assert(pDevice !=
NULL);
22642 ma_assert(g_maOpenSLInitCounter > 0);
22643 if (g_maOpenSLInitCounter == 0) {
22650 resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
22651 if (resultSL != SL_RESULT_SUCCESS) {
22655 MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture);
22659 resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
22660 if (resultSL != SL_RESULT_SUCCESS) {
22664 MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback);
22668 onStop = pDevice->onStop;
22679 ma_assert(pContext !=
NULL);
22684 if (g_maOpenSLInitCounter > 0) {
22685 if (ma_atomic_decrement_32(&g_maOpenSLInitCounter) == 0) {
22686 (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
22695 ma_assert(pContext !=
NULL);
22700 if (ma_atomic_increment_32(&g_maOpenSLInitCounter) == 1) {
22701 SLresult resultSL = slCreateEngine(&g_maEngineObjectSL, 0,
NULL, 0,
NULL,
NULL);
22702 if (resultSL != SL_RESULT_SUCCESS) {
22703 ma_atomic_decrement_32(&g_maOpenSLInitCounter);
22707 (*g_maEngineObjectSL)->Realize(g_maEngineObjectSL, SL_BOOLEAN_FALSE);
22709 resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, SL_IID_ENGINE, &g_maEngineSL);
22710 if (resultSL != SL_RESULT_SUCCESS) {
22711 (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
22712 ma_atomic_decrement_32(&g_maOpenSLInitCounter);
22719 pContext->
onUninit = ma_context_uninit__opensl;
22721 pContext->
onEnumDevices = ma_context_enumerate_devices__opensl;
22738 #ifdef MA_HAS_WEBAUDIO
22739 #include <emscripten/emscripten.h>
22741 ma_bool32 ma_is_capture_supported__webaudio()
22743 return EM_ASM_INT({
22744 return (navigator.mediaDevices !== undefined && navigator.mediaDevices.getUserMedia !== undefined);
22751 EMSCRIPTEN_KEEPALIVE
void ma_device_process_pcm_frames_capture__webaudio(
ma_device* pDevice,
int frameCount,
float* pFrames)
22754 ma_device__handle_duplex_callback_capture(pDevice, (
ma_uint32)frameCount, pFrames, &pDevice->webaudio.duplexRB);
22756 ma_device__send_frames_to_client(pDevice, (
ma_uint32)frameCount, pFrames);
22760 EMSCRIPTEN_KEEPALIVE
void ma_device_process_pcm_frames_playback__webaudio(
ma_device* pDevice,
int frameCount,
float* pFrames)
22763 ma_device__handle_duplex_callback_playback(pDevice, (
ma_uint32)frameCount, pFrames, &pDevice->webaudio.duplexRB);
22765 ma_device__read_frames_from_client(pDevice, (
ma_uint32)frameCount, pFrames);
22774 ma_assert(pContext !=
NULL);
22775 ma_assert(pID0 !=
NULL);
22776 ma_assert(pID1 !=
NULL);
22779 return ma_strcmp(pID0->webaudio, pID1->webaudio) == 0;
22786 ma_assert(pContext !=
NULL);
22787 ma_assert(callback !=
NULL);
22794 ma_zero_object(&deviceInfo);
22795 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
22801 if (ma_is_capture_supported__webaudio()) {
22803 ma_zero_object(&deviceInfo);
22804 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
22814 ma_assert(pContext !=
NULL);
22826 ma_zero_memory(pDeviceInfo->
id.webaudio,
sizeof(pDeviceInfo->
id.webaudio));
22830 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
22832 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
22845 var temp =
new (window.AudioContext || window.webkitAudioContext)();
22846 var sampleRate = temp.sampleRate;
22868 ma_assert(pDevice !=
NULL);
22871 var
device = miniaudio.get_device_by_index($0);
22874 if (
device.scriptNode !== undefined) {
22875 device.scriptNode.onaudioprocess = function(e) {};
22876 device.scriptNode.disconnect();
22877 device.scriptNode = undefined;
22879 if (
device.streamNode !== undefined) {
22880 device.streamNode.disconnect();
22881 device.streamNode = undefined;
22888 device.webaudio.close();
22889 device.webaudio = undefined;
22892 if (
device.intermediaryBuffer !== undefined) {
22893 Module._free(device.intermediaryBuffer);
22894 device.intermediaryBuffer = undefined;
22895 device.intermediaryBufferView = undefined;
22896 device.intermediaryBufferSizeInBytes = undefined;
22900 miniaudio.untrack_device_by_index($0);
22901 }, deviceIndex, deviceType);
22904 void ma_device_uninit__webaudio(
ma_device* pDevice)
22906 ma_assert(pDevice !=
NULL);
22926 ma_assert(pContext !=
NULL);
22927 ma_assert(pConfig !=
NULL);
22929 ma_assert(pDevice !=
NULL);
22937 if (internalBufferSizeInFrames == 0) {
22942 if (internalBufferSizeInFrames < 256) {
22943 internalBufferSizeInFrames = 256;
22944 }
else if (internalBufferSizeInFrames > 16384) {
22945 internalBufferSizeInFrames = 16384;
22947 internalBufferSizeInFrames = ma_next_power_of_2(internalBufferSizeInFrames);
22951 deviceIndex = EM_ASM_INT({
22953 var sampleRate = $1;
22954 var bufferSize = $2;
22955 var isCapture = $3;
22958 if (typeof(miniaudio) ===
'undefined') {
22965 device.webaudio =
new (window.AudioContext || window.webkitAudioContext)({sampleRate:sampleRate});
22966 device.webaudio.suspend();
22972 device.intermediaryBufferSizeInBytes =
channels * bufferSize * 4;
22973 device.intermediaryBuffer = Module._malloc(
device.intermediaryBufferSizeInBytes);
22974 device.intermediaryBufferView =
new Float32Array(Module.HEAPF32.buffer,
device.intermediaryBuffer,
device.intermediaryBufferSizeInBytes);
22995 device.scriptNode.onaudioprocess =
function(e) {
22996 if (
device.intermediaryBuffer === undefined) {
23001 for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
23002 e.outputBuffer.getChannelData(iChannel).fill(0.0);
23006 var sendSilence =
false;
23007 if (
device.streamNode === undefined) {
23008 sendSilence =
true;
23012 if (e.inputBuffer.numberOfChannels !=
channels) {
23013 console.log(
"Capture: Channel count mismatch. " + e.inputBufer.numberOfChannels +
" != " +
channels +
". Sending silence.");
23014 sendSilence =
true;
23018 var totalFramesProcessed = 0;
23019 while (totalFramesProcessed < e.inputBuffer.length) {
23020 var framesRemaining = e.inputBuffer.length - totalFramesProcessed;
23021 var framesToProcess = framesRemaining;
23022 if (framesToProcess > (
device.intermediaryBufferSizeInBytes/
channels/4)) {
23023 framesToProcess = (
device.intermediaryBufferSizeInBytes/
channels/4);
23028 device.intermediaryBufferView.fill(0.0);
23030 for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
23031 for (var iChannel = 0; iChannel < e.inputBuffer.numberOfChannels; ++iChannel) {
23032 device.intermediaryBufferView[iFrame*
channels + iChannel] = e.inputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame];
23038 ccall(
"ma_device_process_pcm_frames_capture__webaudio",
"undefined", [
"number",
"number",
"number"], [pDevice, framesToProcess,
device.intermediaryBuffer]);
23040 totalFramesProcessed += framesToProcess;
23044 navigator.mediaDevices.getUserMedia({audio:
true, video:
false})
23045 .then(
function(stream) {
23046 device.streamNode =
device.webaudio.createMediaStreamSource(stream);
23048 device.scriptNode.connect(
device.webaudio.destination);
23050 .
catch(
function(
error) {
23052 device.scriptNode.connect(
device.webaudio.destination);
23055 device.scriptNode.onaudioprocess =
function(e) {
23056 if (
device.intermediaryBuffer === undefined) {
23060 var outputSilence =
false;
23063 if (e.outputBuffer.numberOfChannels !=
channels) {
23064 console.log(
"Playback: Channel count mismatch. " + e.outputBufer.numberOfChannels +
" != " +
channels +
". Outputting silence.");
23065 outputSilence =
true;
23070 var totalFramesProcessed = 0;
23071 while (totalFramesProcessed < e.outputBuffer.length) {
23072 var framesRemaining = e.outputBuffer.length - totalFramesProcessed;
23073 var framesToProcess = framesRemaining;
23074 if (framesToProcess > (
device.intermediaryBufferSizeInBytes/
channels/4)) {
23075 framesToProcess = (
device.intermediaryBufferSizeInBytes/
channels/4);
23079 ccall(
"ma_device_process_pcm_frames_playback__webaudio",
"undefined", [
"number",
"number",
"number"], [pDevice, framesToProcess,
device.intermediaryBuffer]);
23082 if (outputSilence) {
23083 for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
23084 e.outputBuffer.getChannelData(iChannel).fill(0.0);
23087 for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
23088 for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
23089 e.outputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame] =
device.intermediaryBufferView[iFrame*
channels + iChannel];
23094 totalFramesProcessed += framesToProcess;
23098 device.scriptNode.connect(
device.webaudio.destination);
23101 return miniaudio.track_device(
device);
23104 if (deviceIndex < 0) {
23109 pDevice->webaudio.indexCapture = deviceIndex;
23113 pDevice->capture.internalSampleRate = EM_ASM_INT({
return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
23114 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
23115 pDevice->capture.internalPeriods = 1;
23117 pDevice->webaudio.indexPlayback = deviceIndex;
23121 pDevice->playback.internalSampleRate = EM_ASM_INT({
return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
23122 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
23123 pDevice->playback.internalPeriods = 1;
23162 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames) * 2;
23163 result =
ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames,
NULL, &pDevice->webaudio.duplexRB);
23180 ma_assert(pDevice !=
NULL);
23184 miniaudio.get_device_by_index($0).webaudio.resume();
23185 }, pDevice->webaudio.indexCapture);
23190 miniaudio.get_device_by_index($0).webaudio.resume();
23191 }, pDevice->webaudio.indexPlayback);
23199 ma_assert(pDevice !=
NULL);
23203 miniaudio.get_device_by_index($0).webaudio.suspend();
23204 }, pDevice->webaudio.indexCapture);
23209 miniaudio.get_device_by_index($0).webaudio.suspend();
23210 }, pDevice->webaudio.indexPlayback);
23223 ma_assert(pContext !=
NULL);
23236 ma_assert(pContext !=
NULL);
23239 resultFromJS = EM_ASM_INT({
23240 if ((window.AudioContext || window.webkitAudioContext) === undefined) {
23244 if (typeof(miniaudio) ===
'undefined') {
23246 miniaudio.devices = [];
23248 miniaudio.track_device =
function(
device) {
23250 for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
23251 if (miniaudio.devices[iDevice] ==
null) {
23252 miniaudio.devices[iDevice] =
device;
23258 miniaudio.devices.push(
device);
23259 return miniaudio.devices.length - 1;
23262 miniaudio.untrack_device_by_index =
function(deviceIndex) {
23264 miniaudio.devices[deviceIndex] =
null;
23267 while (miniaudio.devices.length > 0) {
23268 if (miniaudio.devices[miniaudio.devices.length-1] ==
null) {
23269 miniaudio.devices.pop();
23276 miniaudio.untrack_device =
function(
device) {
23277 for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
23278 if (miniaudio.devices[iDevice] ==
device) {
23279 return miniaudio.untrack_device_by_index(iDevice);
23284 miniaudio.get_device_by_index =
function(deviceIndex) {
23285 return miniaudio.devices[deviceIndex];
23292 if (resultFromJS != 1) {
23299 pContext->
onUninit = ma_context_uninit__webaudio;
23301 pContext->
onEnumDevices = ma_context_enumerate_devices__webaudio;
23326 for (iChannel = 0; iChannel <
channels; ++iChannel) {
23328 for (jChannel = iChannel + 1; jChannel <
channels; ++jChannel) {
23329 if (channelMap[iChannel] == channelMap[jChannel]) {
23342 ma_assert(pDevice !=
NULL);
23345 if (pDevice->capture.usingDefaultFormat) {
23346 pDevice->capture.format = pDevice->capture.internalFormat;
23348 if (pDevice->capture.usingDefaultChannels) {
23349 pDevice->capture.channels = pDevice->capture.internalChannels;
23351 if (pDevice->capture.usingDefaultChannelMap) {
23352 if (pDevice->capture.internalChannels == pDevice->capture.channels) {
23353 ma_channel_map_copy(pDevice->capture.channelMap, pDevice->capture.internalChannelMap, pDevice->capture.channels);
23361 if (pDevice->playback.usingDefaultFormat) {
23362 pDevice->playback.format = pDevice->playback.internalFormat;
23364 if (pDevice->playback.usingDefaultChannels) {
23365 pDevice->playback.channels = pDevice->playback.internalChannels;
23367 if (pDevice->playback.usingDefaultChannelMap) {
23368 if (pDevice->playback.internalChannels == pDevice->playback.channels) {
23369 ma_channel_map_copy(pDevice->playback.channelMap, pDevice->playback.internalChannelMap, pDevice->playback.channels);
23376 if (pDevice->usingDefaultSampleRate) {
23378 pDevice->sampleRate = pDevice->capture.internalSampleRate;
23380 pDevice->sampleRate = pDevice->playback.internalSampleRate;
23390 converterConfig.
formatIn = pDevice->capture.internalFormat;
23391 converterConfig.
channelsIn = pDevice->capture.internalChannels;
23392 converterConfig.
sampleRateIn = pDevice->capture.internalSampleRate;
23394 converterConfig.
formatOut = pDevice->capture.format;
23395 converterConfig.
channelsOut = pDevice->capture.channels;
23398 converterConfig.
onRead = ma_device__pcm_converter__on_read_from_buffer_capture;
23407 converterConfig.
formatIn = pDevice->playback.format;
23408 converterConfig.
channelsIn = pDevice->playback.channels;
23411 converterConfig.
formatOut = pDevice->playback.internalFormat;
23412 converterConfig.
channelsOut = pDevice->playback.internalChannels;
23413 converterConfig.
sampleRateOut = pDevice->playback.internalSampleRate;
23417 converterConfig.
onRead = ma_device__on_read_from_client;
23419 converterConfig.
onRead = ma_device__pcm_converter__on_read_from_buffer_playback;
23422 converterConfig.
onRead = ma_device__pcm_converter__on_read_from_buffer_playback;
23429 ma_thread_result MA_THREADCALL ma_worker_thread(
void* pData)
23432 ma_assert(pDevice !=
NULL);
23435 ma_CoInitializeEx(pDevice->pContext,
NULL, MA_COINIT_VALUE);
23444 ma_device__set_state(pDevice, MA_STATE_STOPPED);
23445 ma_event_signal(&pDevice->stopEvent);
23451 ma_event_wait(&pDevice->wakeupEvent);
23457 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED) {
23466 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STARTING);
23469 ma_device__set_state(pDevice, MA_STATE_STARTED);
23470 ma_event_signal(&pDevice->startEvent);
23472 if (pDevice->pContext->onDeviceMainLoop !=
NULL) {
23473 pDevice->pContext->onDeviceMainLoop(pDevice);
23485 ma_assert(pDevice->capture.internalBufferSizeInFrames >= pDevice->capture.internalPeriods);
23486 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
23488 ma_assert(pDevice->playback.internalBufferSizeInFrames >= pDevice->playback.internalPeriods);
23489 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
23491 ma_assert(pDevice->capture.internalBufferSizeInFrames >= pDevice->capture.internalPeriods);
23492 ma_assert(pDevice->playback.internalBufferSizeInFrames >= pDevice->playback.internalPeriods);
23493 periodSizeInFrames = ma_min(
23494 pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods,
23495 pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods
23505 ma_assert(periodSizeInFrames >= 1);
23506 while (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
23513 ma_uint32 captureDeviceDataCapInFrames =
sizeof(captureDeviceData) /
ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
23515 while (totalFramesProcessed < periodSizeInFrames) {
23517 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
23518 ma_uint32 framesToProcess = framesRemaining;
23519 if (framesToProcess > captureDeviceDataCapInFrames) {
23520 framesToProcess = captureDeviceDataCapInFrames;
23523 result = pDevice->pContext->onDeviceRead(pDevice, captureDeviceData, framesToProcess);
23528 onData = pDevice->onData;
23529 if (onData !=
NULL) {
23530 pDevice->capture._dspFrameCount = framesToProcess;
23531 pDevice->capture._dspFrames = captureDeviceData;
23541 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
23543 if (capturedFramesToProcess == 0) {
23547 onData(pDevice, playbackData, capturedData, capturedFramesToProcess);
23550 pDevice->playback._dspFrameCount = capturedFramesToProcess;
23551 pDevice->playback._dspFrames = playbackData;
23553 ma_uint8 playbackDeviceData[4096];
23555 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) /
ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
23557 if (playbackDeviceFramesCount == 0) {
23561 result = pDevice->pContext->onDeviceWrite(pDevice, playbackDeviceData, playbackDeviceFramesCount);
23566 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
23571 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
23582 totalFramesProcessed += framesToProcess;
23593 while (totalFramesProcessed < periodSizeInFrames) {
23594 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
23595 ma_uint32 framesToProcess = framesRemaining;
23596 if (framesToProcess > bufferSizeInFrames) {
23597 framesToProcess = bufferSizeInFrames;
23601 ma_device__read_frames_from_client(pDevice, framesToProcess,
buffer);
23602 result = pDevice->pContext->onDeviceWrite(pDevice,
buffer, framesToProcess);
23604 result = pDevice->pContext->onDeviceRead(pDevice,
buffer, framesToProcess);
23605 ma_device__send_frames_to_client(pDevice, framesToProcess,
buffer);
23608 totalFramesProcessed += framesToProcess;
23624 if (ma_device__get_state(pDevice) != MA_STATE_UNINITIALIZED) {
23625 if (pDevice->pContext->onDeviceStop) {
23626 pDevice->pContext->onDeviceStop(pDevice);
23631 onStop = pDevice->onStop;
23641 if (ma_device__get_state(pDevice) != MA_STATE_UNINITIALIZED) {
23642 ma_device__set_state(pDevice, MA_STATE_STOPPED);
23643 ma_event_signal(&pDevice->stopEvent);
23648 ma_event_signal(&pDevice->stopEvent);
23651 ma_CoUninitialize(pDevice->pContext);
23654 return (ma_thread_result)0;
23661 if (pDevice ==
NULL) {
23665 return ma_device__get_state(pDevice) != MA_STATE_UNINITIALIZED;
23672 ma_CoUninitialize(pContext);
23673 ma_dlclose(pContext, pContext->
win32.hUser32DLL);
23674 ma_dlclose(pContext, pContext->
win32.hOle32DLL);
23675 ma_dlclose(pContext, pContext->
win32.hAdvapi32DLL);
23682 #ifdef MA_WIN32_DESKTOP
23684 pContext->
win32.hOle32DLL = ma_dlopen(pContext,
"ole32.dll");
23685 if (pContext->
win32.hOle32DLL ==
NULL) {
23689 pContext->
win32.CoInitializeEx = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hOle32DLL,
"CoInitializeEx");
23690 pContext->
win32.CoUninitialize = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hOle32DLL,
"CoUninitialize");
23691 pContext->
win32.CoCreateInstance = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hOle32DLL,
"CoCreateInstance");
23692 pContext->
win32.CoTaskMemFree = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hOle32DLL,
"CoTaskMemFree");
23693 pContext->
win32.PropVariantClear = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hOle32DLL,
"PropVariantClear");
23694 pContext->
win32.StringFromGUID2 = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hOle32DLL,
"StringFromGUID2");
23698 pContext->
win32.hUser32DLL = ma_dlopen(pContext,
"user32.dll");
23699 if (pContext->
win32.hUser32DLL ==
NULL) {
23703 pContext->
win32.GetForegroundWindow = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hUser32DLL,
"GetForegroundWindow");
23704 pContext->
win32.GetDesktopWindow = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hUser32DLL,
"GetDesktopWindow");
23708 pContext->
win32.hAdvapi32DLL = ma_dlopen(pContext,
"advapi32.dll");
23709 if (pContext->
win32.hAdvapi32DLL ==
NULL) {
23713 pContext->
win32.RegOpenKeyExA = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hAdvapi32DLL,
"RegOpenKeyExA");
23714 pContext->
win32.RegCloseKey = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hAdvapi32DLL,
"RegCloseKey");
23715 pContext->
win32.RegQueryValueExA = (
ma_proc)ma_dlsym(pContext, pContext->
win32.hAdvapi32DLL,
"RegQueryValueExA");
23718 ma_CoInitializeEx(pContext,
NULL, MA_COINIT_VALUE);
23724 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
23725 ma_dlclose(pContext, pContext->posix.pthreadSO);
23736 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
23737 const char* libpthreadFileNames[] = {
23744 for (
i = 0;
i <
sizeof(libpthreadFileNames) /
sizeof(libpthreadFileNames[0]); ++
i) {
23745 pContext->posix.pthreadSO = ma_dlopen(pContext, libpthreadFileNames[
i]);
23746 if (pContext->posix.pthreadSO !=
NULL) {
23751 if (pContext->posix.pthreadSO ==
NULL) {
23755 pContext->posix.pthread_create = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_create");
23756 pContext->posix.pthread_join = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_join");
23757 pContext->posix.pthread_mutex_init = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_mutex_init");
23758 pContext->posix.pthread_mutex_destroy = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_mutex_destroy");
23759 pContext->posix.pthread_mutex_lock = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_mutex_lock");
23760 pContext->posix.pthread_mutex_unlock = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_mutex_unlock");
23761 pContext->posix.pthread_cond_init = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_cond_init");
23762 pContext->posix.pthread_cond_destroy = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_cond_destroy");
23763 pContext->posix.pthread_cond_wait = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_cond_wait");
23764 pContext->posix.pthread_cond_signal = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_cond_signal");
23765 pContext->posix.pthread_attr_init = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_attr_init");
23766 pContext->posix.pthread_attr_destroy = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_attr_destroy");
23767 pContext->posix.pthread_attr_setschedpolicy = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_attr_setschedpolicy");
23768 pContext->posix.pthread_attr_getschedparam = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_attr_getschedparam");
23769 pContext->posix.pthread_attr_setschedparam = (
ma_proc)ma_dlsym(pContext, pContext->posix.pthreadSO,
"pthread_attr_setschedparam");
23771 pContext->posix.pthread_create = (
ma_proc)pthread_create;
23772 pContext->posix.pthread_join = (
ma_proc)pthread_join;
23773 pContext->posix.pthread_mutex_init = (
ma_proc)pthread_mutex_init;
23774 pContext->posix.pthread_mutex_destroy = (
ma_proc)pthread_mutex_destroy;
23775 pContext->posix.pthread_mutex_lock = (
ma_proc)pthread_mutex_lock;
23776 pContext->posix.pthread_mutex_unlock = (
ma_proc)pthread_mutex_unlock;
23777 pContext->posix.pthread_cond_init = (
ma_proc)pthread_cond_init;
23778 pContext->posix.pthread_cond_destroy = (
ma_proc)pthread_cond_destroy;
23779 pContext->posix.pthread_cond_wait = (
ma_proc)pthread_cond_wait;
23780 pContext->posix.pthread_cond_signal = (
ma_proc)pthread_cond_signal;
23781 pContext->posix.pthread_attr_init = (
ma_proc)pthread_attr_init;
23782 pContext->posix.pthread_attr_destroy = (
ma_proc)pthread_attr_destroy;
23783 #if !defined(__EMSCRIPTEN__)
23784 pContext->posix.pthread_attr_setschedpolicy = (
ma_proc)pthread_attr_setschedpolicy;
23785 pContext->posix.pthread_attr_getschedparam = (
ma_proc)pthread_attr_getschedparam;
23786 pContext->posix.pthread_attr_setschedparam = (
ma_proc)pthread_attr_setschedparam;
23798 result = ma_context_init_backend_apis__win32(pContext);
23800 result = ma_context_init_backend_apis__nix(pContext);
23810 result = ma_context_uninit_backend_apis__win32(pContext);
23812 result = ma_context_uninit_backend_apis__nix(pContext);
23833 if (pContext ==
NULL) {
23837 ma_zero_object(pContext);
23840 if (pConfig !=
NULL) {
23851 result = ma_context_init_backend_apis(pContext);
23857 defaultBackends[iBackend] = (
ma_backend)iBackend;
23861 backendsToIterateCount = backendCount;
23862 if (pBackendsToIterate ==
NULL) {
23863 pBackendsToIterate = (
ma_backend*)defaultBackends;
23864 backendsToIterateCount = ma_countof(defaultBackends);
23867 ma_assert(pBackendsToIterate !=
NULL);
23869 for (iBackend = 0; iBackend < backendsToIterateCount; ++iBackend) {
23870 ma_backend backend = pBackendsToIterate[iBackend];
23874 #ifdef MA_HAS_WASAPI
23877 result = ma_context_init__wasapi(&config, pContext);
23880 #ifdef MA_HAS_DSOUND
23883 result = ma_context_init__dsound(&config, pContext);
23886 #ifdef MA_HAS_WINMM
23889 result = ma_context_init__winmm(&config, pContext);
23895 result = ma_context_init__alsa(&config, pContext);
23898 #ifdef MA_HAS_PULSEAUDIO
23901 result = ma_context_init__pulse(&config, pContext);
23907 result = ma_context_init__jack(&config, pContext);
23910 #ifdef MA_HAS_COREAUDIO
23913 result = ma_context_init__coreaudio(&config, pContext);
23916 #ifdef MA_HAS_SNDIO
23919 result = ma_context_init__sndio(&config, pContext);
23922 #ifdef MA_HAS_AUDIO4
23925 result = ma_context_init__audio4(&config, pContext);
23931 result = ma_context_init__oss(&config, pContext);
23934 #ifdef MA_HAS_AAUDIO
23937 result = ma_context_init__aaudio(&config, pContext);
23940 #ifdef MA_HAS_OPENSL
23943 result = ma_context_init__opensl(&config, pContext);
23946 #ifdef MA_HAS_WEBAUDIO
23949 result = ma_context_init__webaudio(&config, pContext);
23955 result = ma_context_init__null(&config, pContext);
23973 #ifdef MA_DEBUG_OUTPUT
23974 printf(
"[miniaudio] Endian: %s\n", ma_is_little_endian() ?
"LE" :
"BE");
23975 printf(
"[miniaudio] SSE2: %s\n", ma_has_sse2() ?
"YES" :
"NO");
23976 printf(
"[miniaudio] AVX2: %s\n", ma_has_avx2() ?
"YES" :
"NO");
23977 printf(
"[miniaudio] AVX512F: %s\n", ma_has_avx512f() ?
"YES" :
"NO");
23978 printf(
"[miniaudio] NEON: %s\n", ma_has_neon() ?
"YES" :
"NO");
23987 ma_zero_object(pContext);
23993 if (pContext ==
NULL) {
24002 ma_context_uninit_backend_apis(pContext);
24018 result = pContext->
onEnumDevices(pContext, callback, pUserData);
24037 const ma_uint32 bufferExpansionCount = 2;
24041 ma_uint32 newCapacity = totalDeviceInfoCount + bufferExpansionCount;
24043 if (pNewInfos ==
NULL) {
24056 size_t iCaptureDevice;
24057 for (iCaptureDevice = totalDeviceInfoCount; iCaptureDevice > iFirstCaptureDevice; --iCaptureDevice) {
24066 pContext->
pDeviceInfos[totalDeviceInfoCount] = *pInfo;
24079 if (ppPlaybackDeviceInfos !=
NULL) *ppPlaybackDeviceInfos =
NULL;
24080 if (pPlaybackDeviceCount !=
NULL) *pPlaybackDeviceCount = 0;
24081 if (ppCaptureDeviceInfos !=
NULL) *ppCaptureDeviceInfos =
NULL;
24082 if (pCaptureDeviceCount !=
NULL) *pCaptureDeviceCount = 0;
24096 result = pContext->
onEnumDevices(pContext, ma_context_get_devices__enum_callback,
NULL);
24099 if (ppPlaybackDeviceInfos !=
NULL) {
24102 if (pPlaybackDeviceCount !=
NULL) {
24107 if (ppCaptureDeviceInfos !=
NULL) {
24110 if (pCaptureDeviceCount !=
NULL) {
24125 if (pContext ==
NULL || pDeviceInfo ==
NULL) {
24129 ma_zero_object(&deviceInfo);
24132 if (pDeviceID !=
NULL) {
24133 ma_copy_memory(&deviceInfo.
id, pDeviceID,
sizeof(*pDeviceID));
24141 result = pContext->
onGetDeviceInfo(pContext, deviceType, pDeviceID, shareMode, &deviceInfo);
24151 *pDeviceInfo = deviceInfo;
24165 if (pContext ==
NULL) {
24168 if (pDevice ==
NULL) {
24171 if (pConfig ==
NULL) {
24180 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"ma_device_init() called with an invalid config. Device type is invalid. Make sure the device type has been set in the config.",
MA_INVALID_DEVICE_CONFIG);
24202 ma_zero_object(pDevice);
24203 pDevice->pContext = pContext;
24210 if (((
ma_uintptr)pDevice %
sizeof(pDevice)) != 0) {
24212 pContext->
logCallback(pContext, pDevice,
MA_LOG_LEVEL_WARNING,
"WARNING: ma_device_init() called for a device that is not properly aligned. Thread safety is not supported.");
24222 pDevice->usingDefaultSampleRate =
MA_TRUE;
24227 pDevice->capture.usingDefaultFormat =
MA_TRUE;
24231 pDevice->capture.usingDefaultChannels =
MA_TRUE;
24234 pDevice->capture.usingDefaultChannelMap =
MA_TRUE;
24239 pDevice->playback.usingDefaultFormat =
MA_TRUE;
24243 pDevice->playback.usingDefaultChannels =
MA_TRUE;
24246 pDevice->playback.usingDefaultChannelMap =
MA_TRUE;
24253 pDevice->usingDefaultBufferSize =
MA_TRUE;
24258 config.
periods = MA_DEFAULT_PERIODS;
24259 pDevice->usingDefaultPeriods =
MA_TRUE;
24286 pDevice->capture.internalFormat = pDevice->capture.format;
24287 pDevice->capture.internalChannels = pDevice->capture.channels;
24288 pDevice->capture.internalSampleRate = pDevice->sampleRate;
24289 ma_channel_map_copy(pDevice->capture.internalChannelMap, pDevice->capture.channelMap, pDevice->capture.channels);
24291 pDevice->playback.internalFormat = pDevice->playback.format;
24292 pDevice->playback.internalChannels = pDevice->playback.channels;
24293 pDevice->playback.internalSampleRate = pDevice->sampleRate;
24294 ma_channel_map_copy(pDevice->playback.internalChannelMap, pDevice->playback.channelMap, pDevice->playback.channels);
24308 if (ma_event_init(pContext, &pDevice->wakeupEvent) !=
MA_SUCCESS) {
24312 if (ma_event_init(pContext, &pDevice->startEvent) !=
MA_SUCCESS) {
24313 ma_event_uninit(&pDevice->wakeupEvent);
24317 if (ma_event_init(pContext, &pDevice->stopEvent) !=
MA_SUCCESS) {
24318 ma_event_uninit(&pDevice->startEvent);
24319 ma_event_uninit(&pDevice->wakeupEvent);
24325 result = pContext->
onDeviceInit(pContext, &config, pDevice);
24330 ma_device__post_init_setup(pDevice, pConfig->
deviceType);
24335 if (pDevice->capture.name[0] ==
'\0') {
24337 ma_strncpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name), (config.
capture.
pDeviceID ==
NULL) ? MA_DEFAULT_CAPTURE_DEVICE_NAME :
"Capture Device", (
size_t)-1);
24342 if (pDevice->playback.name[0] ==
'\0') {
24344 ma_strncpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name), (config.
playback.
pDeviceID ==
NULL) ? MA_DEFAULT_PLAYBACK_DEVICE_NAME :
"Playback Device", (
size_t)-1);
24351 if (!ma_context_is_backend_asynchronous(pContext)) {
24353 if (ma_thread_create(pContext, &pDevice->thread, ma_worker_thread, pDevice) !=
MA_SUCCESS) {
24359 ma_event_wait(&pDevice->stopEvent);
24361 ma_device__set_state(pDevice, MA_STATE_STOPPED);
24365 #ifdef MA_DEBUG_OUTPUT
24368 printf(
" %s (%s)\n", pDevice->capture.name,
"Capture");
24370 printf(
" Channels: %d -> %d\n", pDevice->capture.channels, pDevice->capture.internalChannels);
24371 printf(
" Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->capture.internalSampleRate);
24372 printf(
" Buffer Size: %d/%d (%d)\n", pDevice->capture.internalBufferSizeInFrames, pDevice->capture.internalPeriods, (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods));
24373 printf(
" Conversion:\n");
24374 printf(
" Pre Format Conversion: %s\n", pDevice->capture.converter.isPreFormatConversionRequired ?
"YES" :
"NO");
24375 printf(
" Post Format Conversion: %s\n", pDevice->capture.converter.isPostFormatConversionRequired ?
"YES" :
"NO");
24376 printf(
" Channel Routing: %s\n", pDevice->capture.converter.isChannelRoutingRequired ?
"YES" :
"NO");
24377 printf(
" SRC: %s\n", pDevice->capture.converter.isSRCRequired ?
"YES" :
"NO");
24378 printf(
" Channel Routing at Start: %s\n", pDevice->capture.converter.isChannelRoutingAtStart ?
"YES" :
"NO");
24379 printf(
" Passthrough: %s\n", pDevice->capture.converter.isPassthrough ?
"YES" :
"NO");
24382 printf(
" %s (%s)\n", pDevice->playback.name,
"Playback");
24384 printf(
" Channels: %d -> %d\n", pDevice->playback.channels, pDevice->playback.internalChannels);
24385 printf(
" Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->playback.internalSampleRate);
24386 printf(
" Buffer Size: %d/%d (%d)\n", pDevice->playback.internalBufferSizeInFrames, pDevice->playback.internalPeriods, (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods));
24387 printf(
" Conversion:\n");
24388 printf(
" Pre Format Conversion: %s\n", pDevice->playback.converter.isPreFormatConversionRequired ?
"YES" :
"NO");
24389 printf(
" Post Format Conversion: %s\n", pDevice->playback.converter.isPostFormatConversionRequired ?
"YES" :
"NO");
24390 printf(
" Channel Routing: %s\n", pDevice->playback.converter.isChannelRoutingRequired ?
"YES" :
"NO");
24391 printf(
" SRC: %s\n", pDevice->playback.converter.isSRCRequired ?
"YES" :
"NO");
24392 printf(
" Channel Routing at Start: %s\n", pDevice->playback.converter.isChannelRoutingAtStart ?
"YES" :
"NO");
24393 printf(
" Passthrough: %s\n", pDevice->playback.converter.isPassthrough ?
"YES" :
"NO");
24398 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STOPPED);
24411 if (pConfig ==
NULL) {
24416 if (pContext ==
NULL) {
24421 defaultBackends[iBackend] = (
ma_backend)iBackend;
24425 backendsToIterateCount = backendCount;
24426 if (pBackendsToIterate ==
NULL) {
24427 pBackendsToIterate = (
ma_backend*)defaultBackends;
24428 backendsToIterateCount = ma_countof(defaultBackends);
24433 for (iBackend = 0; iBackend < backendsToIterateCount; ++iBackend) {
24434 result =
ma_context_init(&pBackendsToIterate[iBackend], 1, pContextConfig, pContext);
24450 pDevice->isOwnerOfContext =
MA_TRUE;
24456 if (!ma_device__is_initialized(pDevice)) {
24466 ma_device__set_state(pDevice, MA_STATE_UNINITIALIZED);
24469 if (!ma_context_is_backend_asynchronous(pDevice->pContext)) {
24470 ma_event_signal(&pDevice->wakeupEvent);
24471 ma_thread_wait(&pDevice->thread);
24474 pDevice->pContext->onDeviceUninit(pDevice);
24476 ma_event_uninit(&pDevice->stopEvent);
24477 ma_event_uninit(&pDevice->startEvent);
24478 ma_event_uninit(&pDevice->wakeupEvent);
24481 if (pDevice->isOwnerOfContext) {
24486 ma_zero_object(pDevice);
24491 if (pDevice ==
NULL) {
24495 ma_atomic_exchange_ptr(&pDevice->onStop, proc);
24502 if (pDevice ==
NULL) {
24506 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED) {
24515 if (!ma_device__is_async(pDevice)) {
24523 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STOPPED);
24525 ma_device__set_state(pDevice, MA_STATE_STARTING);
24528 if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
24529 result = pDevice->pContext->onDeviceStart(pDevice);
24531 ma_device__set_state(pDevice, MA_STATE_STARTED);
24538 ma_event_signal(&pDevice->wakeupEvent);
24544 ma_event_wait(&pDevice->startEvent);
24545 result = pDevice->workResult;
24557 if (pDevice ==
NULL) {
24561 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED) {
24569 if (!ma_device__is_async(pDevice)) {
24570 if (pDevice->pContext->onDeviceStop) {
24571 return pDevice->pContext->onDeviceStop(pDevice);
24579 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STARTED);
24581 ma_device__set_state(pDevice, MA_STATE_STOPPING);
24586 if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
24587 if (pDevice->pContext->onDeviceStop) {
24588 result = pDevice->pContext->onDeviceStop(pDevice);
24593 ma_device__set_state(pDevice, MA_STATE_STOPPED);
24601 ma_event_wait(&pDevice->stopEvent);
24612 if (pDevice ==
NULL) {
24616 return ma_device__get_state(pDevice) == MA_STATE_STARTED;
24623 ma_zero_object(&config);
24631 ma_zero_object(&config);
24664 #ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
25186 switch (standardChannelMap)
25190 ma_get_standard_channel_map_alsa(
channels, channelMap);
25195 ma_get_standard_channel_map_rfc3551(
channels, channelMap);
25200 ma_get_standard_channel_map_flac(
channels, channelMap);
25205 ma_get_standard_channel_map_vorbis(
channels, channelMap);
25210 ma_get_standard_channel_map_sound4(
channels, channelMap);
25215 ma_get_standard_channel_map_sndio(
channels, channelMap);
25221 ma_get_standard_channel_map_microsoft(
channels, channelMap);
25229 ma_copy_memory(pOut, pIn,
sizeof(*pOut) *
channels);
25235 if (channelMap ==
NULL) {
25247 for (iChannel = 0; iChannel <
channels; ++iChannel) {
25261 if (channelMapA == channelMapB) {
25269 for (iChannel = 0; iChannel <
channels; ++iChannel) {
25270 if (channelMapA[iChannel] != channelMapB[iChannel]) {
25282 for (iChannel = 0; iChannel <
channels; ++iChannel) {
25294 for (iChannel = 0; iChannel <
channels; ++iChannel) {
25295 if (channelMap[iChannel] == channelPosition) {
25311 void ma_copy_memory_64(
void* dst,
const void* src,
ma_uint64 sizeInBytes)
25313 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
25314 ma_copy_memory(dst, src, (
size_t)sizeInBytes);
25316 while (sizeInBytes > 0) {
25317 ma_uint64 bytesToCopyNow = sizeInBytes;
25322 ma_copy_memory(dst, src, (
size_t)bytesToCopyNow);
25324 sizeInBytes -= bytesToCopyNow;
25325 dst = (
void*)((
ma_uint8*)dst + bytesToCopyNow);
25326 src = (
const void*)((
const ma_uint8*)src + bytesToCopyNow);
25331 void ma_zero_memory_64(
void* dst,
ma_uint64 sizeInBytes)
25333 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
25334 ma_zero_memory(dst, (
size_t)sizeInBytes);
25336 while (sizeInBytes > 0) {
25337 ma_uint64 bytesToZeroNow = sizeInBytes;
25342 ma_zero_memory(dst, (
size_t)bytesToZeroNow);
25344 sizeInBytes -= bytesToZeroNow;
25345 dst = (
void*)((
ma_uint8*)dst + bytesToZeroNow);
25377 ma_pcm_u8_to_s16__reference(dst, src,
count, ditherMode);
25380 #if defined(MA_SUPPORT_SSE2)
25383 ma_pcm_u8_to_s16__optimized(dst, src,
count, ditherMode);
25386 #if defined(MA_SUPPORT_AVX2)
25389 ma_pcm_u8_to_s16__optimized(dst, src,
count, ditherMode);
25392 #if defined(MA_SUPPORT_AVX512)
25395 ma_pcm_u8_to_s16__avx2(dst, src,
count, ditherMode);
25398 #if defined(MA_SUPPORT_NEON)
25401 ma_pcm_u8_to_s16__optimized(dst, src,
count, ditherMode);
25407 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25408 ma_pcm_u8_to_s16__reference(dst, src,
count, ditherMode);
25410 ma_pcm_u8_to_s16__optimized(dst, src,
count, ditherMode);
25425 dst_s24[
i*3+0] = 0;
25426 dst_s24[
i*3+1] = 0;
25435 ma_pcm_u8_to_s24__reference(dst, src,
count, ditherMode);
25438 #if defined(MA_SUPPORT_SSE2)
25441 ma_pcm_u8_to_s24__optimized(dst, src,
count, ditherMode);
25444 #if defined(MA_SUPPORT_AVX2)
25447 ma_pcm_u8_to_s24__optimized(dst, src,
count, ditherMode);
25450 #if defined(MA_SUPPORT_AVX512)
25453 ma_pcm_u8_to_s24__avx2(dst, src,
count, ditherMode);
25456 #if defined(MA_SUPPORT_NEON)
25459 ma_pcm_u8_to_s24__optimized(dst, src,
count, ditherMode);
25465 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25466 ma_pcm_u8_to_s24__reference(dst, src,
count, ditherMode);
25468 ma_pcm_u8_to_s24__optimized(dst, src,
count, ditherMode);
25491 ma_pcm_u8_to_s32__reference(dst, src,
count, ditherMode);
25494 #if defined(MA_SUPPORT_SSE2)
25497 ma_pcm_u8_to_s32__optimized(dst, src,
count, ditherMode);
25500 #if defined(MA_SUPPORT_AVX2)
25503 ma_pcm_u8_to_s32__optimized(dst, src,
count, ditherMode);
25506 #if defined(MA_SUPPORT_AVX512)
25509 ma_pcm_u8_to_s32__avx2(dst, src,
count, ditherMode);
25512 #if defined(MA_SUPPORT_NEON)
25515 ma_pcm_u8_to_s32__optimized(dst, src,
count, ditherMode);
25521 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25522 ma_pcm_u8_to_s32__reference(dst, src,
count, ditherMode);
25524 ma_pcm_u8_to_s32__optimized(dst, src,
count, ditherMode);
25531 float* dst_f32 = (
float*)dst;
25536 float x = (float)src_u8[
i];
25537 x =
x * 0.00784313725490196078f;
25548 ma_pcm_u8_to_f32__reference(dst, src,
count, ditherMode);
25551 #if defined(MA_SUPPORT_SSE2)
25554 ma_pcm_u8_to_f32__optimized(dst, src,
count, ditherMode);
25557 #if defined(MA_SUPPORT_AVX2)
25560 ma_pcm_u8_to_f32__optimized(dst, src,
count, ditherMode);
25563 #if defined(MA_SUPPORT_AVX512)
25566 ma_pcm_u8_to_f32__avx2(dst, src,
count, ditherMode);
25569 #if defined(MA_SUPPORT_NEON)
25572 ma_pcm_u8_to_f32__optimized(dst, src,
count, ditherMode);
25578 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25579 ma_pcm_u8_to_f32__reference(dst, src,
count, ditherMode);
25581 ma_pcm_u8_to_f32__optimized(dst, src,
count, ditherMode);
25593 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
25595 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
25596 dst_u8[iFrame*
channels + iChannel] = src_u8[iChannel][iFrame];
25607 ma_copy_memory_64(dst, src[0], frameCount *
sizeof(
ma_uint8));
25610 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
25611 dst_u8[iFrame*2 + 0] = src_u8[0][iFrame];
25612 dst_u8[iFrame*2 + 1] = src_u8[1][iFrame];
25616 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
25618 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
25619 dst_u8[iFrame*
channels + iChannel] = src_u8[iChannel][iFrame];
25627 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25628 ma_pcm_interleave_u8__reference(dst, src, frameCount,
channels);
25630 ma_pcm_interleave_u8__optimized(dst, src, frameCount,
channels);
25641 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
25643 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
25644 dst_u8[iChannel][iFrame] = src_u8[iFrame*
channels + iChannel];
25651 ma_pcm_deinterleave_u8__reference(dst, src, frameCount,
channels);
25656 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25657 ma_pcm_deinterleave_u8__reference(dst, src, frameCount,
channels);
25659 ma_pcm_deinterleave_u8__optimized(dst, src, frameCount,
channels);
25684 ma_int32 dither = ma_dither_s32(ditherMode, -0x80, 0x7F);
25685 if ((
x + dither) <= 0x7FFF) {
25700 ma_pcm_s16_to_u8__reference(dst, src,
count, ditherMode);
25703 #if defined(MA_SUPPORT_SSE2)
25706 ma_pcm_s16_to_u8__optimized(dst, src,
count, ditherMode);
25709 #if defined(MA_SUPPORT_AVX2)
25712 ma_pcm_s16_to_u8__optimized(dst, src,
count, ditherMode);
25715 #if defined(MA_SUPPORT_AVX512)
25718 ma_pcm_s16_to_u8__avx2(dst, src,
count, ditherMode);
25721 #if defined(MA_SUPPORT_NEON)
25724 ma_pcm_s16_to_u8__optimized(dst, src,
count, ditherMode);
25730 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25731 ma_pcm_s16_to_u8__reference(dst, src,
count, ditherMode);
25733 ma_pcm_s16_to_u8__optimized(dst, src,
count, ditherMode);
25752 dst_s24[
i*3+0] = 0;
25753 dst_s24[
i*3+1] = (
ma_uint8)(src_s16[
i] & 0xFF);
25754 dst_s24[
i*3+2] = (
ma_uint8)(src_s16[
i] >> 8);
25762 ma_pcm_s16_to_s24__reference(dst, src,
count, ditherMode);
25765 #if defined(MA_SUPPORT_SSE2)
25768 ma_pcm_s16_to_s24__optimized(dst, src,
count, ditherMode);
25771 #if defined(MA_SUPPORT_AVX2)
25774 ma_pcm_s16_to_s24__optimized(dst, src,
count, ditherMode);
25777 #if defined(MA_SUPPORT_AVX512)
25780 ma_pcm_s16_to_s24__avx2(dst, src,
count, ditherMode);
25783 #if defined(MA_SUPPORT_NEON)
25786 ma_pcm_s16_to_s24__optimized(dst, src,
count, ditherMode);
25792 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25793 ma_pcm_s16_to_s24__reference(dst, src,
count, ditherMode);
25795 ma_pcm_s16_to_s24__optimized(dst, src,
count, ditherMode);
25807 dst_s32[
i] = src_s16[
i] << 16;
25815 ma_pcm_s16_to_s32__reference(dst, src,
count, ditherMode);
25818 #if defined(MA_SUPPORT_SSE2)
25821 ma_pcm_s16_to_s32__optimized(dst, src,
count, ditherMode);
25824 #if defined(MA_SUPPORT_AVX2)
25827 ma_pcm_s16_to_s32__optimized(dst, src,
count, ditherMode);
25830 #if defined(MA_SUPPORT_AVX512)
25833 ma_pcm_s16_to_s32__avx2(dst, src,
count, ditherMode);
25836 #if defined(MA_SUPPORT_NEON)
25839 ma_pcm_s16_to_s32__optimized(dst, src,
count, ditherMode);
25845 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25846 ma_pcm_s16_to_s32__reference(dst, src,
count, ditherMode);
25848 ma_pcm_s16_to_s32__optimized(dst, src,
count, ditherMode);
25855 float* dst_f32 = (
float*)dst;
25860 float x = (float)src_s16[
i];
25865 x =
x * 0.00003051804379339284f;
25869 x =
x * 0.000030517578125f;
25880 ma_pcm_s16_to_f32__reference(dst, src,
count, ditherMode);
25883 #if defined(MA_SUPPORT_SSE2)
25886 ma_pcm_s16_to_f32__optimized(dst, src,
count, ditherMode);
25889 #if defined(MA_SUPPORT_AVX2)
25892 ma_pcm_s16_to_f32__optimized(dst, src,
count, ditherMode);
25895 #if defined(MA_SUPPORT_AVX512)
25898 ma_pcm_s16_to_f32__avx2(dst, src,
count, ditherMode);
25901 #if defined(MA_SUPPORT_NEON)
25904 ma_pcm_s16_to_f32__optimized(dst, src,
count, ditherMode);
25910 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25911 ma_pcm_s16_to_f32__reference(dst, src,
count, ditherMode);
25913 ma_pcm_s16_to_f32__optimized(dst, src,
count, ditherMode);
25924 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
25926 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
25927 dst_s16[iFrame*
channels + iChannel] = src_s16[iChannel][iFrame];
25934 ma_pcm_interleave_s16__reference(dst, src, frameCount,
channels);
25939 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25940 ma_pcm_interleave_s16__reference(dst, src, frameCount,
channels);
25942 ma_pcm_interleave_s16__optimized(dst, src, frameCount,
channels);
25953 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
25955 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
25956 dst_s16[iChannel][iFrame] = src_s16[iFrame*
channels + iChannel];
25963 ma_pcm_deinterleave_s16__reference(dst, src, frameCount,
channels);
25968 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
25969 ma_pcm_deinterleave_s16__reference(dst, src, frameCount,
channels);
25971 ma_pcm_deinterleave_s16__optimized(dst, src, frameCount,
channels);
25994 ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
25995 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
26010 ma_pcm_s24_to_u8__reference(dst, src,
count, ditherMode);
26013 #if defined(MA_SUPPORT_SSE2)
26016 ma_pcm_s24_to_u8__optimized(dst, src,
count, ditherMode);
26019 #if defined(MA_SUPPORT_AVX2)
26022 ma_pcm_s24_to_u8__optimized(dst, src,
count, ditherMode);
26025 #if defined(MA_SUPPORT_AVX512)
26028 ma_pcm_s24_to_u8__avx2(dst, src,
count, ditherMode);
26031 #if defined(MA_SUPPORT_NEON)
26034 ma_pcm_s24_to_u8__optimized(dst, src,
count, ditherMode);
26040 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26041 ma_pcm_s24_to_u8__reference(dst, src,
count, ditherMode);
26043 ma_pcm_s24_to_u8__optimized(dst, src,
count, ditherMode);
26058 dst_s16[
i] = (
ma_int16)dst_lo | dst_hi;
26066 ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
26067 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
26081 ma_pcm_s24_to_s16__reference(dst, src,
count, ditherMode);
26084 #if defined(MA_SUPPORT_SSE2)
26087 ma_pcm_s24_to_s16__optimized(dst, src,
count, ditherMode);
26090 #if defined(MA_SUPPORT_AVX2)
26093 ma_pcm_s24_to_s16__optimized(dst, src,
count, ditherMode);
26096 #if defined(MA_SUPPORT_AVX512)
26099 ma_pcm_s24_to_s16__avx2(dst, src,
count, ditherMode);
26102 #if defined(MA_SUPPORT_NEON)
26105 ma_pcm_s24_to_s16__optimized(dst, src,
count, ditherMode);
26111 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26112 ma_pcm_s24_to_s16__reference(dst, src,
count, ditherMode);
26114 ma_pcm_s24_to_s16__optimized(dst, src,
count, ditherMode);
26123 ma_copy_memory_64(dst, src,
count * 3);
26142 ma_pcm_s24_to_s32__reference(dst, src,
count, ditherMode);
26145 #if defined(MA_SUPPORT_SSE2)
26148 ma_pcm_s24_to_s32__optimized(dst, src,
count, ditherMode);
26151 #if defined(MA_SUPPORT_AVX2)
26154 ma_pcm_s24_to_s32__optimized(dst, src,
count, ditherMode);
26157 #if defined(MA_SUPPORT_AVX512)
26160 ma_pcm_s24_to_s32__avx2(dst, src,
count, ditherMode);
26163 #if defined(MA_SUPPORT_NEON)
26166 ma_pcm_s24_to_s32__optimized(dst, src,
count, ditherMode);
26172 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26173 ma_pcm_s24_to_s32__reference(dst, src,
count, ditherMode);
26175 ma_pcm_s24_to_s32__optimized(dst, src,
count, ditherMode);
26182 float* dst_f32 = (
float*)dst;
26191 x =
x + 8388608.0f;
26192 x =
x * 0.00000011920929665621f;
26196 x =
x * 0.00000011920928955078125f;
26207 ma_pcm_s24_to_f32__reference(dst, src,
count, ditherMode);
26210 #if defined(MA_SUPPORT_SSE2)
26213 ma_pcm_s24_to_f32__optimized(dst, src,
count, ditherMode);
26216 #if defined(MA_SUPPORT_AVX2)
26219 ma_pcm_s24_to_f32__optimized(dst, src,
count, ditherMode);
26222 #if defined(MA_SUPPORT_AVX512)
26225 ma_pcm_s24_to_f32__avx2(dst, src,
count, ditherMode);
26228 #if defined(MA_SUPPORT_NEON)
26231 ma_pcm_s24_to_f32__optimized(dst, src,
count, ditherMode);
26237 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26238 ma_pcm_s24_to_f32__reference(dst, src,
count, ditherMode);
26240 ma_pcm_s24_to_f32__optimized(dst, src,
count, ditherMode);
26251 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
26253 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
26254 dst8[iFrame*3*
channels + iChannel*3 + 0] = src8[iChannel][iFrame*3 + 0];
26255 dst8[iFrame*3*
channels + iChannel*3 + 1] = src8[iChannel][iFrame*3 + 1];
26256 dst8[iFrame*3*
channels + iChannel*3 + 2] = src8[iChannel][iFrame*3 + 2];
26263 ma_pcm_interleave_s24__reference(dst, src, frameCount,
channels);
26268 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26269 ma_pcm_interleave_s24__reference(dst, src, frameCount,
channels);
26271 ma_pcm_interleave_s24__optimized(dst, src, frameCount,
channels);
26282 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
26284 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
26285 dst8[iChannel][iFrame*3 + 0] = src8[iFrame*3*
channels + iChannel*3 + 0];
26286 dst8[iChannel][iFrame*3 + 1] = src8[iFrame*3*
channels + iChannel*3 + 1];
26287 dst8[iChannel][iFrame*3 + 2] = src8[iFrame*3*
channels + iChannel*3 + 2];
26294 ma_pcm_deinterleave_s24__reference(dst, src, frameCount,
channels);
26299 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26300 ma_pcm_deinterleave_s24__reference(dst, src, frameCount,
channels);
26302 ma_pcm_deinterleave_s24__optimized(dst, src, frameCount,
channels);
26328 ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
26329 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
26344 ma_pcm_s32_to_u8__reference(dst, src,
count, ditherMode);
26347 #if defined(MA_SUPPORT_SSE2)
26350 ma_pcm_s32_to_u8__optimized(dst, src,
count, ditherMode);
26353 #if defined(MA_SUPPORT_AVX2)
26356 ma_pcm_s32_to_u8__optimized(dst, src,
count, ditherMode);
26359 #if defined(MA_SUPPORT_AVX512)
26362 ma_pcm_s32_to_u8__avx2(dst, src,
count, ditherMode);
26365 #if defined(MA_SUPPORT_NEON)
26368 ma_pcm_s32_to_u8__optimized(dst, src,
count, ditherMode);
26374 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26375 ma_pcm_s32_to_u8__reference(dst, src,
count, ditherMode);
26377 ma_pcm_s32_to_u8__optimized(dst, src,
count, ditherMode);
26400 ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
26401 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
26415 ma_pcm_s32_to_s16__reference(dst, src,
count, ditherMode);
26418 #if defined(MA_SUPPORT_SSE2)
26421 ma_pcm_s32_to_s16__optimized(dst, src,
count, ditherMode);
26424 #if defined(MA_SUPPORT_AVX2)
26427 ma_pcm_s32_to_s16__optimized(dst, src,
count, ditherMode);
26430 #if defined(MA_SUPPORT_AVX512)
26433 ma_pcm_s32_to_s16__avx2(dst, src,
count, ditherMode);
26436 #if defined(MA_SUPPORT_NEON)
26439 ma_pcm_s32_to_s16__optimized(dst, src,
count, ditherMode);
26445 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26446 ma_pcm_s32_to_s16__reference(dst, src,
count, ditherMode);
26448 ma_pcm_s32_to_s16__optimized(dst, src,
count, ditherMode);
26461 dst_s24[
i*3+0] = (
ma_uint8)((
x & 0x0000FF00) >> 8);
26462 dst_s24[
i*3+1] = (
ma_uint8)((
x & 0x00FF0000) >> 16);
26463 dst_s24[
i*3+2] = (
ma_uint8)((
x & 0xFF000000) >> 24);
26471 ma_pcm_s32_to_s24__reference(dst, src,
count, ditherMode);
26474 #if defined(MA_SUPPORT_SSE2)
26477 ma_pcm_s32_to_s24__optimized(dst, src,
count, ditherMode);
26480 #if defined(MA_SUPPORT_AVX2)
26483 ma_pcm_s32_to_s24__optimized(dst, src,
count, ditherMode);
26486 #if defined(MA_SUPPORT_AVX512)
26489 ma_pcm_s32_to_s24__avx2(dst, src,
count, ditherMode);
26492 #if defined(MA_SUPPORT_NEON)
26495 ma_pcm_s32_to_s24__optimized(dst, src,
count, ditherMode);
26501 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26502 ma_pcm_s32_to_s24__reference(dst, src,
count, ditherMode);
26504 ma_pcm_s32_to_s24__optimized(dst, src,
count, ditherMode);
26519 float* dst_f32 = (
float*)dst;
26524 double x = src_s32[
i];
26527 x =
x + 2147483648.0;
26528 x =
x * 0.0000000004656612873077392578125;
26531 x =
x / 2147483648.0;
26534 dst_f32[
i] = (float)
x;
26542 ma_pcm_s32_to_f32__reference(dst, src,
count, ditherMode);
26545 #if defined(MA_SUPPORT_SSE2)
26548 ma_pcm_s32_to_f32__optimized(dst, src,
count, ditherMode);
26551 #if defined(MA_SUPPORT_AVX2)
26554 ma_pcm_s32_to_f32__optimized(dst, src,
count, ditherMode);
26557 #if defined(MA_SUPPORT_AVX512)
26560 ma_pcm_s32_to_f32__avx2(dst, src,
count, ditherMode);
26563 #if defined(MA_SUPPORT_NEON)
26566 ma_pcm_s32_to_f32__optimized(dst, src,
count, ditherMode);
26572 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26573 ma_pcm_s32_to_f32__reference(dst, src,
count, ditherMode);
26575 ma_pcm_s32_to_f32__optimized(dst, src,
count, ditherMode);
26586 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
26588 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
26589 dst_s32[iFrame*
channels + iChannel] = src_s32[iChannel][iFrame];
26596 ma_pcm_interleave_s32__reference(dst, src, frameCount,
channels);
26601 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26602 ma_pcm_interleave_s32__reference(dst, src, frameCount,
channels);
26604 ma_pcm_interleave_s32__optimized(dst, src, frameCount,
channels);
26615 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
26617 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
26618 dst_s32[iChannel][iFrame] = src_s32[iFrame*
channels + iChannel];
26625 ma_pcm_deinterleave_s32__reference(dst, src, frameCount,
channels);
26630 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26631 ma_pcm_deinterleave_s32__reference(dst, src, frameCount,
channels);
26633 ma_pcm_deinterleave_s32__optimized(dst, src, frameCount,
channels);
26644 const float* src_f32 = (
const float*)src;
26646 float ditherMin = 0;
26647 float ditherMax = 0;
26649 ditherMin = 1.0f / -128;
26650 ditherMax = 1.0f / 127;
26654 float x = src_f32[
i];
26655 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
26656 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
26666 ma_pcm_f32_to_u8__reference(dst, src,
count, ditherMode);
26669 #if defined(MA_SUPPORT_SSE2)
26672 ma_pcm_f32_to_u8__optimized(dst, src,
count, ditherMode);
26675 #if defined(MA_SUPPORT_AVX2)
26678 ma_pcm_f32_to_u8__optimized(dst, src,
count, ditherMode);
26681 #if defined(MA_SUPPORT_AVX512)
26684 ma_pcm_f32_to_u8__avx2(dst, src,
count, ditherMode);
26687 #if defined(MA_SUPPORT_NEON)
26690 ma_pcm_f32_to_u8__optimized(dst, src,
count, ditherMode);
26696 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
26697 ma_pcm_f32_to_u8__reference(dst, src,
count, ditherMode);
26699 ma_pcm_f32_to_u8__optimized(dst, src,
count, ditherMode);
26709 const float* src_f32 = (
const float*)src;
26711 float ditherMin = 0;
26712 float ditherMax = 0;
26714 ditherMin = 1.0f / -32768;
26715 ditherMax = 1.0f / 32767;
26719 float x = src_f32[
i];
26720 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
26721 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
26744 const float* src_f32 = (
const float*)src;
26746 float ditherMin = 0;
26747 float ditherMax = 0;
26749 ditherMin = 1.0f / -32768;
26750 ditherMax = 1.0f / 32767;
26755 count4 =
count >> 2;
26756 for (i4 = 0; i4 < count4; i4 += 1) {
26757 float d0 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
26758 float d1 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
26759 float d2 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
26760 float d3 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
26762 float x0 = src_f32[
i+0];
26763 float x1 = src_f32[
i+1];
26764 float x2 = src_f32[
i+2];
26765 float x3 = src_f32[
i+3];
26772 x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
26773 x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
26774 x2 = ((
x2 < -1) ? -1 : ((
x2 > 1) ? 1 :
x2));
26775 x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
26777 x0 = x0 * 32767.0f;
26778 x1 = x1 * 32767.0f;
26779 x2 =
x2 * 32767.0f;
26780 x3 = x3 * 32767.0f;
26792 float x = src_f32[
i];
26793 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
26794 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
26801 #if defined(MA_SUPPORT_SSE2)
26808 const float* src_f32;
26814 ma_pcm_f32_to_s16__optimized(dst, src,
count, ditherMode);
26819 src_f32 = (
const float*)src;
26824 ditherMin = 1.0f / -32768;
26825 ditherMax = 1.0f / 32767;
26831 count8 =
count >> 3;
26832 for (i8 = 0; i8 < count8; i8 += 1) {
26839 d0 = _mm_set1_ps(0);
26840 d1 = _mm_set1_ps(0);
26843 ma_dither_f32_rectangle(ditherMin, ditherMax),
26844 ma_dither_f32_rectangle(ditherMin, ditherMax),
26845 ma_dither_f32_rectangle(ditherMin, ditherMax),
26846 ma_dither_f32_rectangle(ditherMin, ditherMax)
26849 ma_dither_f32_rectangle(ditherMin, ditherMax),
26850 ma_dither_f32_rectangle(ditherMin, ditherMax),
26851 ma_dither_f32_rectangle(ditherMin, ditherMax),
26852 ma_dither_f32_rectangle(ditherMin, ditherMax)
26856 ma_dither_f32_triangle(ditherMin, ditherMax),
26857 ma_dither_f32_triangle(ditherMin, ditherMax),
26858 ma_dither_f32_triangle(ditherMin, ditherMax),
26859 ma_dither_f32_triangle(ditherMin, ditherMax)
26862 ma_dither_f32_triangle(ditherMin, ditherMax),
26863 ma_dither_f32_triangle(ditherMin, ditherMax),
26864 ma_dither_f32_triangle(ditherMin, ditherMax),
26865 ma_dither_f32_triangle(ditherMin, ditherMax)
26869 x0 = *((__m128*)(src_f32 +
i) + 0);
26870 x1 = *((__m128*)(src_f32 +
i) + 1);
26872 x0 = _mm_add_ps(x0, d0);
26873 x1 = _mm_add_ps(x1, d1);
26875 x0 = _mm_mul_ps(x0, _mm_set1_ps(32767.0f));
26876 x1 = _mm_mul_ps(x1, _mm_set1_ps(32767.0f));
26878 _mm_stream_si128(((__m128i*)(dst_s16 +
i)), _mm_packs_epi32(_mm_cvttps_epi32(x0), _mm_cvttps_epi32(x1)));
26886 float x = src_f32[
i];
26887 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
26888 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
26895 #if defined(MA_SUPPORT_AVX2)
26902 const float* src_f32;
26908 ma_pcm_f32_to_s16__optimized(dst, src,
count, ditherMode);
26913 src_f32 = (
const float*)src;
26918 ditherMin = 1.0f / -32768;
26919 ditherMax = 1.0f / 32767;
26925 count16 =
count >> 4;
26926 for (i16 = 0; i16 < count16; i16 += 1) {
26938 d0 = _mm256_set1_ps(0);
26939 d1 = _mm256_set1_ps(0);
26941 d0 = _mm256_set_ps(
26942 ma_dither_f32_rectangle(ditherMin, ditherMax),
26943 ma_dither_f32_rectangle(ditherMin, ditherMax),
26944 ma_dither_f32_rectangle(ditherMin, ditherMax),
26945 ma_dither_f32_rectangle(ditherMin, ditherMax),
26946 ma_dither_f32_rectangle(ditherMin, ditherMax),
26947 ma_dither_f32_rectangle(ditherMin, ditherMax),
26948 ma_dither_f32_rectangle(ditherMin, ditherMax),
26949 ma_dither_f32_rectangle(ditherMin, ditherMax)
26951 d1 = _mm256_set_ps(
26952 ma_dither_f32_rectangle(ditherMin, ditherMax),
26953 ma_dither_f32_rectangle(ditherMin, ditherMax),
26954 ma_dither_f32_rectangle(ditherMin, ditherMax),
26955 ma_dither_f32_rectangle(ditherMin, ditherMax),
26956 ma_dither_f32_rectangle(ditherMin, ditherMax),
26957 ma_dither_f32_rectangle(ditherMin, ditherMax),
26958 ma_dither_f32_rectangle(ditherMin, ditherMax),
26959 ma_dither_f32_rectangle(ditherMin, ditherMax)
26962 d0 = _mm256_set_ps(
26963 ma_dither_f32_triangle(ditherMin, ditherMax),
26964 ma_dither_f32_triangle(ditherMin, ditherMax),
26965 ma_dither_f32_triangle(ditherMin, ditherMax),
26966 ma_dither_f32_triangle(ditherMin, ditherMax),
26967 ma_dither_f32_triangle(ditherMin, ditherMax),
26968 ma_dither_f32_triangle(ditherMin, ditherMax),
26969 ma_dither_f32_triangle(ditherMin, ditherMax),
26970 ma_dither_f32_triangle(ditherMin, ditherMax)
26972 d1 = _mm256_set_ps(
26973 ma_dither_f32_triangle(ditherMin, ditherMax),
26974 ma_dither_f32_triangle(ditherMin, ditherMax),
26975 ma_dither_f32_triangle(ditherMin, ditherMax),
26976 ma_dither_f32_triangle(ditherMin, ditherMax),
26977 ma_dither_f32_triangle(ditherMin, ditherMax),
26978 ma_dither_f32_triangle(ditherMin, ditherMax),
26979 ma_dither_f32_triangle(ditherMin, ditherMax),
26980 ma_dither_f32_triangle(ditherMin, ditherMax)
26984 x0 = *((__m256*)(src_f32 +
i) + 0);
26985 x1 = *((__m256*)(src_f32 +
i) + 1);
26987 x0 = _mm256_add_ps(x0, d0);
26988 x1 = _mm256_add_ps(x1, d1);
26990 x0 = _mm256_mul_ps(x0, _mm256_set1_ps(32767.0f));
26991 x1 = _mm256_mul_ps(x1, _mm256_set1_ps(32767.0f));
26994 i0 = _mm256_cvttps_epi32(x0);
26995 i1 = _mm256_cvttps_epi32(x1);
26996 p0 = _mm256_permute2x128_si256(i0,
i1, 0 | 32);
26997 p1 = _mm256_permute2x128_si256(i0,
i1, 1 | 48);
26998 r = _mm256_packs_epi32(p0, p1);
27000 _mm256_stream_si256(((__m256i*)(dst_s16 +
i)),
r);
27008 float x = src_f32[
i];
27009 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
27010 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
27017 #if defined(MA_SUPPORT_AVX512)
27021 ma_pcm_f32_to_s16__avx2(dst, src,
count, ditherMode);
27024 #if defined(MA_SUPPORT_NEON)
27031 const float* src_f32;
27037 ma_pcm_f32_to_s16__optimized(dst, src,
count, ditherMode);
27042 src_f32 = (
const float*)src;
27047 ditherMin = 1.0f / -32768;
27048 ditherMax = 1.0f / 32767;
27054 count8 =
count >> 3;
27055 for (i8 = 0; i8 < count8; i8 += 1) {
27064 d0 = vmovq_n_f32(0);
27065 d1 = vmovq_n_f32(0);
27068 d0v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27069 d0v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27070 d0v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27071 d0v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27072 d0 = vld1q_f32(d0v);
27075 d1v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27076 d1v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27077 d1v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27078 d1v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
27079 d1 = vld1q_f32(d1v);
27082 d0v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
27083 d0v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
27084 d0v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
27085 d0v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
27086 d0 = vld1q_f32(d0v);
27089 d1v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
27090 d1v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
27091 d1v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
27092 d1v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
27093 d1 = vld1q_f32(d1v);
27096 x0 = *((float32x4_t*)(src_f32 +
i) + 0);
27097 x1 = *((float32x4_t*)(src_f32 +
i) + 1);
27099 x0 = vaddq_f32(x0, d0);
27100 x1 = vaddq_f32(x1, d1);
27102 x0 = vmulq_n_f32(x0, 32767.0f);
27103 x1 = vmulq_n_f32(x1, 32767.0f);
27105 i0 = vcvtq_s32_f32(x0);
27106 i1 = vcvtq_s32_f32(x1);
27107 *((int16x8_t*)(dst_s16 +
i)) = vcombine_s16(vqmovn_s32(i0), vqmovn_s32(
i1));
27115 float x = src_f32[
i];
27116 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
27117 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
27127 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27128 ma_pcm_f32_to_s16__reference(dst, src,
count, ditherMode);
27130 ma_pcm_f32_to_s16__optimized(dst, src,
count, ditherMode);
27138 const float* src_f32 = (
const float*)src;
27143 float x = src_f32[
i];
27144 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
27149 x =
x * 8388607.5f;
27150 x =
x - 8388608.0f;
27153 x =
x * 8388607.0f;
27157 dst_s24[(
i*3)+0] = (
ma_uint8)((
r & 0x0000FF) >> 0);
27158 dst_s24[(
i*3)+1] = (
ma_uint8)((
r & 0x00FF00) >> 8);
27159 dst_s24[(
i*3)+2] = (
ma_uint8)((
r & 0xFF0000) >> 16);
27167 ma_pcm_f32_to_s24__reference(dst, src,
count, ditherMode);
27170 #if defined(MA_SUPPORT_SSE2)
27173 ma_pcm_f32_to_s24__optimized(dst, src,
count, ditherMode);
27176 #if defined(MA_SUPPORT_AVX2)
27179 ma_pcm_f32_to_s24__optimized(dst, src,
count, ditherMode);
27182 #if defined(MA_SUPPORT_AVX512)
27185 ma_pcm_f32_to_s24__avx2(dst, src,
count, ditherMode);
27188 #if defined(MA_SUPPORT_NEON)
27191 ma_pcm_f32_to_s24__optimized(dst, src,
count, ditherMode);
27197 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27198 ma_pcm_f32_to_s24__reference(dst, src,
count, ditherMode);
27200 ma_pcm_f32_to_s24__optimized(dst, src,
count, ditherMode);
27208 const float* src_f32 = (
const float*)src;
27212 double x = src_f32[
i];
27213 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
27218 x =
x * 2147483647.5;
27219 x =
x - 2147483648.0;
27222 x =
x * 2147483647.0;
27233 ma_pcm_f32_to_s32__reference(dst, src,
count, ditherMode);
27236 #if defined(MA_SUPPORT_SSE2)
27239 ma_pcm_f32_to_s32__optimized(dst, src,
count, ditherMode);
27242 #if defined(MA_SUPPORT_AVX2)
27245 ma_pcm_f32_to_s32__optimized(dst, src,
count, ditherMode);
27248 #if defined(MA_SUPPORT_AVX512)
27251 ma_pcm_f32_to_s32__avx2(dst, src,
count, ditherMode);
27254 #if defined(MA_SUPPORT_NEON)
27257 ma_pcm_f32_to_s32__optimized(dst, src,
count, ditherMode);
27263 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27264 ma_pcm_f32_to_s32__reference(dst, src,
count, ditherMode);
27266 ma_pcm_f32_to_s32__optimized(dst, src,
count, ditherMode);
27275 ma_copy_memory_64(dst, src,
count *
sizeof(
float));
27281 float* dst_f32 = (
float*)dst;
27282 const float** src_f32 = (
const float**)src;
27285 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
27287 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
27288 dst_f32[iFrame*
channels + iChannel] = src_f32[iChannel][iFrame];
27295 ma_pcm_interleave_f32__reference(dst, src, frameCount,
channels);
27300 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27301 ma_pcm_interleave_f32__reference(dst, src, frameCount,
channels);
27303 ma_pcm_interleave_f32__optimized(dst, src, frameCount,
channels);
27310 float** dst_f32 = (
float**)dst;
27311 const float* src_f32 = (
const float*)src;
27314 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
27316 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
27317 dst_f32[iChannel][iFrame] = src_f32[iFrame*
channels + iChannel];
27324 ma_pcm_deinterleave_f32__reference(dst, src, frameCount,
channels);
27329 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27330 ma_pcm_deinterleave_f32__reference(dst, src, frameCount,
channels);
27332 ma_pcm_deinterleave_f32__optimized(dst, src, frameCount,
channels);
27339 ma_assert(pConverter !=
NULL);
27421 #if defined(MA_SUPPORT_SSE2)
27424 ma_assert(pConverter !=
NULL);
27507 #if defined(MA_SUPPORT_AVX2)
27510 ma_assert(pConverter !=
NULL);
27593 #if defined(MA_SUPPORT_AVX512)
27596 ma_assert(pConverter !=
NULL);
27679 #if defined(MA_SUPPORT_NEON)
27682 ma_assert(pConverter !=
NULL);
27767 if (pConverter ==
NULL) {
27770 ma_zero_object(pConverter);
27772 if (pConfig ==
NULL) {
27776 pConverter->
config = *pConfig;
27784 #if defined(MA_SUPPORT_AVX512)
27786 ma_format_converter_init_callbacks__avx512(pConverter);
27789 #if defined(MA_SUPPORT_AVX2)
27791 ma_format_converter_init_callbacks__avx2(pConverter);
27794 #if defined(MA_SUPPORT_SSE2)
27796 ma_format_converter_init_callbacks__sse2(pConverter);
27799 #if defined(MA_SUPPORT_NEON)
27801 ma_format_converter_init_callbacks__neon(pConverter);
27805 ma_format_converter_init_callbacks__default(pConverter);
27849 if (pConverter ==
NULL || pFramesOut ==
NULL) {
27853 totalFramesRead = 0;
27858 pNextFramesOut = (
ma_uint8*)pFramesOut;
27864 while (totalFramesRead < frameCount) {
27866 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
27867 ma_uint64 framesToReadRightNow = framesRemaining;
27868 if (framesToReadRightNow > 0xFFFFFFFF) {
27869 framesToReadRightNow = 0xFFFFFFFF;
27873 if (framesJustRead == 0) {
27877 totalFramesRead += framesJustRead;
27878 pNextFramesOut += framesJustRead * frameSizeOut;
27880 if (framesJustRead < framesToReadRightNow) {
27889 ma_assert(
sizeof(temp) <= 0xFFFFFFFF);
27891 maxFramesToReadAtATime =
sizeof(temp) / sampleSizeIn / pConverter->
config.
channels;
27893 while (totalFramesRead < frameCount) {
27895 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
27896 ma_uint64 framesToReadRightNow = framesRemaining;
27897 if (framesToReadRightNow > maxFramesToReadAtATime) {
27898 framesToReadRightNow = maxFramesToReadAtATime;
27902 if (framesJustRead == 0) {
27908 totalFramesRead += framesJustRead;
27909 pNextFramesOut += framesJustRead * frameSizeOut;
27911 if (framesJustRead < framesToReadRightNow) {
27919 size_t splitBufferSizeOut;
27923 ma_assert(
sizeof(tempSamplesOfOutFormat) <= 0xFFFFFFFF);
27925 ma_split_buffer(tempSamplesOfOutFormat,
sizeof(tempSamplesOfOutFormat), pConverter->
config.
channels,
MA_SIMD_ALIGNMENT, (
void**)&ppTempSamplesOfOutFormat, &splitBufferSizeOut);
27927 maxFramesToReadAtATime = (
ma_uint32)(splitBufferSizeOut / sampleSizeIn);
27929 while (totalFramesRead < frameCount) {
27931 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
27932 ma_uint64 framesToReadRightNow = framesRemaining;
27933 if (framesToReadRightNow > maxFramesToReadAtATime) {
27934 framesToReadRightNow = maxFramesToReadAtATime;
27940 if (framesJustRead == 0) {
27946 size_t splitBufferSizeIn;
27951 ma_split_buffer(tempSamplesOfInFormat,
sizeof(tempSamplesOfInFormat), pConverter->
config.
channels,
MA_SIMD_ALIGNMENT, (
void**)&ppTempSamplesOfInFormat, &splitBufferSizeIn);
27953 if (framesToReadRightNow > (splitBufferSizeIn / sampleSizeIn)) {
27954 framesToReadRightNow = (splitBufferSizeIn / sampleSizeIn);
27958 if (framesJustRead == 0) {
27962 for (iChannel = 0; iChannel < pConverter->
config.
channels; iChannel += 1) {
27963 pConverter->
onConvertPCM(ppTempSamplesOfOutFormat[iChannel], ppTempSamplesOfInFormat[iChannel], framesJustRead, pConverter->
config.
ditherMode);
27969 totalFramesRead += framesJustRead;
27970 pNextFramesOut += framesJustRead * frameSizeOut;
27972 if (framesJustRead < framesToReadRightNow) {
27978 return totalFramesRead;
27988 if (pConverter ==
NULL || ppSamplesOut ==
NULL) {
27992 totalFramesRead = 0;
27996 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
void*) * pConverter->
config.
channels);
28003 ma_assert(
sizeof(tempSamplesOfOutFormat) <= 0xFFFFFFFF);
28005 maxFramesToReadAtATime =
sizeof(tempSamplesOfOutFormat) / sampleSizeIn / pConverter->
config.
channels;
28007 while (totalFramesRead < frameCount) {
28010 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
28011 ma_uint64 framesToReadRightNow = framesRemaining;
28012 if (framesToReadRightNow > maxFramesToReadAtATime) {
28013 framesToReadRightNow = maxFramesToReadAtATime;
28019 if (framesJustRead == 0) {
28027 if (framesJustRead == 0) {
28036 totalFramesRead += framesJustRead;
28037 for (iChannel = 0; iChannel < pConverter->
config.
channels; ++iChannel) {
28038 ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
28041 if (framesJustRead < framesToReadRightNow) {
28049 while (totalFramesRead < frameCount) {
28052 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
28053 ma_uint64 framesToReadRightNow = framesRemaining;
28054 if (framesToReadRightNow > 0xFFFFFFFF) {
28055 framesToReadRightNow = 0xFFFFFFFF;
28059 if (framesJustRead == 0) {
28063 totalFramesRead += framesJustRead;
28064 for (iChannel = 0; iChannel < pConverter->
config.
channels; ++iChannel) {
28065 ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
28068 if (framesJustRead < framesToReadRightNow) {
28075 size_t splitBufferSize;
28079 ma_assert(
sizeof(temp) <= 0xFFFFFFFF);
28083 maxFramesToReadAtATime = (
ma_uint32)(splitBufferSize / sampleSizeIn);
28085 while (totalFramesRead < frameCount) {
28088 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
28089 ma_uint64 framesToReadRightNow = framesRemaining;
28090 if (framesToReadRightNow > maxFramesToReadAtATime) {
28091 framesToReadRightNow = maxFramesToReadAtATime;
28095 if (framesJustRead == 0) {
28099 for (iChannel = 0; iChannel < pConverter->
config.
channels; iChannel += 1) {
28101 ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
28104 totalFramesRead += framesJustRead;
28106 if (framesJustRead < framesToReadRightNow) {
28113 return totalFramesRead;
28120 ma_zero_object(&config);
28166 static MA_INLINE ma_vec3 ma_vec3f(
float x,
float y,
float z)
28176 static MA_INLINE ma_vec3 ma_vec3_add(ma_vec3 a, ma_vec3 b)
28185 static MA_INLINE ma_vec3 ma_vec3_sub(ma_vec3 a, ma_vec3 b)
28194 static MA_INLINE ma_vec3 ma_vec3_mul(ma_vec3 a, ma_vec3 b)
28203 static MA_INLINE ma_vec3 ma_vec3_div(ma_vec3 a, ma_vec3 b)
28212 static MA_INLINE float ma_vec3_dot(ma_vec3 a, ma_vec3 b)
28214 return a.x*b.x + a.y*b.y + a.z*b.z;
28217 static MA_INLINE float ma_vec3_length2(ma_vec3 a)
28219 return ma_vec3_dot(a, a);
28222 static MA_INLINE float ma_vec3_length(ma_vec3 a)
28224 return (
float)
sqrt(ma_vec3_length2(a));
28227 static MA_INLINE ma_vec3 ma_vec3_normalize(ma_vec3 a)
28229 float len = 1 / ma_vec3_length(a);
28239 static MA_INLINE float ma_vec3_distance(ma_vec3 a, ma_vec3 b)
28241 return ma_vec3_length(ma_vec3_sub(a, b));
28245 #define MA_PLANE_LEFT 0
28246 #define MA_PLANE_RIGHT 1
28247 #define MA_PLANE_FRONT 2
28248 #define MA_PLANE_BACK 3
28249 #define MA_PLANE_BOTTOM 4
28250 #define MA_PLANE_TOP 5
28253 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28254 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28255 { 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f},
28256 { 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f},
28257 { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
28258 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28259 { 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f},
28260 { 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f},
28261 { 0.25f, 0.0f, 0.75f, 0.0f, 0.0f, 0.0f},
28262 { 0.0f, 0.25f, 0.75f, 0.0f, 0.0f, 0.0f},
28263 { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
28264 { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28265 { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28266 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
28267 { 0.33f, 0.0f, 0.33f, 0.0f, 0.0f, 0.34f},
28268 { 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f},
28269 { 0.0f, 0.33f, 0.33f, 0.0f, 0.0f, 0.34f},
28270 { 0.33f, 0.0f, 0.0f, 0.33f, 0.0f, 0.34f},
28271 { 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f},
28272 { 0.0f, 0.33f, 0.0f, 0.33f, 0.0f, 0.34f},
28273 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28274 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28275 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28276 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28277 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28278 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28279 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28280 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28281 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28282 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28283 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28284 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28285 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28286 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28287 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28288 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28289 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28290 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28291 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28292 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28293 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28294 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28295 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28296 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28297 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28298 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28299 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28300 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28301 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28302 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28303 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28304 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
28307 float ma_calculate_channel_position_planar_weight(
ma_channel channelPositionA,
ma_channel channelPositionB)
28339 float contribution =
28340 g_maChannelPlaneRatios[channelPositionA][0] * g_maChannelPlaneRatios[channelPositionB][0] +
28341 g_maChannelPlaneRatios[channelPositionA][1] * g_maChannelPlaneRatios[channelPositionB][1] +
28342 g_maChannelPlaneRatios[channelPositionA][2] * g_maChannelPlaneRatios[channelPositionB][2] +
28343 g_maChannelPlaneRatios[channelPositionA][3] * g_maChannelPlaneRatios[channelPositionB][3] +
28344 g_maChannelPlaneRatios[channelPositionA][4] * g_maChannelPlaneRatios[channelPositionB][4] +
28345 g_maChannelPlaneRatios[channelPositionA][5] * g_maChannelPlaneRatios[channelPositionB][5];
28347 return contribution;
28352 ma_assert(pRouter !=
NULL);
28355 return ma_calculate_channel_position_planar_weight(channelPositionIn, channelPositionOut);
28362 ma_assert(pRouter !=
NULL);
28369 for (
i = 0;
i < 6; ++
i) {
28370 if (g_maChannelPlaneRatios[channelPosition][
i] != 0) {
28383 if (pRouter ==
NULL) {
28387 ma_zero_object(pRouter);
28389 if (pConfig ==
NULL) {
28403 pRouter->
config = *pConfig;
28432 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28434 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28436 isInputChannelPositionInOutput =
MA_TRUE;
28441 if (!isInputChannelPositionInOutput) {
28442 areAllChannelPositionsPresent =
MA_FALSE;
28447 if (areAllChannelPositionsPresent) {
28454 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28455 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28477 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28480 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28483 if (channelPosIn == channelPosOut) {
28493 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28497 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28510 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28519 float monoWeight = 1.0f / len;
28521 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28525 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28529 pRouter->
config.
weights[iChannelIn][iChannelOut] += monoWeight;
28544 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28547 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosIn)) {
28549 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28552 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosOut)) {
28555 weight = ma_channel_router__calculate_input_channel_planar_weight(pRouter, channelPosIn, channelPosOut);
28559 if (pRouter->
config.
weights[iChannelIn][iChannelOut] == 0) {
28569 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28572 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosOut)) {
28574 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28577 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosIn)) {
28580 weight = ma_channel_router__calculate_input_channel_planar_weight(pRouter, channelPosIn, channelPosOut);
28584 if (pRouter->
config.
weights[iChannelIn][iChannelOut] == 0) {
28625 void ma_channel_router__do_routing(
ma_channel_router* pRouter,
ma_uint64 frameCount,
float** ppSamplesOut,
const float** ppSamplesIn)
28630 ma_assert(pRouter !=
NULL);
28636 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28638 ma_copy_memory_64(ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn], frameCount *
sizeof(
float));
28644 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28645 ma_zero_memory_64(ppSamplesOut[iChannelOut], frameCount *
sizeof(
float));
28649 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
28650 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
28652 #if defined(MA_SUPPORT_NEON)
28653 if (ma_channel_router__can_use_neon(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
28654 float32x4_t weight = vmovq_n_f32(pRouter->
config.
weights[iChannelIn][iChannelOut]);
28658 for (iFrame4 = 0; iFrame4 < frameCount4; iFrame4 += 1) {
28659 float32x4_t* pO = (float32x4_t*)ppSamplesOut[iChannelOut] + iFrame4;
28660 float32x4_t* pI = (float32x4_t*)ppSamplesIn [iChannelIn ] + iFrame4;
28661 *pO = vaddq_f32(*pO, vmulq_f32(*pI, weight));
28664 iFrame += frameCount4*4;
28668 #if defined(MA_SUPPORT_AVX512)
28669 if (ma_channel_router__can_use_avx512(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
28670 __m512 weight = _mm512_set1_ps(pRouter->
config.
weights[iChannelIn][iChannelOut]);
28671 ma_uint64 frameCount16 = frameCount/16;
28674 for (iFrame16 = 0; iFrame16 < frameCount16; iFrame16 += 1) {
28675 __m512* pO = (__m512*)ppSamplesOut[iChannelOut] + iFrame16;
28676 __m512* pI = (__m512*)ppSamplesIn [iChannelIn ] + iFrame16;
28677 *pO = _mm512_add_ps(*pO, _mm512_mul_ps(*pI, weight));
28680 iFrame += frameCount16*16;
28684 #if defined(MA_SUPPORT_AVX2)
28685 if (ma_channel_router__can_use_avx2(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
28686 __m256 weight = _mm256_set1_ps(pRouter->
config.
weights[iChannelIn][iChannelOut]);
28690 for (iFrame8 = 0; iFrame8 < frameCount8; iFrame8 += 1) {
28691 __m256* pO = (__m256*)ppSamplesOut[iChannelOut] + iFrame8;
28692 __m256* pI = (__m256*)ppSamplesIn [iChannelIn ] + iFrame8;
28693 *pO = _mm256_add_ps(*pO, _mm256_mul_ps(*pI, weight));
28696 iFrame += frameCount8*8;
28700 #if defined(MA_SUPPORT_SSE2)
28701 if (ma_channel_router__can_use_sse2(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
28702 __m128 weight = _mm_set1_ps(pRouter->
config.
weights[iChannelIn][iChannelOut]);
28706 for (iFrame4 = 0; iFrame4 < frameCount4; iFrame4 += 1) {
28707 __m128* pO = (__m128*)ppSamplesOut[iChannelOut] + iFrame4;
28708 __m128* pI = (__m128*)ppSamplesIn [iChannelIn ] + iFrame4;
28709 *pO = _mm_add_ps(*pO, _mm_mul_ps(*pI, weight));
28712 iFrame += frameCount4*4;
28716 float weight0 = pRouter->
config.
weights[iChannelIn][iChannelOut];
28717 float weight1 = pRouter->
config.
weights[iChannelIn][iChannelOut];
28718 float weight2 = pRouter->
config.
weights[iChannelIn][iChannelOut];
28719 float weight3 = pRouter->
config.
weights[iChannelIn][iChannelOut];
28723 for (iFrame4 = 0; iFrame4 < frameCount4; iFrame4 += 1) {
28724 ppSamplesOut[iChannelOut][iFrame+0] += ppSamplesIn[iChannelIn][iFrame+0] * weight0;
28725 ppSamplesOut[iChannelOut][iFrame+1] += ppSamplesIn[iChannelIn][iFrame+1] * weight1;
28726 ppSamplesOut[iChannelOut][iFrame+2] += ppSamplesIn[iChannelIn][iFrame+2] * weight2;
28727 ppSamplesOut[iChannelOut][iFrame+3] += ppSamplesIn[iChannelIn][iFrame+3] * weight3;
28733 for (; iFrame < frameCount; ++iFrame) {
28734 ppSamplesOut[iChannelOut][iFrame] += ppSamplesIn[iChannelIn][iFrame] * pRouter->
config.
weights[iChannelIn][iChannelOut];
28743 if (pRouter ==
NULL || ppSamplesOut ==
NULL) {
28749 if (frameCount <= 0xFFFFFFFF) {
28755 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
float*) * pRouter->
config.
channelsOut);
28757 totalFramesRead = 0;
28758 while (totalFramesRead < frameCount) {
28761 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
28762 ma_uint64 framesToReadRightNow = framesRemaining;
28763 if (framesToReadRightNow > 0xFFFFFFFF) {
28764 framesToReadRightNow = 0xFFFFFFFF;
28768 if (framesJustRead == 0) {
28772 totalFramesRead += framesJustRead;
28774 if (framesJustRead < framesToReadRightNow) {
28779 ppNextSamplesOut[iChannel] += framesJustRead;
28783 return totalFramesRead;
28791 size_t maxBytesToReadPerFrameEachIteration;
28792 size_t maxFramesToReadEachIteration;
28796 ma_assert(
sizeof(temp) <= 0xFFFFFFFF);
28797 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
float*) * pRouter->
config.
channelsOut);
28802 maxFramesToReadEachIteration = maxBytesToReadPerFrameEachIteration/
sizeof(float);
28804 totalFramesRead = 0;
28805 while (totalFramesRead < frameCount) {
28808 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
28809 ma_uint64 framesToReadRightNow = framesRemaining;
28810 if (framesToReadRightNow > maxFramesToReadEachIteration) {
28811 framesToReadRightNow = maxFramesToReadEachIteration;
28815 if (framesJustRead == 0) {
28819 ma_channel_router__do_routing(pRouter, framesJustRead, (
float**)ppNextSamplesOut, (
const float**)ppTemp);
28821 totalFramesRead += framesJustRead;
28822 if (totalFramesRead < frameCount) {
28823 for (iChannel = 0; iChannel < pRouter->
config.
channelsIn; iChannel += 1) {
28824 ppNextSamplesOut[iChannel] += framesJustRead;
28828 if (framesJustRead < framesToReadRightNow) {
28833 return totalFramesRead;
28842 ma_zero_object(&config);
28845 for (iChannel = 0; iChannel < channelsIn; ++iChannel) {
28846 config.
channelMapIn[iChannel] = channelMapIn[iChannel];
28850 for (iChannel = 0; iChannel < channelsOut; ++iChannel) {
28868 #define ma_floorf(x) ((float)floor((double)(x)))
28869 #define ma_sinf(x) ((float)sin((double)(x)))
28870 #define ma_cosf(x) ((float)cos((double)(x)))
28875 return sin(MA_PI_D*
x) / (MA_PI_D*
x);
28881 #define ma_sincf(x) ((float)ma_sinc((double)(x)))
28884 ma_uint64 ma_src_read_deinterleaved__passthrough(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData);
28885 ma_uint64 ma_src_read_deinterleaved__linear(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData);
28886 ma_uint64 ma_src_read_deinterleaved__sinc(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData);
28888 void ma_src__build_sinc_table__sinc(
ma_src* pSRC)
28892 ma_assert(pSRC !=
NULL);
28894 pSRC->sinc.table[0] = 1.0f;
28895 for (
i = 1;
i < ma_countof(pSRC->sinc.table);
i += 1) {
28897 pSRC->sinc.table[
i] = (float)(sin(
x)/
x);
28901 void ma_src__build_sinc_table__rectangular(
ma_src* pSRC)
28904 ma_src__build_sinc_table__sinc(pSRC);
28907 void ma_src__build_sinc_table__hann(
ma_src* pSRC)
28911 ma_src__build_sinc_table__sinc(pSRC);
28913 for (
i = 0;
i < ma_countof(pSRC->sinc.table);
i += 1) {
28914 double x = pSRC->sinc.table[
i];
28917 double w = 0.5 * (1 - cos((2*MA_PI_D*n) / (N)));
28919 pSRC->sinc.table[
i] = (float)(
x *
w);
28925 if (pSRC ==
NULL) {
28929 ma_zero_object(pSRC);
28938 pSRC->config = *pConfig;
28941 pSRC->useSSE2 = ma_has_sse2() && !pConfig->
noSSE2;
28942 pSRC->useAVX2 = ma_has_avx2() && !pConfig->
noAVX2;
28943 pSRC->useAVX512 = ma_has_avx512f() && !pConfig->
noAVX512;
28944 pSRC->useNEON = ma_has_neon() && !pConfig->
noNEON;
28948 if (pSRC->config.sinc.windowWidth == 0) {
28959 switch (pSRC->config.sinc.windowFunction) {
28971 if (pSRC ==
NULL) {
28976 if (sampleRateIn == 0 || sampleRateOut == 0) {
28980 ma_atomic_exchange_32(&pSRC->config.sampleRateIn, sampleRateIn);
28981 ma_atomic_exchange_32(&pSRC->config.sampleRateOut, sampleRateOut);
28990 if (pSRC ==
NULL || frameCount == 0 || ppSamplesOut ==
NULL) {
28994 algorithm = pSRC->config.algorithm;
28997 switch (algorithm) {
28998 case ma_src_algorithm_none:
return ma_src_read_deinterleaved__passthrough(pSRC, frameCount, ppSamplesOut, pUserData);
28999 case ma_src_algorithm_linear:
return ma_src_read_deinterleaved__linear( pSRC, frameCount, ppSamplesOut, pUserData);
29000 case ma_src_algorithm_sinc:
return ma_src_read_deinterleaved__sinc( pSRC, frameCount, ppSamplesOut, pUserData);
29008 ma_uint64 ma_src_read_deinterleaved__passthrough(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData)
29010 if (frameCount <= 0xFFFFFFFF) {
29011 return pSRC->config.onReadDeinterleaved(pSRC, (
ma_uint32)frameCount, ppSamplesOut, pUserData);
29017 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
29018 ppNextSamplesOut[iChannel] = (
float*)ppSamplesOut[iChannel];
29021 totalFramesRead = 0;
29022 while (totalFramesRead < frameCount) {
29024 ma_uint64 framesRemaining = frameCount - totalFramesRead;
29025 ma_uint64 framesToReadRightNow = framesRemaining;
29026 if (framesToReadRightNow > 0xFFFFFFFF) {
29027 framesToReadRightNow = 0xFFFFFFFF;
29030 framesJustRead = (
ma_uint32)pSRC->config.onReadDeinterleaved(pSRC, (
ma_uint32)framesToReadRightNow, (
void**)ppNextSamplesOut, pUserData);
29031 if (framesJustRead == 0) {
29035 totalFramesRead += framesJustRead;
29036 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
29037 ppNextSamplesOut[iChannel] += framesJustRead;
29040 if (framesJustRead < framesToReadRightNow) {
29045 return totalFramesRead;
29049 ma_uint64 ma_src_read_deinterleaved__linear(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData)
29056 ma_assert(pSRC !=
NULL);
29057 ma_assert(frameCount > 0);
29058 ma_assert(ppSamplesOut !=
NULL);
29060 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
void*) * pSRC->config.channels);
29062 factor = (float)pSRC->config.sampleRateIn / pSRC->config.sampleRateOut;
29063 maxFrameCountPerChunkIn = ma_countof(pSRC->linear.input[0]);
29065 totalFramesRead = 0;
29066 while (totalFramesRead < frameCount) {
29078 ma_uint64 framesRemaining = frameCount - totalFramesRead;
29079 ma_uint64 framesToRead = framesRemaining;
29080 if (framesToRead > 16384) {
29081 framesToRead = 16384;
29086 tBeg = pSRC->linear.timeIn;
29087 tEnd = tBeg + ((
ma_int64)framesToRead*factor);
29089 framesToReadFromClient = (
ma_uint32)(tEnd) + 1 + 1;
29090 if (framesToReadFromClient >= maxFrameCountPerChunkIn) {
29091 framesToReadFromClient = maxFrameCountPerChunkIn;
29094 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
29095 ppSamplesFromClient[iChannel] = pSRC->linear.input[iChannel] + pSRC->linear.leftoverFrames;
29098 framesReadFromClient = 0;
29099 if (framesToReadFromClient > pSRC->linear.leftoverFrames) {
29100 framesReadFromClient = (
ma_uint32)pSRC->config.onReadDeinterleaved(pSRC, (
ma_uint32)framesToReadFromClient - pSRC->linear.leftoverFrames, (
void**)ppSamplesFromClient, pUserData);
29103 framesReadFromClient += pSRC->linear.leftoverFrames;
29104 if (framesReadFromClient < 2) {
29108 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
29109 ppSamplesFromClient[iChannel] = pSRC->linear.input[iChannel];
29119 tAvailable = framesReadFromClient - tBeg - 1;
29121 maxOutputFramesToRead = (
ma_uint32)(tAvailable / factor);
29122 if (maxOutputFramesToRead == 0) {
29123 maxOutputFramesToRead = 1;
29125 if (maxOutputFramesToRead > framesToRead) {
29126 maxOutputFramesToRead = (
ma_uint32)framesToRead;
29130 maxOutputFramesToRead4 = maxOutputFramesToRead/4;
29131 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
29133 float t0 = pSRC->linear.timeIn + factor*0;
29134 float t1 = pSRC->linear.timeIn + factor*1;
29135 float t2 = pSRC->linear.timeIn + factor*2;
29136 float t3 = pSRC->linear.timeIn + factor*3;
29139 for (iFrameOut = 0; iFrameOut < maxOutputFramesToRead4; iFrameOut += 1) {
29140 float iPrevSample0 = (float)floor(t0);
29141 float iPrevSample1 = (float)floor(t1);
29142 float iPrevSample2 = (float)floor(t2);
29143 float iPrevSample3 = (float)floor(t3);
29145 float iNextSample0 = iPrevSample0 + 1;
29146 float iNextSample1 = iPrevSample1 + 1;
29147 float iNextSample2 = iPrevSample2 + 1;
29148 float iNextSample3 = iPrevSample3 + 1;
29150 float alpha0 = t0 - iPrevSample0;
29151 float alpha1 = t1 - iPrevSample1;
29152 float alpha2 = t2 - iPrevSample2;
29153 float alpha3 = t3 - iPrevSample3;
29155 float prevSample0 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample0];
29156 float prevSample1 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample1];
29157 float prevSample2 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample2];
29158 float prevSample3 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample3];
29160 float nextSample0 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample0];
29161 float nextSample1 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample1];
29162 float nextSample2 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample2];
29163 float nextSample3 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample3];
29165 ppNextSamplesOut[iChannel][iFrameOut*4 + 0] = ma_mix_f32_fast(prevSample0, nextSample0, alpha0);
29166 ppNextSamplesOut[iChannel][iFrameOut*4 + 1] = ma_mix_f32_fast(prevSample1, nextSample1, alpha1);
29167 ppNextSamplesOut[iChannel][iFrameOut*4 + 2] = ma_mix_f32_fast(prevSample2, nextSample2, alpha2);
29168 ppNextSamplesOut[iChannel][iFrameOut*4 + 3] = ma_mix_f32_fast(prevSample3, nextSample3, alpha3);
29176 t = pSRC->linear.timeIn + (factor*maxOutputFramesToRead4*4);
29177 for (iFrameOut = (maxOutputFramesToRead4*4); iFrameOut < maxOutputFramesToRead; iFrameOut += 1) {
29178 float iPrevSample = (float)floor(
t);
29179 float iNextSample = iPrevSample + 1;
29180 float alpha =
t - iPrevSample;
29184 ma_assert(iPrevSample < ma_countof(pSRC->linear.input[iChannel]));
29185 ma_assert(iNextSample < ma_countof(pSRC->linear.input[iChannel]));
29187 prevSample = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample];
29188 nextSample = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample];
29190 ppNextSamplesOut[iChannel][iFrameOut] = ma_mix_f32_fast(prevSample, nextSample,
alpha);
29195 ppNextSamplesOut[iChannel] += maxOutputFramesToRead;
29198 totalFramesRead += maxOutputFramesToRead;
29202 tNext = pSRC->linear.timeIn + (maxOutputFramesToRead*factor);
29204 pSRC->linear.timeIn = tNext;
29205 ma_assert(tNext <= framesReadFromClient+1);
29208 pSRC->linear.leftoverFrames = framesReadFromClient - iNextFrame;
29209 pSRC->linear.timeIn = tNext - iNextFrame;
29211 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
29213 for (iFrame = 0; iFrame < pSRC->linear.leftoverFrames; ++iFrame) {
29214 float sample = ppSamplesFromClient[iChannel][framesReadFromClient-pSRC->linear.leftoverFrames + iFrame];
29215 ppSamplesFromClient[iChannel][iFrame] =
sample;
29221 if (framesReadFromClient < framesToReadFromClient) {
29226 return totalFramesRead;
29233 ma_zero_object(&config);
29279 #define MA_USE_SINC_TABLE_INTERPOLATION
29284 ma_assert(pSRC !=
NULL);
29286 ma_assert(sampleIndex >= -(
ma_int32)pSRC->config.sinc.windowWidth);
29287 ma_assert(sampleIndex < (
ma_int32)pSRC->config.sinc.windowWidth);
29290 ma_assert(windowPosInSamples < ma_countof(pSRC->sinc.input[0]) - pSRC->config.sinc.windowWidth);
29292 return pSRC->sinc.input[
channel][windowPosInSamples + pSRC->config.sinc.windowWidth + sampleIndex];
29295 static MA_INLINE float ma_src_sinc__interpolation_factor(
const ma_src* pSRC,
float x)
29300 ma_assert(pSRC !=
NULL);
29302 xabs = (float)fabs(
x);
29306 #if defined(MA_USE_SINC_TABLE_INTERPOLATION)
29308 float a = xabs - ixabs;
29309 return ma_mix_f32_fast(pSRC->sinc.table[ixabs], pSRC->sinc.table[ixabs+1], a);
29312 return pSRC->sinc.table[ixabs];
29316 #if defined(MA_SUPPORT_SSE2)
29317 static MA_INLINE __m128 ma_fabsf_sse2(__m128
x)
29319 return _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF)),
x);
29322 static MA_INLINE __m128 ma_truncf_sse2(__m128
x)
29324 return _mm_cvtepi32_ps(_mm_cvttps_epi32(
x));
29327 static MA_INLINE __m128 ma_src_sinc__interpolation_factor__sse2(
const ma_src* pSRC, __m128
x)
29329 __m128 resolution128;
29339 xabs = ma_fabsf_sse2(
x);
29340 xabs = _mm_mul_ps(xabs, resolution128);
29341 ixabs = _mm_cvttps_epi32(xabs);
29343 ixabsv = (
int*)&ixabs;
29346 pSRC->sinc.table[ixabsv[3]],
29347 pSRC->sinc.table[ixabsv[2]],
29348 pSRC->sinc.table[ixabsv[1]],
29349 pSRC->sinc.table[ixabsv[0]]
29353 pSRC->sinc.table[ixabsv[3]+1],
29354 pSRC->sinc.table[ixabsv[2]+1],
29355 pSRC->sinc.table[ixabsv[1]+1],
29356 pSRC->sinc.table[ixabsv[0]+1]
29359 a = _mm_sub_ps(xabs, _mm_cvtepi32_ps(ixabs));
29360 r = ma_mix_f32_fast__sse2(lo, hi, a);
29366 #if defined(MA_SUPPORT_AVX2)
29367 static MA_INLINE __m256 ma_fabsf_avx2(__m256
x)
29369 return _mm256_and_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x7FFFFFFF)),
x);
29373 static MA_INLINE __m256 ma_src_sinc__interpolation_factor__avx2(
const ma_src* pSRC, __m256
x)
29376 __m256 xabs = ma_fabsf_avx2(
x);
29378 xabs = _mm256_mul_ps(xabs, resolution256);
29380 __m256i ixabs = _mm256_cvttps_epi32(xabs);
29381 __m256 a = _mm256_sub_ps(xabs, _mm256_cvtepi32_ps(ixabs));
29384 int* ixabsv = (
int*)&ixabs;
29386 __m256 lo = _mm256_set_ps(
29387 pSRC->sinc.table[ixabsv[7]],
29388 pSRC->sinc.table[ixabsv[6]],
29389 pSRC->sinc.table[ixabsv[5]],
29390 pSRC->sinc.table[ixabsv[4]],
29391 pSRC->sinc.table[ixabsv[3]],
29392 pSRC->sinc.table[ixabsv[2]],
29393 pSRC->sinc.table[ixabsv[1]],
29394 pSRC->sinc.table[ixabsv[0]]
29397 __m256 hi = _mm256_set_ps(
29398 pSRC->sinc.table[ixabsv[7]+1],
29399 pSRC->sinc.table[ixabsv[6]+1],
29400 pSRC->sinc.table[ixabsv[5]+1],
29401 pSRC->sinc.table[ixabsv[4]+1],
29402 pSRC->sinc.table[ixabsv[3]+1],
29403 pSRC->sinc.table[ixabsv[2]+1],
29404 pSRC->sinc.table[ixabsv[1]+1],
29405 pSRC->sinc.table[ixabsv[0]+1]
29408 __m256
r = ma_mix_f32_fast__avx2(lo, hi, a);
29416 #if defined(MA_SUPPORT_NEON)
29417 static MA_INLINE float32x4_t ma_fabsf_neon(float32x4_t
x)
29419 return vabdq_f32(vmovq_n_f32(0),
x);
29422 static MA_INLINE float32x4_t ma_src_sinc__interpolation_factor__neon(
const ma_src* pSRC, float32x4_t
x)
29432 xabs = ma_fabsf_neon(
x);
29434 ixabs = vcvtq_s32_f32(xabs);
29436 ixabsv = (
int*)&ixabs;
29438 lo[0] = pSRC->sinc.table[ixabsv[0]];
29439 lo[1] = pSRC->sinc.table[ixabsv[1]];
29440 lo[2] = pSRC->sinc.table[ixabsv[2]];
29441 lo[3] = pSRC->sinc.table[ixabsv[3]];
29443 hi[0] = pSRC->sinc.table[ixabsv[0]+1];
29444 hi[1] = pSRC->sinc.table[ixabsv[1]+1];
29445 hi[2] = pSRC->sinc.table[ixabsv[2]+1];
29446 hi[3] = pSRC->sinc.table[ixabsv[3]+1];
29448 a = vsubq_f32(xabs, vcvtq_f32_s32(ixabs));
29449 r = ma_mix_f32_fast__neon(vld1q_f32(lo), vld1q_f32(hi), a);
29455 ma_uint64 ma_src_read_deinterleaved__sinc(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData)
29458 float inverseFactor;
29465 float* windowSamples;
29471 ma_assert(pSRC !=
NULL);
29472 ma_assert(frameCount > 0);
29473 ma_assert(ppSamplesOut !=
NULL);
29475 factor = (float)pSRC->config.sampleRateIn / pSRC->config.sampleRateOut;
29476 inverseFactor = 1/factor;
29478 windowWidth = (
ma_int32)pSRC->config.sinc.windowWidth;
29479 windowWidth2 = windowWidth*2;
29485 windowWidthSIMD = windowWidth;
29486 if (pSRC->useNEON) {
29487 windowWidthSIMD = (windowWidthSIMD + 1) & ~(1);
29488 }
else if (pSRC->useAVX512) {
29489 windowWidthSIMD = (windowWidthSIMD + 7) & ~(7);
29490 }
else if (pSRC->useAVX2) {
29491 windowWidthSIMD = (windowWidthSIMD + 3) & ~(3);
29492 }
else if (pSRC->useSSE2) {
29493 windowWidthSIMD = (windowWidthSIMD + 1) & ~(1);
29496 windowWidthSIMD2 = windowWidthSIMD*2;
29497 (
void)windowWidthSIMD2;
29499 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
void*) * pSRC->config.channels);
29507 for (
i = 0;
i < windowWidth2; ++
i) {
29508 iWindowF[
i] = (float)(
i - windowWidth);
29511 totalOutputFramesRead = 0;
29512 while (totalOutputFramesRead < frameCount) {
29513 ma_uint32 maxInputSamplesAvailableInCache;
29527 maxInputSamplesAvailableInCache = ma_countof(pSRC->sinc.input[0]) - (pSRC->config.sinc.windowWidth*2) - pSRC->sinc.windowPosInSamples;
29528 if (maxInputSamplesAvailableInCache > pSRC->sinc.inputFrameCount) {
29529 maxInputSamplesAvailableInCache = pSRC->sinc.inputFrameCount;
29533 if (pSRC->config.neverConsumeEndOfInput) {
29534 if (maxInputSamplesAvailableInCache >= pSRC->config.sinc.windowWidth) {
29535 maxInputSamplesAvailableInCache -= pSRC->config.sinc.windowWidth;
29537 maxInputSamplesAvailableInCache = 0;
29541 timeInBeg = pSRC->sinc.timeIn;
29542 timeInEnd = (float)(pSRC->sinc.windowPosInSamples + maxInputSamplesAvailableInCache);
29544 ma_assert(timeInBeg >= 0);
29545 ma_assert(timeInBeg <= timeInEnd);
29547 maxOutputFramesToRead = (
ma_uint64)(((timeInEnd - timeInBeg) * inverseFactor));
29549 outputFramesRemaining = frameCount - totalOutputFramesRead;
29550 outputFramesToRead = outputFramesRemaining;
29551 if (outputFramesToRead > maxOutputFramesToRead) {
29552 outputFramesToRead = maxOutputFramesToRead;
29555 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
29557 float timeIn = timeInBeg;
29559 for (iSample = 0; iSample < outputFramesToRead; iSample += 1) {
29560 float sampleOut = 0;
29561 float iTimeInF = ma_floorf(timeIn);
29567 windowSamples[0] = 0;
29568 for (
i = 1;
i < windowWidth2; ++
i) {
29569 windowSamples[
i] = pSRC->sinc.input[iChannel][iTimeIn +
i];
29572 #if defined(MA_SUPPORT_AVX2) || defined(MA_SUPPORT_AVX512)
29573 if (pSRC->useAVX2 || pSRC->useAVX512) {
29576 __m256 resolution256;
29584 t = _mm256_set1_ps((timeIn - iTimeInF));
29585 r = _mm256_set1_ps(0);
29587 windowWidth8 = windowWidthSIMD2 >> 3;
29588 for (iWindow8 = 0; iWindow8 < windowWidth8; iWindow8 += 1) {
29589 __m256
w = *((__m256*)iWindowF + iWindow8);
29591 __m256 xabs = _mm256_sub_ps(
t,
w);
29592 xabs = ma_fabsf_avx2(xabs);
29593 xabs = _mm256_mul_ps(xabs, resolution256);
29595 ixabs[iWindow8] = _mm256_cvttps_epi32(xabs);
29596 a[iWindow8] = _mm256_sub_ps(xabs, _mm256_cvtepi32_ps(ixabs[iWindow8]));
29599 for (iWindow8 = 0; iWindow8 < windowWidth8; iWindow8 += 1) {
29600 int* ixabsv = (
int*)&ixabs[iWindow8];
29602 __m256 lo = _mm256_set_ps(
29603 pSRC->sinc.table[ixabsv[7]],
29604 pSRC->sinc.table[ixabsv[6]],
29605 pSRC->sinc.table[ixabsv[5]],
29606 pSRC->sinc.table[ixabsv[4]],
29607 pSRC->sinc.table[ixabsv[3]],
29608 pSRC->sinc.table[ixabsv[2]],
29609 pSRC->sinc.table[ixabsv[1]],
29610 pSRC->sinc.table[ixabsv[0]]
29613 __m256 hi = _mm256_set_ps(
29614 pSRC->sinc.table[ixabsv[7]+1],
29615 pSRC->sinc.table[ixabsv[6]+1],
29616 pSRC->sinc.table[ixabsv[5]+1],
29617 pSRC->sinc.table[ixabsv[4]+1],
29618 pSRC->sinc.table[ixabsv[3]+1],
29619 pSRC->sinc.table[ixabsv[2]+1],
29620 pSRC->sinc.table[ixabsv[1]+1],
29621 pSRC->sinc.table[ixabsv[0]+1]
29624 __m256
s = *((__m256*)windowSamples + iWindow8);
29625 r = _mm256_add_ps(
r, _mm256_mul_ps(
s, ma_mix_f32_fast__avx2(lo, hi, a[iWindow8])));
29629 __m256
x = _mm256_hadd_ps(
r, _mm256_permute2f128_ps(
r,
r, 1));
29630 x = _mm256_hadd_ps(
x,
x);
29631 x = _mm256_hadd_ps(
x,
x);
29632 sampleOut += _mm_cvtss_f32(_mm256_castps256_ps128(
x));
29634 iWindow += windowWidth8 * 8;
29638 #if defined(MA_SUPPORT_SSE2)
29639 if (pSRC->useSSE2) {
29640 __m128
t = _mm_set1_ps((timeIn - iTimeInF));
29641 __m128
r = _mm_set1_ps(0);
29643 ma_int32 windowWidth4 = windowWidthSIMD2 >> 2;
29645 for (iWindow4 = 0; iWindow4 < windowWidth4; iWindow4 += 1) {
29646 __m128*
s = (__m128*)windowSamples + iWindow4;
29647 __m128*
w = (__m128*)iWindowF + iWindow4;
29649 __m128 a = ma_src_sinc__interpolation_factor__sse2(pSRC, _mm_sub_ps(
t, *
w));
29650 r = _mm_add_ps(
r, _mm_mul_ps(*
s, a));
29653 sampleOut += ((
float*)(&
r))[0];
29654 sampleOut += ((
float*)(&
r))[1];
29655 sampleOut += ((
float*)(&
r))[2];
29656 sampleOut += ((
float*)(&
r))[3];
29658 iWindow += windowWidth4 * 4;
29662 #if defined(MA_SUPPORT_NEON)
29663 if (pSRC->useNEON) {
29664 float32x4_t
t = vmovq_n_f32((timeIn - iTimeInF));
29665 float32x4_t
r = vmovq_n_f32(0);
29667 ma_int32 windowWidth4 = windowWidthSIMD2 >> 2;
29669 for (iWindow4 = 0; iWindow4 < windowWidth4; iWindow4 += 1) {
29670 float32x4_t*
s = (float32x4_t*)windowSamples + iWindow4;
29671 float32x4_t*
w = (float32x4_t*)iWindowF + iWindow4;
29673 float32x4_t a = ma_src_sinc__interpolation_factor__neon(pSRC, vsubq_f32(
t, *
w));
29674 r = vaddq_f32(
r, vmulq_f32(*
s, a));
29677 sampleOut += ((
float*)(&
r))[0];
29678 sampleOut += ((
float*)(&
r))[1];
29679 sampleOut += ((
float*)(&
r))[2];
29680 sampleOut += ((
float*)(&
r))[3];
29682 iWindow += windowWidth4 * 4;
29691 tScalar = (timeIn - iTimeIn);
29692 for (; iWindow < windowWidth2; iWindow += 1) {
29693 float s = windowSamples[iWindow];
29694 float w = iWindowF[iWindow];
29696 float a = ma_src_sinc__interpolation_factor(pSRC, (tScalar -
w));
29702 ppNextSamplesOut[iChannel][iSample] = (float)sampleOut;
29707 ppNextSamplesOut[iChannel] += outputFramesToRead;
29710 totalOutputFramesRead += outputFramesToRead;
29712 prevWindowPosInSamples = pSRC->sinc.windowPosInSamples;
29714 pSRC->sinc.timeIn += ((
ma_int64)outputFramesToRead * factor);
29715 pSRC->sinc.windowPosInSamples = (
ma_uint32)pSRC->sinc.timeIn;
29716 pSRC->sinc.inputFrameCount -= pSRC->sinc.windowPosInSamples - prevWindowPosInSamples;
29719 availableOutputFrames = (
ma_uint32)((timeInEnd - pSRC->sinc.timeIn) * inverseFactor);
29721 if (availableOutputFrames == 0) {
29722 size_t samplesToMove = ma_countof(pSRC->sinc.input[0]) - pSRC->sinc.windowPosInSamples;
29724 pSRC->sinc.timeIn -= ma_floorf(pSRC->sinc.timeIn);
29725 pSRC->sinc.windowPosInSamples = 0;
29728 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
29729 memmove(pSRC->sinc.input[iChannel], pSRC->sinc.input[iChannel] + ma_countof(pSRC->sinc.input[iChannel]) - samplesToMove, samplesToMove *
sizeof(*pSRC->sinc.input[iChannel]));
29734 if (pSRC->isEndOfInputLoaded) {
29735 pSRC->isEndOfInputLoaded =
MA_FALSE;
29743 ma_assert(pSRC->isEndOfInputLoaded ==
MA_FALSE);
29745 if (pSRC->sinc.inputFrameCount <= pSRC->config.sinc.windowWidth || availableOutputFrames == 0) {
29751 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
29752 ppInputDst[iChannel] = pSRC->sinc.input[iChannel] + pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount;
29756 framesToReadFromClient = ma_countof(pSRC->sinc.input[0]) - (pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount);
29758 framesReadFromClient = 0;
29759 if (framesToReadFromClient > 0) {
29760 framesReadFromClient = pSRC->config.onReadDeinterleaved(pSRC, framesToReadFromClient, (
void**)ppInputDst, pUserData);
29763 if (framesReadFromClient != framesToReadFromClient) {
29764 pSRC->isEndOfInputLoaded =
MA_TRUE;
29766 pSRC->isEndOfInputLoaded =
MA_FALSE;
29769 if (framesReadFromClient != 0) {
29770 pSRC->sinc.inputFrameCount += framesReadFromClient;
29773 if (pSRC->config.neverConsumeEndOfInput) {
29774 if ((pSRC->sinc.inputFrameCount * inverseFactor) <= pSRC->config.sinc.windowWidth) {
29778 if ((pSRC->sinc.inputFrameCount * inverseFactor) < 1) {
29785 leftoverFrames = ma_countof(pSRC->sinc.input[0]) - (pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount);
29786 if (leftoverFrames > 0) {
29787 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
29788 ma_zero_memory(pSRC->sinc.input[iChannel] + pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount, leftoverFrames *
sizeof(
float));
29794 return totalOutputFramesRead;
29806 if (formatOut == formatIn) {
29879 if (pInterleavedPCMFrames ==
NULL || ppDeinterleavedPCMFrames ==
NULL) {
29889 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
29891 for (iChannel = 0; iChannel <
channels; ++iChannel) {
29893 pDstS16[iPCMFrame] = pSrcS16[iPCMFrame*
channels+iChannel];
29900 const float* pSrcF32 = (
const float*)pInterleavedPCMFrames;
29902 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
29904 for (iChannel = 0; iChannel <
channels; ++iChannel) {
29905 float* pDstF32 = (
float*)ppDeinterleavedPCMFrames[iChannel];
29906 pDstF32[iPCMFrame] = pSrcF32[iPCMFrame*
channels+iChannel];
29915 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
29917 for (iChannel = 0; iChannel <
channels; ++iChannel) {
29918 void* pDst = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
29919 const void* pSrc = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*
channels+iChannel)*sampleSizeInBytes);
29920 memcpy(pDst, pSrc, sampleSizeInBytes);
29935 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
29937 for (iChannel = 0; iChannel <
channels; ++iChannel) {
29938 const ma_int16* pSrcS16 = (
const ma_int16*)ppDeinterleavedPCMFrames[iChannel];
29939 pDstS16[iPCMFrame*
channels+iChannel] = pSrcS16[iPCMFrame];
29946 float* pDstF32 = (
float*)pInterleavedPCMFrames;
29948 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
29950 for (iChannel = 0; iChannel <
channels; ++iChannel) {
29951 const float* pSrcF32 = (
const float*)ppDeinterleavedPCMFrames[iChannel];
29952 pDstF32[iPCMFrame*
channels+iChannel] = pSrcF32[iPCMFrame];
29961 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
29963 for (iChannel = 0; iChannel <
channels; ++iChannel) {
29964 void* pDst = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*
channels+iChannel)*sampleSizeInBytes);
29965 const void* pSrc = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
29966 memcpy(pDst, pSrc, sampleSizeInBytes);
29978 void* pUserDataForClient;
29979 } ma_pcm_converter_callback_data;
29983 ma_pcm_converter_callback_data* pData;
29988 pData = (ma_pcm_converter_callback_data*)pUserData;
29989 ma_assert(pData !=
NULL);
29991 pDSP = pData->pDSP;
29992 ma_assert(pDSP !=
NULL);
29994 return pDSP->onRead(pDSP, pFramesOut, frameCount, pData->pUserDataForClient);
29999 ma_pcm_converter_callback_data* pData;
30004 pData = (ma_pcm_converter_callback_data*)pUserData;
30005 ma_assert(pData !=
NULL);
30007 pDSP = pData->pDSP;
30008 ma_assert(pDSP !=
NULL);
30011 ma_assert(pDSP->isPreFormatConversionRequired ==
MA_FALSE);
30012 ma_assert(pDSP->isChannelRoutingRequired ==
MA_FALSE);
30013 ma_assert(pDSP->isSRCRequired ==
MA_FALSE);
30015 return pDSP->onRead(pDSP, pFramesOut, frameCount, pData->pUserDataForClient);
30020 ma_pcm_converter_callback_data* pData;
30025 pData = (ma_pcm_converter_callback_data*)pUserData;
30026 ma_assert(pData !=
NULL);
30028 pDSP = pData->pDSP;
30029 ma_assert(pDSP !=
NULL);
30031 if (!pDSP->isChannelRoutingAtStart) {
30034 if (pDSP->isSRCRequired) {
30042 ma_uint32 ma_pcm_converter__src_on_read_deinterleaved(
ma_src* pSRC,
ma_uint32 frameCount,
void** ppSamplesOut,
void* pUserData)
30044 ma_pcm_converter_callback_data* pData;
30049 pData = (ma_pcm_converter_callback_data*)pUserData;
30050 ma_assert(pData !=
NULL);
30052 pDSP = pData->pDSP;
30053 ma_assert(pDSP !=
NULL);
30056 if (pDSP->isChannelRoutingAtStart) {
30065 ma_pcm_converter_callback_data* pData;
30070 pData = (ma_pcm_converter_callback_data*)pUserData;
30071 ma_assert(pData !=
NULL);
30073 pDSP = pData->pDSP;
30074 ma_assert(pDSP !=
NULL);
30077 if (pDSP->isChannelRoutingAtStart) {
30080 if (pDSP->isSRCRequired) {
30092 if (pDSP ==
NULL) {
30096 ma_zero_object(pDSP);
30097 pDSP->onRead = pConfig->
onRead;
30157 pDSP->isSRCRequired =
MA_TRUE;
30160 pDSP->isChannelRoutingRequired =
MA_TRUE;
30164 if (!pDSP->isSRCRequired && !pDSP->isChannelRoutingRequired) {
30167 pDSP->isPostFormatConversionRequired =
MA_TRUE;
30170 pDSP->isPreFormatConversionRequired =
MA_TRUE;
30171 pDSP->isPostFormatConversionRequired =
MA_TRUE;
30175 if (!pDSP->isPreFormatConversionRequired && !pDSP->isPostFormatConversionRequired && !pDSP->isChannelRoutingRequired && !pDSP->isSRCRequired) {
30176 pDSP->isPassthrough =
MA_TRUE;
30181 pDSP->isChannelRoutingAtStart =
MA_TRUE;
30197 ma_pcm_converter__pre_format_converter_on_read,
30226 if (pDSP->isPreFormatConversionRequired) {
30227 postFormatConverterConfig.
onReadDeinterleaved = ma_pcm_converter__post_format_converter_on_read_deinterleaved;
30230 postFormatConverterConfig.
onRead = ma_pcm_converter__post_format_converter_on_read;
30245 ma_pcm_converter__src_on_read_deinterleaved,
30254 ma_copy_memory(&srcConfig.
sinc, &pConfig->
sinc,
sizeof(pConfig->
sinc));
30270 ma_pcm_converter__channel_router_on_read_deinterleaved,
30296 if (pDSP ==
NULL) {
30301 if (sampleRateIn == 0) {
30306 if (!pDSP->isDynamicSampleRateAllowed) {
30310 ma_atomic_exchange_32(&pDSP->src.config.sampleRateIn, sampleRateIn);
30311 return ma_pcm_converter_refresh_sample_rate(pDSP);
30316 if (pDSP ==
NULL) {
30321 if (sampleRateOut == 0) {
30326 if (!pDSP->isDynamicSampleRateAllowed) {
30330 ma_atomic_exchange_32(&pDSP->src.config.sampleRateOut, sampleRateOut);
30331 return ma_pcm_converter_refresh_sample_rate(pDSP);
30336 if (pDSP ==
NULL) {
30341 if (sampleRateIn == 0 || sampleRateOut == 0) {
30346 if (!pDSP->isDynamicSampleRateAllowed) {
30350 ma_atomic_exchange_32(&pDSP->src.config.sampleRateIn, sampleRateIn);
30351 ma_atomic_exchange_32(&pDSP->src.config.sampleRateOut, sampleRateOut);
30353 return ma_pcm_converter_refresh_sample_rate(pDSP);
30358 ma_pcm_converter_callback_data data;
30360 if (pDSP ==
NULL || pFramesOut ==
NULL) {
30365 if (pDSP->isPassthrough) {
30366 if (frameCount <= 0xFFFFFFFF) {
30367 return (
ma_uint32)pDSP->onRead(pDSP, pFramesOut, (
ma_uint32)frameCount, pDSP->pUserData);
30372 while (totalFramesRead < frameCount) {
30374 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
30375 ma_uint64 framesToReadRightNow = framesRemaining;
30376 if (framesToReadRightNow > 0xFFFFFFFF) {
30377 framesToReadRightNow = 0xFFFFFFFF;
30380 framesRead = pDSP->onRead(pDSP, pNextFramesOut, (
ma_uint32)framesToReadRightNow, pDSP->pUserData);
30381 if (framesRead == 0) {
30385 pNextFramesOut += framesRead * pDSP->channelRouter.config.channelsOut *
ma_get_bytes_per_sample(pDSP->formatConverterOut.config.formatOut);
30386 totalFramesRead += framesRead;
30389 return totalFramesRead;
30394 ma_assert(pDSP->isPostFormatConversionRequired ==
MA_TRUE);
30397 data.pUserDataForClient = pDSP->pUserData;
30404 const void* pDataIn;
30410 } ma_convert_frames__data;
30414 ma_convert_frames__data* pData;
30421 pData = (ma_convert_frames__data*)pUserData;
30422 ma_assert(pData !=
NULL);
30423 ma_assert(pData->totalFrameCount >= pData->iNextFrame);
30425 framesToRead = frameCount;
30426 framesRemaining = (pData->totalFrameCount - pData->iNextFrame);
30427 if (framesToRead > framesRemaining) {
30428 framesToRead = (
ma_uint32)framesRemaining;
30433 if (!pData->isFeedingZeros) {
30434 ma_copy_memory(pFramesOut, (
const ma_uint8*)pData->pDataIn + (frameSizeInBytes * pData->iNextFrame), frameSizeInBytes * framesToRead);
30436 ma_zero_memory(pFramesOut, frameSizeInBytes * framesToRead);
30439 pData->iNextFrame += framesToRead;
30440 return framesToRead;
30446 ma_zero_object(&config);
30459 ma_zero_object(&config);
30466 if (channelMapIn !=
NULL) {
30469 if (channelMapOut !=
NULL) {
30488 return ma_convert_frames_ex(pOut, formatOut, channelsOut, sampleRateOut, channelMapOut, pIn, formatIn, channelsIn, sampleRateIn, channelMapIn, frameCount);
30491 ma_uint64 ma_convert_frames_ex(
void* pOut,
ma_format formatOut,
ma_uint32 channelsOut,
ma_uint32 sampleRateOut,
ma_channel channelMapOut[
MA_MAX_CHANNELS],
const void* pIn,
ma_format formatIn,
ma_uint32 channelsIn,
ma_uint32 sampleRateIn,
ma_channel channelMapIn[
MA_MAX_CHANNELS],
ma_uint64 frameCount)
30494 ma_convert_frames__data data;
30499 if (frameCount == 0) {
30503 frameCountOut = ma_calculate_frame_count_after_src(sampleRateOut, sampleRateIn, frameCount);
30504 if (pOut ==
NULL) {
30505 return frameCountOut;
30508 data.pDataIn = pIn;
30509 data.formatIn = formatIn;
30510 data.channelsIn = channelsIn;
30511 data.totalFrameCount = frameCount;
30512 data.iNextFrame = 0;
30515 ma_zero_object(&converterConfig);
30517 converterConfig.
formatIn = formatIn;
30520 if (channelMapIn !=
NULL) {
30529 if (channelMapOut !=
NULL) {
30535 converterConfig.
onRead = ma_convert_frames__on_read;
30548 if (totalFramesRead < frameCountOut) {
30551 data.isFeedingZeros =
MA_TRUE;
30552 data.totalFrameCount = ((
ma_uint64)0xFFFFFFFF << 32) | 0xFFFFFFFF;
30553 data.pDataIn =
NULL;
30555 while (totalFramesRead < frameCountOut) {
30559 framesToRead = (frameCountOut - totalFramesRead);
30560 ma_assert(framesToRead > 0);
30562 framesJustRead =
ma_pcm_converter_read(&converter, ma_offset_ptr(pOut, totalFramesRead * bpf), framesToRead);
30563 totalFramesRead += framesJustRead;
30565 if (framesJustRead < framesToRead) {
30571 if (totalFramesRead < frameCountOut) {
30572 ma_zero_memory_64(ma_offset_ptr(pOut, totalFramesRead * bpf), ((frameCountOut - totalFramesRead) * bpf));
30573 totalFramesRead = frameCountOut;
30577 ma_assert(totalFramesRead == frameCountOut);
30578 return totalFramesRead;
30589 return encodedOffset & 0x7FFFFFFF;
30594 return encodedOffset & 0x80000000;
30599 ma_assert(pRB !=
NULL);
30605 ma_assert(pRB !=
NULL);
30611 return offsetLoopFlag | offsetInBytes;
30616 ma_assert(pOffsetInBytes !=
NULL);
30617 ma_assert(pOffsetLoopFlag !=
NULL);
30619 *pOffsetInBytes = ma_rb__extract_offset_in_bytes(encodedOffset);
30620 *pOffsetLoopFlag = ma_rb__extract_offset_loop_flag(encodedOffset);
30624 ma_result ma_rb_init_ex(
size_t subbufferSizeInBytes,
size_t subbufferCount,
size_t subbufferStrideInBytes,
void* pOptionalPreallocatedBuffer,
ma_rb* pRB)
30632 if (subbufferSizeInBytes == 0 || subbufferCount == 0) {
30636 if (subbufferSizeInBytes > maxSubBufferSize) {
30641 ma_zero_object(pRB);
30645 if (pOptionalPreallocatedBuffer !=
NULL) {
30647 pRB->
pBuffer = pOptionalPreallocatedBuffer;
30649 size_t bufferSizeInBytes;
30663 ma_zero_memory(pRB->
pBuffer, bufferSizeInBytes);
30672 return ma_rb_init_ex(bufferSizeInBytes, 1, 0, pOptionalPreallocatedBuffer, pRB);
30694 size_t bytesAvailable;
30695 size_t bytesRequested;
30697 if (pRB ==
NULL || pSizeInBytes ==
NULL || ppBufferOut ==
NULL) {
30703 ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
30706 ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
30712 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
30713 bytesAvailable = writeOffsetInBytes - readOffsetInBytes;
30718 bytesRequested = *pSizeInBytes;
30719 if (bytesRequested > bytesAvailable) {
30720 bytesRequested = bytesAvailable;
30723 *pSizeInBytes = bytesRequested;
30724 (*ppBufferOut) = ma_rb__get_read_ptr(pRB);
30742 if (pBufferOut != ma_rb__get_read_ptr(pRB)) {
30747 ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
30750 newReadOffsetInBytes = (
ma_uint32)(readOffsetInBytes + sizeInBytes);
30756 newReadOffsetLoopFlag = readOffsetLoopFlag;
30758 newReadOffsetInBytes = 0;
30759 newReadOffsetLoopFlag ^= 0x80000000;
30762 ma_atomic_exchange_32(&pRB->
encodedReadOffset, ma_rb__construct_offset(newReadOffsetLoopFlag, newReadOffsetInBytes));
30774 size_t bytesAvailable;
30775 size_t bytesRequested;
30777 if (pRB ==
NULL || pSizeInBytes ==
NULL || ppBufferOut ==
NULL) {
30783 ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
30786 ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
30793 if (writeOffsetLoopFlag == readOffsetLoopFlag) {
30796 bytesAvailable = readOffsetInBytes - writeOffsetInBytes;
30799 bytesRequested = *pSizeInBytes;
30800 if (bytesRequested > bytesAvailable) {
30801 bytesRequested = bytesAvailable;
30804 *pSizeInBytes = bytesRequested;
30805 *ppBufferOut = ma_rb__get_write_ptr(pRB);
30809 ma_zero_memory(*ppBufferOut, *pSizeInBytes);
30828 if (pBufferOut != ma_rb__get_write_ptr(pRB)) {
30833 ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
30836 newWriteOffsetInBytes = (
ma_uint32)(writeOffsetInBytes + sizeInBytes);
30842 newWriteOffsetLoopFlag = writeOffsetLoopFlag;
30844 newWriteOffsetInBytes = 0;
30845 newWriteOffsetLoopFlag ^= 0x80000000;
30848 ma_atomic_exchange_32(&pRB->
encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetLoopFlag, newWriteOffsetInBytes));
30868 ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
30871 ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
30873 newReadOffsetInBytes = readOffsetInBytes;
30874 newReadOffsetLoopFlag = readOffsetLoopFlag;
30877 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
30878 if ((readOffsetInBytes + offsetInBytes) > writeOffsetInBytes) {
30879 newReadOffsetInBytes = writeOffsetInBytes;
30881 newReadOffsetInBytes = (
ma_uint32)(readOffsetInBytes + offsetInBytes);
30887 newReadOffsetLoopFlag ^= 0x80000000;
30889 newReadOffsetInBytes = (
ma_uint32)(readOffsetInBytes + offsetInBytes);
30893 ma_atomic_exchange_32(&pRB->
encodedReadOffset, ma_rb__construct_offset(newReadOffsetInBytes, newReadOffsetLoopFlag));
30913 ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
30916 ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
30918 newWriteOffsetInBytes = writeOffsetInBytes;
30919 newWriteOffsetLoopFlag = writeOffsetLoopFlag;
30922 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
30926 newWriteOffsetLoopFlag ^= 0x80000000;
30928 newWriteOffsetInBytes = (
ma_uint32)(writeOffsetInBytes + offsetInBytes);
30931 if ((writeOffsetInBytes + offsetInBytes) > readOffsetInBytes) {
30932 newWriteOffsetInBytes = readOffsetInBytes;
30934 newWriteOffsetInBytes = (
ma_uint32)(writeOffsetInBytes + offsetInBytes);
30938 ma_atomic_exchange_32(&pRB->
encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetInBytes, newWriteOffsetLoopFlag));
30956 ma_rb__deconstruct_offset(readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
30959 ma_rb__deconstruct_offset(writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
30961 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
30962 return writeOffsetInBytes - readOffsetInBytes;
31011 ma_assert(pRB !=
NULL);
31025 ma_zero_object(pRB);
31032 result =
ma_rb_init_ex(subbufferSizeInFrames*bpf, subbufferCount, subbufferStrideInFrames*bpf, pOptionalPreallocatedBuffer, &pRB->
rb);
31059 size_t sizeInBytes;
31062 if (pRB ==
NULL || pSizeInFrames ==
NULL) {
31066 sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
31073 *pSizeInFrames = (
ma_uint32)(sizeInBytes / (
size_t)ma_pcm_rb_get_bpf(pRB));
31088 size_t sizeInBytes;
31095 sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
31102 *pSizeInFrames = (
ma_uint32)(sizeInBytes / ma_pcm_rb_get_bpf(pRB));
31187 return MA_MALLOC(sz);
31192 return MA_REALLOC(p, sz);
31206 if (alignment == 0) {
31210 extraBytes = alignment-1 +
sizeof(
void*);
31212 pUnaligned =
ma_malloc(sz + extraBytes);
31213 if (pUnaligned ==
NULL) {
31218 ((
void**)pAligned)[-1] = pUnaligned;
31235 case ma_format_s24:
return "24-bit Signed Integer (Tightly Packed)";
31238 default:
return "Invalid";
31246 pOut[
i] = ma_mix_f32(pInA[
i], pInB[
i], factor);
31270 #ifndef MA_NO_DECODING
31272 size_t ma_decoder_read_bytes(
ma_decoder* pDecoder,
void* pBufferOut,
size_t bytesToRead)
31276 ma_assert(pDecoder !=
NULL);
31277 ma_assert(pBufferOut !=
NULL);
31279 bytesRead = pDecoder->
onRead(pDecoder, pBufferOut, bytesToRead);
31289 ma_assert(pDecoder !=
NULL);
31291 wasSuccessful = pDecoder->
onSeek(pDecoder, byteOffset, origin);
31292 if (wasSuccessful) {
31300 return wasSuccessful;
31305 ma_assert(pDecoder !=
NULL);
31308 ma_uint64 bytesToSeekThisIteration = 0x7FFFFFFF;
31309 if (bytesToSeekThisIteration > byteOffset) {
31310 bytesToSeekThisIteration = byteOffset;
31317 byteOffset -= bytesToSeekThisIteration;
31321 while (byteOffset > 0) {
31322 ma_uint64 bytesToSeekThisIteration = 0x7FFFFFFF;
31323 if (bytesToSeekThisIteration > byteOffset) {
31324 bytesToSeekThisIteration = byteOffset;
31331 byteOffset -= bytesToSeekThisIteration;
31341 ma_zero_object(&config);
31342 config.
format = outputFormat;
31353 if (pConfig !=
NULL) {
31356 ma_zero_object(&config);
31366 ma_assert(pDecoder !=
NULL);
31411 size_t ma_decoder_internal_on_read__wav(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
31414 ma_assert(pDecoder !=
NULL);
31416 return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead);
31422 ma_assert(pDecoder !=
NULL);
31435 ma_assert(pDecoder !=
NULL);
31438 ma_assert(pWav !=
NULL);
31458 ma_assert(pWav !=
NULL);
31484 ma_assert(pConfig !=
NULL);
31485 ma_assert(pDecoder !=
NULL);
31488 pWav =
drwav_open(ma_decoder_internal_on_read__wav, ma_decoder_internal_on_seek__wav, pDecoder);
31489 if (pWav ==
NULL) {
31494 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__wav;
31495 pDecoder->
onUninit = ma_decoder_internal_on_uninit__wav;
31537 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__wav);
31549 #define MA_HAS_FLAC
31551 size_t ma_decoder_internal_on_read__flac(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
31554 ma_assert(pDecoder !=
NULL);
31556 return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead);
31562 ma_assert(pDecoder !=
NULL);
31575 ma_assert(pDecoder !=
NULL);
31578 ma_assert(pFlac !=
NULL);
31598 ma_assert(pFlac !=
NULL);
31624 ma_assert(pConfig !=
NULL);
31625 ma_assert(pDecoder !=
NULL);
31628 pFlac =
drflac_open(ma_decoder_internal_on_read__flac, ma_decoder_internal_on_seek__flac, pDecoder);
31629 if (pFlac ==
NULL) {
31634 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__flac;
31635 pDecoder->
onUninit = ma_decoder_internal_on_uninit__flac;
31654 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__flac);
31665 #ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
31666 #define MA_HAS_VORBIS
31669 #define MA_VORBIS_DATA_CHUNK_SIZE 4096
31676 size_t dataCapacity;
31679 float** ppPacketData;
31680 } ma_vorbis_decoder;
31682 ma_uint32 ma_vorbis_decoder_read_pcm_frames(ma_vorbis_decoder* pVorbis,
ma_decoder* pDecoder,
void* pSamplesOut,
ma_uint32 frameCount)
31684 float* pSamplesOutF;
31687 ma_assert(pVorbis !=
NULL);
31688 ma_assert(pDecoder !=
NULL);
31690 pSamplesOutF = (
float*)pSamplesOut;
31692 totalFramesRead = 0;
31693 while (frameCount > 0) {
31695 while (pVorbis->framesRemaining > 0 && frameCount > 0) {
31698 pSamplesOutF[0] = pVorbis->ppPacketData[iChannel][pVorbis->framesConsumed];
31702 pVorbis->framesConsumed += 1;
31703 pVorbis->framesRemaining -= 1;
31705 totalFramesRead += 1;
31708 if (frameCount == 0) {
31712 ma_assert(pVorbis->framesRemaining == 0);
31718 int consumedDataSize;
31720 if (pVorbis->dataSize > INT_MAX) {
31726 if (consumedDataSize != 0) {
31727 size_t leftoverDataSize = (pVorbis->dataSize - (size_t)consumedDataSize);
31729 for (
i = 0;
i < leftoverDataSize; ++
i) {
31730 pVorbis->pData[
i] = pVorbis->pData[
i + consumedDataSize];
31733 pVorbis->dataSize = leftoverDataSize;
31734 pVorbis->framesConsumed = 0;
31735 pVorbis->framesRemaining = samplesRead;
31740 if (pVorbis->dataCapacity == pVorbis->dataSize) {
31742 size_t newCap = pVorbis->dataCapacity + MA_VORBIS_DATA_CHUNK_SIZE;
31746 if (pNewData ==
NULL) {
31747 return totalFramesRead;
31750 pVorbis->pData = pNewData;
31751 pVorbis->dataCapacity = newCap;
31755 bytesRead = ma_decoder_read_bytes(pDecoder, pVorbis->pData + pVorbis->dataSize, (pVorbis->dataCapacity - pVorbis->dataSize));
31756 if (bytesRead == 0) {
31757 return totalFramesRead;
31760 pVorbis->dataSize += bytesRead;
31765 return totalFramesRead;
31772 ma_assert(pVorbis !=
NULL);
31773 ma_assert(pDecoder !=
NULL);
31785 pVorbis->framesConsumed = 0;
31786 pVorbis->framesRemaining = 0;
31787 pVorbis->dataSize = 0;
31789 while (frameIndex > 0) {
31792 if (framesToRead > frameIndex) {
31796 framesRead = ma_vorbis_decoder_read_pcm_frames(pVorbis, pDecoder,
buffer, framesToRead);
31797 if (framesRead == 0) {
31801 frameIndex -= framesRead;
31810 ma_vorbis_decoder* pVorbis = (ma_vorbis_decoder*)pDecoder->
pInternalDecoder;
31811 ma_assert(pVorbis !=
NULL);
31813 return ma_vorbis_decoder_seek_to_pcm_frame(pVorbis, pDecoder, frameIndex);
31818 ma_vorbis_decoder* pVorbis = (ma_vorbis_decoder*)pDecoder->
pInternalDecoder;
31819 ma_assert(pVorbis !=
NULL);
31831 ma_vorbis_decoder* pVorbis;
31836 ma_assert(pDecoder !=
NULL);
31840 ma_assert(pVorbis !=
NULL);
31842 return ma_vorbis_decoder_read_pcm_frames(pVorbis, pDecoder, pSamplesOut, frameCount);
31856 size_t dataSize = 0;
31857 size_t dataCapacity = 0;
31860 size_t vorbisDataSize;
31861 ma_vorbis_decoder* pVorbis;
31863 ma_assert(pConfig !=
NULL);
31864 ma_assert(pDecoder !=
NULL);
31872 int vorbisError = 0;
31873 int consumedDataSize = 0;
31875 dataCapacity += MA_VORBIS_DATA_CHUNK_SIZE;
31877 if (pNewData ==
NULL) {
31885 bytesRead = ma_decoder_read_bytes(pDecoder, pData + dataSize, (dataCapacity - dataSize));
31886 if (bytesRead == 0) {
31890 dataSize += bytesRead;
31891 if (dataSize > INT_MAX) {
31896 if (pInternalVorbis !=
NULL) {
31901 size_t leftoverDataSize = (dataSize - (size_t)consumedDataSize);
31903 for (
i = 0;
i < leftoverDataSize; ++
i) {
31904 pData[
i] = pData[
i + consumedDataSize];
31907 dataSize = leftoverDataSize;
31929 vorbisDataSize =
sizeof(ma_vorbis_decoder) +
sizeof(
float)*vorbisInfo.
max_frame_size;
31930 pVorbis = (ma_vorbis_decoder*)
ma_malloc(vorbisDataSize);
31931 if (pVorbis ==
NULL) {
31937 ma_zero_memory(pVorbis, vorbisDataSize);
31938 pVorbis->pInternalVorbis = pInternalVorbis;
31939 pVorbis->pData = pData;
31940 pVorbis->dataSize = dataSize;
31941 pVorbis->dataCapacity = dataCapacity;
31943 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__vorbis;
31944 pDecoder->
onUninit = ma_decoder_internal_on_uninit__vorbis;
31954 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__vorbis);
31970 size_t ma_decoder_internal_on_read__mp3(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
31973 ma_assert(pDecoder !=
NULL);
31975 return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead);
31981 ma_assert(pDecoder !=
NULL);
31994 ma_assert(pDecoder !=
NULL);
31998 ma_assert(pMP3 !=
NULL);
32009 ma_assert(pMP3 !=
NULL);
32037 ma_assert(pConfig !=
NULL);
32038 ma_assert(pDecoder !=
NULL);
32041 if (pMP3 ==
NULL) {
32056 ma_zero_object(&mp3Config);
32059 if (!
drmp3_init(pMP3, ma_decoder_internal_on_read__mp3, ma_decoder_internal_on_seek__mp3, pDecoder, &mp3Config)) {
32064 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__mp3;
32065 pDecoder->
onUninit = ma_decoder_internal_on_uninit__mp3;
32075 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__mp3);
32094 ma_assert(pDecoder !=
NULL);
32098 return (
ma_uint32)ma_decoder_read_bytes(pDecoder, pSamplesOut, frameCount * bpf) / bpf;
32106 ma_assert(pDecoder !=
NULL);
32114 if (totalBytesToSeek < 0x7FFFFFFF) {
32121 totalBytesToSeek -= 0x7FFFFFFF;
32123 while (totalBytesToSeek > 0) {
32124 ma_uint64 bytesToSeekThisIteration = totalBytesToSeek;
32125 if (bytesToSeekThisIteration > 0x7FFFFFFF) {
32126 bytesToSeekThisIteration = 0x7FFFFFFF;
32134 totalBytesToSeek -= bytesToSeekThisIteration;
32162 ma_assert(pConfigIn !=
NULL);
32163 ma_assert(pConfigOut !=
NULL);
32164 ma_assert(pDecoder !=
NULL);
32166 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__raw;
32167 pDecoder->
onUninit = ma_decoder_internal_on_uninit__raw;
32176 result = ma_decoder__init_dsp(pDecoder, pConfigOut, ma_decoder_internal_on_read_pcm_frames__raw);
32186 ma_assert(pConfig !=
NULL);
32188 if (pDecoder ==
NULL) {
32192 ma_zero_object(pDecoder);
32194 if (onRead ==
NULL || onSeek ==
NULL) {
32198 pDecoder->
onRead = onRead;
32199 pDecoder->
onSeek = onSeek;
32211 config = ma_decoder_config_init_copy(pConfig);
32213 result = ma_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
32219 return ma_decoder_init_wav__internal(&config, pDecoder);
32230 config = ma_decoder_config_init_copy(pConfig);
32232 result = ma_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
32238 return ma_decoder_init_flac__internal(&config, pDecoder);
32249 config = ma_decoder_config_init_copy(pConfig);
32251 result = ma_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
32256 #ifdef MA_HAS_VORBIS
32257 return ma_decoder_init_vorbis__internal(&config, pDecoder);
32268 config = ma_decoder_config_init_copy(pConfig);
32270 result = ma_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
32276 return ma_decoder_init_mp3__internal(&config, pDecoder);
32287 config = ma_decoder_config_init_copy(pConfigOut);
32289 result = ma_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
32294 return ma_decoder_init_raw__internal(pConfigIn, &config, pDecoder);
32301 ma_assert(pConfig !=
NULL);
32302 ma_assert(pDecoder !=
NULL);
32315 result = ma_decoder_init_wav__internal(pConfig, pDecoder);
32323 result = ma_decoder_init_flac__internal(pConfig, pDecoder);
32329 #ifdef MA_HAS_VORBIS
32331 result = ma_decoder_init_vorbis__internal(pConfig, pDecoder);
32339 result = ma_decoder_init_mp3__internal(pConfig, pDecoder);
32358 config = ma_decoder_config_init_copy(pConfig);
32360 result = ma_decoder__preinit(onRead, onSeek, pUserData, &config, pDecoder);
32365 return ma_decoder_init__internal(onRead, onSeek, pUserData, &config, pDecoder);
32369 size_t ma_decoder__on_read_memory(
ma_decoder* pDecoder,
void* pBufferOut,
size_t bytesToRead)
32371 size_t bytesRemaining;
32376 if (bytesToRead > bytesRemaining) {
32377 bytesToRead = bytesRemaining;
32380 if (bytesToRead > 0) {
32385 return bytesToRead;
32391 if (byteOffset > 0) {
32416 ma_result result = ma_decoder__preinit(ma_decoder__on_read_memory, ma_decoder__on_seek_memory,
NULL, pConfig, pDecoder);
32421 if (pData ==
NULL || dataSize == 0) {
32438 config = ma_decoder_config_init_copy(pConfig);
32440 result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
32445 return ma_decoder_init__internal(ma_decoder__on_read_memory, ma_decoder__on_seek_memory,
NULL, &config, pDecoder);
32453 config = ma_decoder_config_init_copy(pConfig);
32455 result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
32461 return ma_decoder_init_wav__internal(&config, pDecoder);
32472 config = ma_decoder_config_init_copy(pConfig);
32474 result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
32480 return ma_decoder_init_flac__internal(&config, pDecoder);
32491 config = ma_decoder_config_init_copy(pConfig);
32493 result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
32498 #ifdef MA_HAS_VORBIS
32499 return ma_decoder_init_vorbis__internal(&config, pDecoder);
32510 config = ma_decoder_config_init_copy(pConfig);
32512 result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
32518 return ma_decoder_init_mp3__internal(&config, pDecoder);
32529 config = ma_decoder_config_init_copy(pConfigOut);
32531 result = ma_decoder__preinit_memory(pData, dataSize, &config, pDecoder);
32536 return ma_decoder_init_raw__internal(pConfigIn, &config, pDecoder);
32539 #ifndef MA_NO_STDIO
32541 #if !defined(_MSC_VER) && !defined(__DMC__)
32542 #include <strings.h>
32545 const char* ma_path_file_name(
const char* path)
32547 const char* fileName;
32549 if (path ==
NULL) {
32556 while (path[0] !=
'\0') {
32557 if (path[0] ==
'/' || path[0] ==
'\\') {
32565 while (fileName[0] !=
'\0' && (fileName[0] ==
'/' || fileName[0] ==
'\\')) {
32572 const char* ma_path_extension(
const char* path)
32574 const char* extension;
32575 const char* lastOccurance;
32577 if (path ==
NULL) {
32581 extension = ma_path_file_name(path);
32582 lastOccurance =
NULL;
32585 while (extension[0] !=
'\0') {
32586 if (extension[0] ==
'.') {
32588 lastOccurance = extension;
32594 return (lastOccurance !=
NULL) ? lastOccurance : extension;
32597 ma_bool32 ma_path_extension_equal(
const char* path,
const char* extension)
32602 if (path ==
NULL || extension ==
NULL) {
32607 ext2 = ma_path_extension(path);
32609 #if defined(_MSC_VER) || defined(__DMC__)
32610 return _stricmp(ext1, ext2) == 0;
32612 return strcasecmp(ext1, ext2) == 0;
32616 size_t ma_decoder__on_read_stdio(
ma_decoder* pDecoder,
void* pBufferOut,
size_t bytesToRead)
32618 return fread(pBufferOut, 1, bytesToRead, (FILE*)pDecoder->
pUserData);
32630 if (pDecoder ==
NULL) {
32634 ma_zero_object(pDecoder);
32636 if (pFilePath ==
NULL || pFilePath[0] ==
'\0') {
32640 #if defined(_MSC_VER) && _MSC_VER >= 1400
32641 if (fopen_s(&pFile, pFilePath,
"rb") != 0) {
32645 pFile = fopen(pFilePath,
"rb");
32646 if (pFile ==
NULL) {
32660 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
32666 if (ma_path_extension_equal(pFilePath,
"wav")) {
32676 if (ma_path_extension_equal(pFilePath,
"flac")) {
32686 if (ma_path_extension_equal(pFilePath,
"mp3")) {
32696 return ma_decoder_init(ma_decoder__on_read_stdio, ma_decoder__on_seek_stdio, pDecoder->
pUserData, pConfig, pDecoder);
32701 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
32711 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
32721 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
32731 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
32742 if (pDecoder ==
NULL) {
32750 #ifndef MA_NO_STDIO
32752 if (pDecoder->
onRead == ma_decoder__on_read_stdio) {
32762 if (pDecoder ==
NULL) {
32775 if (pDecoder ==
NULL) {
32784 if (pDecoder ==
NULL) {
32802 void* pPCMFramesOut;
32804 ma_assert(pDecoder !=
NULL);
32806 totalFrameCount = 0;
32810 dataCapInFrames = 0;
32811 pPCMFramesOut =
NULL;
32817 if (totalFrameCount == dataCapInFrames) {
32818 void* pNewPCMFramesOut;
32819 ma_uint64 newDataCapInFrames = dataCapInFrames*2;
32820 if (newDataCapInFrames == 0) {
32821 newDataCapInFrames = 4096;
32830 pNewPCMFramesOut = (
void*)
ma_realloc(pPCMFramesOut, (
size_t)(newDataCapInFrames * bpf));
32831 if (pNewPCMFramesOut ==
NULL) {
32836 dataCapInFrames = newDataCapInFrames;
32837 pPCMFramesOut = pNewPCMFramesOut;
32840 frameCountToTryReading = dataCapInFrames - totalFrameCount;
32841 ma_assert(frameCountToTryReading > 0);
32844 totalFrameCount += framesJustRead;
32846 if (framesJustRead < frameCountToTryReading) {
32852 if (pConfigOut !=
NULL) {
32859 if (ppPCMFramesOut !=
NULL) {
32860 *ppPCMFramesOut = pPCMFramesOut;
32865 if (pFrameCountOut !=
NULL) {
32866 *pFrameCountOut = totalFrameCount;
32873 #ifndef MA_NO_STDIO
32880 if (pFrameCountOut !=
NULL) {
32881 *pFrameCountOut = 0;
32883 if (ppPCMFramesOut !=
NULL) {
32884 *ppPCMFramesOut =
NULL;
32887 if (pFilePath ==
NULL) {
32891 config = ma_decoder_config_init_copy(pConfig);
32898 return ma_decoder__full_decode_and_uninit(&
decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
32908 if (pFrameCountOut !=
NULL) {
32909 *pFrameCountOut = 0;
32911 if (ppPCMFramesOut !=
NULL) {
32912 *ppPCMFramesOut =
NULL;
32915 if (pData ==
NULL || dataSize == 0) {
32919 config = ma_decoder_config_init_copy(pConfig);
32926 return ma_decoder__full_decode_and_uninit(&
decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
32941 if (pSineWave ==
NULL) {
32944 ma_zero_object(pSineWave);
32946 if (amplitude == 0 || periodsPerSecond == 0) {
32950 if (amplitude > 1) {
32953 if (amplitude < -1) {
32959 pSineWave->
delta = MA_TAU_D / sampleRate;
32960 pSineWave->
time = 0;
32972 if (pSineWave ==
NULL) {
32976 if (ppFrames !=
NULL) {
32978 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
32985 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
32986 ppFrames[0][iFrame*
channels + iChannel] =
s;
32989 for (iChannel = 0; iChannel <
channels; iChannel += 1) {
32990 ppFrames[iChannel][iFrame] =
s;
33001 #if defined(_MSC_VER)
33002 #pragma warning(pop)