diff --git a/tests/ma_debug_playback.c b/tests/ma_debug_playback.c deleted file mode 100644 index fccb0312..00000000 --- a/tests/ma_debug_playback.c +++ /dev/null @@ -1,175 +0,0 @@ - -#define MA_LOG_LEVEL MA_LOG_LEVEL_VERBOSE -#define MA_DEBUG_OUTPUT -#define MINIAUDIO_IMPLEMENTATION -#include "../miniaudio.h" - -int print_context_info(ma_context* pContext) -{ - ma_result result = MA_SUCCESS; - ma_device_info* pPlaybackDeviceInfos; - ma_uint32 playbackDeviceCount; - ma_device_info* pCaptureDeviceInfos; - ma_uint32 captureDeviceCount; - - printf("BACKEND: %s\n", ma_get_backend_name(pContext->backend)); - - // Enumeration. - printf(" Enumerating Devices... "); - { - result = ma_context_get_devices(pContext, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount); - if (result == MA_SUCCESS) { - printf("Done\n"); - } else { - printf("Failed\n"); - goto done; - } - - printf(" Playback Devices (%d)\n", playbackDeviceCount); - for (ma_uint32 iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) { - printf(" %d: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name); - } - - printf(" Capture Devices (%d)\n", captureDeviceCount); - for (ma_uint32 iDevice = 0; iDevice < captureDeviceCount; ++iDevice) { - printf(" %d: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name); - } - } - - // Device Information. - printf(" Getting Device Information...\n"); - { - printf(" Playback Devices (%d)\n", playbackDeviceCount); - for (ma_uint32 iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) { - printf(" %d: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name); - - result = ma_context_get_device_info(pContext, ma_device_type_playback, &pPlaybackDeviceInfos[iDevice].id, ma_share_mode_shared, &pPlaybackDeviceInfos[iDevice]); - if (result == MA_SUCCESS) { - printf(" Name: %s\n", pPlaybackDeviceInfos[iDevice].name); - printf(" Min Channels: %d\n", pPlaybackDeviceInfos[iDevice].minChannels); - printf(" Max Channels: %d\n", pPlaybackDeviceInfos[iDevice].maxChannels); - printf(" Min Sample Rate: %d\n", pPlaybackDeviceInfos[iDevice].minSampleRate); - printf(" Max Sample Rate: %d\n", pPlaybackDeviceInfos[iDevice].maxSampleRate); - printf(" Format Count: %d\n", pPlaybackDeviceInfos[iDevice].formatCount); - for (ma_uint32 iFormat = 0; iFormat < pPlaybackDeviceInfos[iDevice].formatCount; ++iFormat) { - printf(" %s\n", ma_get_format_name(pPlaybackDeviceInfos[iDevice].formats[iFormat])); - } - } else { - printf(" ERROR\n"); - } - } - - printf(" Capture Devices (%d)\n", captureDeviceCount); - for (ma_uint32 iDevice = 0; iDevice < captureDeviceCount; ++iDevice) { - printf(" %d: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name); - - result = ma_context_get_device_info(pContext, ma_device_type_capture, &pCaptureDeviceInfos[iDevice].id, ma_share_mode_shared, &pCaptureDeviceInfos[iDevice]); - if (result == MA_SUCCESS) { - printf(" Name: %s\n", pCaptureDeviceInfos[iDevice].name); - printf(" Min Channels: %d\n", pCaptureDeviceInfos[iDevice].minChannels); - printf(" Max Channels: %d\n", pCaptureDeviceInfos[iDevice].maxChannels); - printf(" Min Sample Rate: %d\n", pCaptureDeviceInfos[iDevice].minSampleRate); - printf(" Max Sample Rate: %d\n", pCaptureDeviceInfos[iDevice].maxSampleRate); - printf(" Format Count: %d\n", pCaptureDeviceInfos[iDevice].formatCount); - for (ma_uint32 iFormat = 0; iFormat < pCaptureDeviceInfos[iDevice].formatCount; ++iFormat) { - printf(" %s\n", ma_get_format_name(pCaptureDeviceInfos[iDevice].formats[iFormat])); - } - } else { - printf(" ERROR\n"); - } - } - } - -done: - printf("\n"); - return (result == MA_SUCCESS) ? 0 : -1; -} - -int print_device_info(ma_device* pDevice) -{ - printf("DEVICE NAME: %s\n", pDevice->name); - printf(" Format: %s -> %s\n", ma_get_format_name(pDevice->format), ma_get_format_name(pDevice->internalFormat)); - printf(" Channels: %d -> %d\n", pDevice->channels, pDevice->internalChannels); - printf(" Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->internalSampleRate); - printf(" Buffer Size: %d\n", pDevice->bufferSizeInFrames); - printf(" Periods: %d\n", pDevice->periods); - - return 0; -} - -ma_uint32 on_send(ma_device* pDevice, ma_uint32 frameCount, void* pFramesOut) -{ - ma_sine_wave* pSineWave = (ma_sine_wave*)pDevice->pUserData; - ma_assert(pSineWave != NULL); - - float* pFramesOutF32 = (float*)pFramesOut; - - for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) { - float sample; - ma_sine_wave_read(pSineWave, 1, &sample); - for (ma_uint32 iChannel = 0; iChannel < pDevice->channels; ++iChannel) { - pFramesOutF32[iChannel] = sample; - } - - pFramesOutF32 += pDevice->channels; - } - - return frameCount; -} - -int main(int argc, char** argv) -{ - ma_result result; - - ma_sine_wave sineWave; - result = ma_sine_wave_init(0.2, 400, 44100, &sineWave); - if (result != MA_SUCCESS) { - printf("Failed to initialize sine wave.\n"); - return -1; - } - - // Separate context for this test. - ma_context_config contextConfig = ma_context_config_init(NULL); // <-- Don't need a log callback because we're using debug output instead. - ma_context context; - result = ma_context_init(NULL, 0, &contextConfig, &context); - if (result != MA_SUCCESS) { - printf("Failed to initialize context.\n"); - return -1; - } - - print_context_info(&context); - - - // Device. - ma_device_config deviceConfig = ma_device_config_init_playback(ma_format_f32, 2, 44100, on_send); - deviceConfig.bufferSizeInFrames = 32768; - - ma_device device; - result = ma_device_init(&context, ma_device_type_playback, NULL, &deviceConfig, &sineWave, &device); - if (result != MA_SUCCESS) { - ma_context_uninit(&context); - printf("Failed to initialize device.\n"); - return -1; - } - - print_device_info(&device); - - - // Start playback. - result = ma_device_start(&device); - if (result != MA_SUCCESS) { - ma_device_uninit(&device); - ma_context_uninit(&context); - printf("Failed to start device.\n"); - return -1; - } - - - printf("Press Enter to quit...\n"); - getchar(); - - - ma_device_uninit(&device); - ma_context_uninit(&context); - return 0; -} diff --git a/tests/ma_dithering.c b/tests/ma_dithering.c deleted file mode 100644 index 9ef36f6d..00000000 --- a/tests/ma_dithering.c +++ /dev/null @@ -1,148 +0,0 @@ -#define MA_DEBUG_OUTPUT -#define MA_USE_REFERENCE_CONVERSION_APIS -#define MINIAUDIO_IMPLEMENTATION -#include "../miniaudio.h" - -// Two converters are needed here. One for converting f32 samples from the sine wave generator to the input format, -// and another for converting the input format to the output format for device output. -ma_sine_wave sineWave; -ma_format_converter converterIn; -ma_format_converter converterOut; - -ma_uint32 on_convert_samples_in(ma_format_converter* pConverter, ma_uint32 frameCount, void* pFrames, void* pUserData) -{ - (void)pUserData; - ma_assert(pConverter->config.formatIn == ma_format_f32); - - ma_sine_wave* pSineWave = (ma_sine_wave*)pConverter->config.pUserData; - ma_assert(pSineWave); - - return (ma_uint32)ma_sine_wave_read_f32(pSineWave, frameCount, (float*)pFrames); -} - -ma_uint32 on_convert_samples_out(ma_format_converter* pConverter, ma_uint32 frameCount, void* pFrames, void* pUserData) -{ - (void)pUserData; - - ma_format_converter* pConverterIn = (ma_format_converter*)pConverter->config.pUserData; - ma_assert(pConverterIn != NULL); - - return (ma_uint32)ma_format_converter_read(pConverterIn, frameCount, pFrames, NULL); -} - -void on_send_to_device__original(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) -{ - ma_assert(pDevice->playback.format == ma_format_f32); - ma_assert(pDevice->playback.channels == 1); - - ma_sine_wave_read_f32(&sineWave, frameCount, (float*)pOutput); - - (void)pDevice; - (void)pInput; -} - -void on_send_to_device__dithered(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) -{ - ma_assert(pDevice->playback.channels == 1); - - ma_format_converter* pConverter = (ma_format_converter*)pDevice->pUserData; - ma_assert(pConverter != NULL); - ma_assert(pDevice->playback.format == pConverter->config.formatOut); - - ma_format_converter_read(pConverter, frameCount, pOutput, NULL); - - (void)pInput; -} - -int do_dithering_test() -{ - ma_device_config config; - ma_device device; - ma_result result; - - config = ma_device_config_init(ma_device_type_playback); - config.playback.format = ma_format_f32; - config.playback.channels = 1; - config.sampleRate = 0; - config.dataCallback = on_send_to_device__original; - - // We first play the sound the way it's meant to be played. - result = ma_device_init(NULL, &config, &device); - if (result != MA_SUCCESS) { - return -1; - } - - ma_sine_wave_init(0.5, 400, device.sampleRate, &sineWave); - - result = ma_device_start(&device); - if (result != MA_SUCCESS) { - return -2; - } - - printf("Press Enter to play enable dithering.\n"); - getchar(); - ma_device_uninit(&device); - - - ma_format srcFormat = ma_format_s24; - ma_format dstFormat = ma_format_u8; - ma_dither_mode ditherMode = ma_dither_mode_triangle; - - ma_format_converter_config converterInConfig = ma_format_converter_config_init_new(); - converterInConfig.formatIn = ma_format_f32; // <-- From the sine wave generator. - converterInConfig.formatOut = srcFormat; - converterInConfig.channels = config.playback.channels; - converterInConfig.ditherMode = ma_dither_mode_none; - converterInConfig.onRead = on_convert_samples_in; - converterInConfig.pUserData = &sineWave; - result = ma_format_converter_init(&converterInConfig, &converterIn); - if (result != MA_SUCCESS) { - return -3; - } - - ma_format_converter_config converterOutConfig = ma_format_converter_config_init_new(); - converterOutConfig.formatIn = srcFormat; - converterOutConfig.formatOut = dstFormat; - converterOutConfig.channels = config.playback.channels; - converterOutConfig.ditherMode = ditherMode; - converterOutConfig.onRead = on_convert_samples_out; - converterOutConfig.pUserData = &converterIn; - result = ma_format_converter_init(&converterOutConfig, &converterOut); - if (result != MA_SUCCESS) { - return -3; - } - - config.playback.format = dstFormat; - config.dataCallback = on_send_to_device__dithered; - config.pUserData = &converterOut; - - result = ma_device_init(NULL, &config, &device); - if (result != MA_SUCCESS) { - return -1; - } - - // Now we play the sound after it's run through a dithered format converter. - ma_sine_wave_init(0.5, 400, device.sampleRate, &sineWave); - - result = ma_device_start(&device); - if (result != MA_SUCCESS) { - return -2; - } - - printf("Press Enter to stop.\n"); - getchar(); - - return 0; -} - -int main(int argc, char** argv) -{ - (void)argc; - (void)argv; - - - do_dithering_test(); - - - return 0; -} \ No newline at end of file diff --git a/tests/ma_no_device_io.c b/tests/ma_no_device_io.c deleted file mode 100644 index a40270c6..00000000 --- a/tests/ma_no_device_io.c +++ /dev/null @@ -1,34 +0,0 @@ -// Just a simple test to check that MA_NO_DEVICE_IO compiles. - -#include "../extras/dr_flac.h" -#include "../extras/dr_mp3.h" -#include "../extras/dr_wav.h" - -#define MA_NO_DEVICE_IO -#define MINIAUDIO_IMPLEMENTATION -#include "../miniaudio.h" - -int main(int argc, char** argv) -{ - (void)argc; - (void)argv; - - ma_result result = MA_ERROR; - - ma_pcm_converter_config dspConfig = ma_pcm_converter_config_init_new(); - ma_pcm_converter converter; - result = ma_pcm_converter_init(&dspConfig, &converter); - - ma_decoder_config decoderConfig = ma_decoder_config_init(ma_format_unknown, 0, 0); - ma_decoder decoder; - result = ma_decoder_init_file("res/sine_s16_mono_48000.wav", &decoderConfig, &decoder); - - return result; -} - -#define DR_FLAC_IMPLEMENTATION -#include "../extras/dr_flac.h" -#define DR_MP3_IMPLEMENTATION -#include "../extras/dr_mp3.h" -#define DR_WAV_IMPLEMENTATION -#include "../extras/dr_wav.h" diff --git a/tests/ma_profiling.c b/tests/ma_profiling.c deleted file mode 100644 index ad814ba3..00000000 --- a/tests/ma_profiling.c +++ /dev/null @@ -1,1172 +0,0 @@ -#define MINIAUDIO_IMPLEMENTATION -#include "../miniaudio.h" - -typedef enum -{ - simd_mode_scalar = 0, - simd_mode_sse2, - simd_mode_avx2, - simd_mode_avx512, - simd_mode_neon -} simd_mode; - -const char* simd_mode_to_string(simd_mode mode) -{ - switch (mode) { - case simd_mode_scalar: return "Reference"; - case simd_mode_sse2: return "SSE2"; - case simd_mode_avx2: return "AVX2"; - case simd_mode_avx512: return "AVX-512"; - case simd_mode_neon: return "NEON"; - } - - return "Unknown"; -} - -const char* ma_src_algorithm_to_string(ma_src_algorithm algorithm) -{ - switch (algorithm) { - case ma_src_algorithm_none: return "Passthrough"; - case ma_src_algorithm_linear: return "Linear"; - case ma_src_algorithm_sinc: return "Sinc"; - } - - return "Unknown"; -} - -const char* ma_dither_mode_to_string(ma_dither_mode ditherMode) -{ - switch (ditherMode) { - case ma_dither_mode_none: return "None"; - case ma_dither_mode_rectangle: return "Rectangle"; - case ma_dither_mode_triangle: return "Triangle"; - } - - return "Unkown"; -} - - - - -/////////////////////////////////////////////////////////////////////////////// -// -// Format Conversion -// -/////////////////////////////////////////////////////////////////////////////// -typedef struct -{ - void* pBaseData; - ma_uint64 sampleCount; - ma_uint64 iNextSample; -} format_conversion_data; - -void pcm_convert__reference(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode) -{ - switch (formatIn) - { - case ma_format_u8: - { - switch (formatOut) - { - case ma_format_s16: ma_pcm_u8_to_s16__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_u8_to_s24__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_u8_to_s32__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_u8_to_f32__reference(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s16: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s16_to_u8__reference( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s16_to_s24__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s16_to_s32__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s16_to_f32__reference(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s24: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s24_to_u8__reference( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s24_to_s16__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s24_to_s32__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s24_to_f32__reference(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s32_to_u8__reference( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s32_to_s16__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s32_to_s24__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s32_to_f32__reference(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_f32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_f32_to_u8__reference( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_f32_to_s16__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_f32_to_s24__reference(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_f32_to_s32__reference(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - default: break; - } -} - -void pcm_convert__optimized(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode) -{ - switch (formatIn) - { - case ma_format_u8: - { - switch (formatOut) - { - case ma_format_s16: ma_pcm_u8_to_s16__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_u8_to_s24__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_u8_to_s32__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_u8_to_f32__optimized(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s16: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s16_to_u8__optimized( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s16_to_s24__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s16_to_s32__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s16_to_f32__optimized(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s24: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s24_to_u8__optimized( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s24_to_s16__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s24_to_s32__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s24_to_f32__optimized(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s32_to_u8__optimized( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s32_to_s16__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s32_to_s24__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s32_to_f32__optimized(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_f32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_f32_to_u8__optimized( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_f32_to_s16__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_f32_to_s24__optimized(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_f32_to_s32__optimized(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - default: break; - } -} - -#if defined(MA_SUPPORT_SSE2) -void pcm_convert__sse2(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode) -{ - switch (formatIn) - { - case ma_format_u8: - { - switch (formatOut) - { - case ma_format_s16: ma_pcm_u8_to_s16__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_u8_to_s24__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_u8_to_s32__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_u8_to_f32__sse2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s16: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s16_to_u8__sse2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s16_to_s24__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s16_to_s32__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s16_to_f32__sse2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s24: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s24_to_u8__sse2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s24_to_s16__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s24_to_s32__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s24_to_f32__sse2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s32_to_u8__sse2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s32_to_s16__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s32_to_s24__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s32_to_f32__sse2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_f32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_f32_to_u8__sse2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_f32_to_s16__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_f32_to_s24__sse2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_f32_to_s32__sse2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - default: break; - } -} -#endif - -#if defined(MA_SUPPORT_AVX2) -void pcm_convert__avx(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode) -{ - switch (formatIn) - { - case ma_format_u8: - { - switch (formatOut) - { - case ma_format_s16: ma_pcm_u8_to_s16__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_u8_to_s24__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_u8_to_s32__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_u8_to_f32__avx2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s16: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s16_to_u8__avx2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s16_to_s24__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s16_to_s32__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s16_to_f32__avx2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s24: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s24_to_u8__avx2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s24_to_s16__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s24_to_s32__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s24_to_f32__avx2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s32_to_u8__avx2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s32_to_s16__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s32_to_s24__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s32_to_f32__avx2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_f32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_f32_to_u8__avx2( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_f32_to_s16__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_f32_to_s24__avx2(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_f32_to_s32__avx2(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - default: break; - } -} -#endif - -#if defined(MA_SUPPORT_AVX512) -void pcm_convert__avx512(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode) -{ - switch (formatIn) - { - case ma_format_u8: - { - switch (formatOut) - { - case ma_format_s16: ma_pcm_u8_to_s16__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_u8_to_s24__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_u8_to_s32__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_u8_to_f32__avx512(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s16: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s16_to_u8__avx512( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s16_to_s24__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s16_to_s32__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s16_to_f32__avx512(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s24: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s24_to_u8__avx512( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s24_to_s16__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s24_to_s32__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s24_to_f32__avx512(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s32_to_u8__avx512( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s32_to_s16__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s32_to_s24__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s32_to_f32__avx512(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_f32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_f32_to_u8__avx512( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_f32_to_s16__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_f32_to_s24__avx512(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_f32_to_s32__avx512(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - default: break; - } -} -#endif - -#if defined(MA_SUPPORT_NEON) -void pcm_convert__neon(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode) -{ - switch (formatIn) - { - case ma_format_u8: - { - switch (formatOut) - { - case ma_format_s16: ma_pcm_u8_to_s16__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_u8_to_s24__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_u8_to_s32__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_u8_to_f32__neon(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s16: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s16_to_u8__neon( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s16_to_s24__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s16_to_s32__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s16_to_f32__neon(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s24: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s24_to_u8__neon( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s24_to_s16__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_s24_to_s32__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s24_to_f32__neon(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_s32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_s32_to_u8__neon( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_s32_to_s16__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_s32_to_s24__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_f32: ma_pcm_s32_to_f32__neon(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - case ma_format_f32: - { - switch (formatOut) - { - case ma_format_u8: ma_pcm_f32_to_u8__neon( pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s16: ma_pcm_f32_to_s16__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s24: ma_pcm_f32_to_s24__neon(pOut, pIn, sampleCount, ditherMode); return; - case ma_format_s32: ma_pcm_f32_to_s32__neon(pOut, pIn, sampleCount, ditherMode); return; - default: break; - } - } break; - - default: break; - } -} -#endif - -void pcm_convert(void* pOut, ma_format formatOut, const void* pIn, ma_format formatIn, ma_uint64 sampleCount, ma_dither_mode ditherMode, simd_mode mode) -{ - // For testing, we always reset the seed for dithering so we can get consistent results for comparisons. - ma_seed(1234); - - switch (mode) - { - case simd_mode_scalar: - { - pcm_convert__optimized(pOut, formatOut, pIn, formatIn, sampleCount, ditherMode); - } break; - -#if defined(MA_SUPPORT_SSE2) - case simd_mode_sse2: - { - pcm_convert__sse2(pOut, formatOut, pIn, formatIn, sampleCount, ditherMode); - } break; -#endif - -#if defined(MA_SUPPORT_AVX2) - case simd_mode_avx2: - { - pcm_convert__avx(pOut, formatOut, pIn, formatIn, sampleCount, ditherMode); - } break; -#endif - -#if defined(MA_SUPPORT_AVX512) - case simd_mode_avx512: - { - pcm_convert__avx512(pOut, formatOut, pIn, formatIn, sampleCount, ditherMode); - } break; -#endif - -#if defined(MA_SUPPORT_NEON) - case simd_mode_neon: - { - pcm_convert__neon(pOut, formatOut, pIn, formatIn, sampleCount, ditherMode); - } break; -#endif - - default: break; - } -} - - -int do_profiling__format_conversion__profile_individual(ma_format formatIn, ma_format formatOut, ma_dither_mode ditherMode, const void* pBaseData, ma_uint64 sampleCount, simd_mode mode, const void* pReferenceData, double referenceTime) -{ - void* pTestData = ma_aligned_malloc((size_t)(sampleCount * ma_get_bytes_per_sample(formatOut)), MA_SIMD_ALIGNMENT); - if (pTestData == NULL) { - printf("Out of memory.\n"); - return -1; - } - - ma_timer timer; - ma_timer_init(&timer); - double timeTaken = ma_timer_get_time_in_seconds(&timer); - { - pcm_convert(pTestData, formatOut, pBaseData, formatIn, sampleCount, ditherMode, mode); - } - timeTaken = ma_timer_get_time_in_seconds(&timer) - timeTaken; - - - // Compare with the reference for correctness. - ma_bool32 passed = MA_TRUE; - for (ma_uint64 iSample = 0; iSample < sampleCount; ++iSample) { - ma_uint32 bps = ma_get_bytes_per_sample(formatOut); - - // We need to compare on a format by format basis because we allow for very slight deviations in results depending on the output format. - switch (formatOut) - { - case ma_format_s16: - { - ma_int16 a = ((const ma_int16*)pReferenceData)[iSample]; - ma_int16 b = ((const ma_int16*)pTestData)[iSample]; - if (abs(a-b) > 0) { - printf("Incorrect Sample: (%d) %d != %d\n", (int)iSample, a, b); - passed = MA_FALSE; - } - } break; - - default: - { - if (memcmp(ma_offset_ptr(pReferenceData, iSample*bps), ma_offset_ptr(pTestData, iSample*bps), bps) != 0) { - printf("Incorrect Sample: (%d)\n", (int)iSample); - passed = MA_FALSE; - } - } break; - } - } - - if (passed) { - printf(" [PASSED] "); - } else { - printf(" [FAILED] "); - } - printf("(Dither = %s) %s -> %s (%s): %.4fms (%.2f%%)\n", ma_dither_mode_to_string(ditherMode), ma_get_format_name(formatIn), ma_get_format_name(formatOut), simd_mode_to_string(mode), timeTaken*1000, referenceTime/timeTaken*100); - - ma_aligned_free(pTestData); - return 0; -} - -int do_profiling__format_conversion__profile_set(ma_format formatIn, ma_format formatOut, ma_dither_mode ditherMode) -{ - // Generate our base data to begin with. This is generated from an f32 sine wave which is converted to formatIn. That then becomes our base data. - ma_uint32 sampleCount = 10000000; - - float* pSourceData = (float*)ma_aligned_malloc(sampleCount*sizeof(*pSourceData), MA_SIMD_ALIGNMENT); - if (pSourceData == NULL) { - printf("Out of memory.\n"); - return -1; - } - - ma_sine_wave sineWave; - ma_sine_wave_init(1.0, 400, 48000, &sineWave); - ma_sine_wave_read_f32(&sineWave, sampleCount, pSourceData); - - void* pBaseData = ma_aligned_malloc(sampleCount * ma_get_bytes_per_sample(formatIn), MA_SIMD_ALIGNMENT); - ma_pcm_convert(pBaseData, formatIn, pSourceData, ma_format_f32, sampleCount, ma_dither_mode_none); - - - // Reference first so we can get a benchmark. - void* pReferenceData = ma_aligned_malloc(sampleCount * ma_get_bytes_per_sample(formatOut), MA_SIMD_ALIGNMENT); - ma_timer timer; - ma_timer_init(&timer); - double referenceTime = ma_timer_get_time_in_seconds(&timer); - { - pcm_convert__reference(pReferenceData, formatOut, pBaseData, formatIn, sampleCount, ditherMode); - } - referenceTime = ma_timer_get_time_in_seconds(&timer) - referenceTime; - - - // Here is where each optimized implementation is profiled. - do_profiling__format_conversion__profile_individual(formatIn, formatOut, ditherMode, pBaseData, sampleCount, simd_mode_scalar, pReferenceData, referenceTime); - - if (ma_has_sse2()) { - do_profiling__format_conversion__profile_individual(formatIn, formatOut, ditherMode, pBaseData, sampleCount, simd_mode_sse2, pReferenceData, referenceTime); - } - if (ma_has_avx2()) { - do_profiling__format_conversion__profile_individual(formatIn, formatOut, ditherMode, pBaseData, sampleCount, simd_mode_avx2, pReferenceData, referenceTime); - } - if (ma_has_avx512f()) { - do_profiling__format_conversion__profile_individual(formatIn, formatOut, ditherMode, pBaseData, sampleCount, simd_mode_avx512, pReferenceData, referenceTime); - } - if (ma_has_neon()) { - do_profiling__format_conversion__profile_individual(formatIn, formatOut, ditherMode, pBaseData, sampleCount, simd_mode_neon, pReferenceData, referenceTime); - } - - - - ma_aligned_free(pReferenceData); - ma_aligned_free(pBaseData); - ma_aligned_free(pSourceData); - return 0; -} - -int do_profiling__format_conversion() -{ - // First we need to generate our base data. - - - do_profiling__format_conversion__profile_set(ma_format_f32, ma_format_s16, ma_dither_mode_none); - - return 0; -} - - - -/////////////////////////////////////////////////////////////////////////////// -// -// Channel Routing -// -/////////////////////////////////////////////////////////////////////////////// - -float g_ChannelRouterProfilingOutputBenchmark[8][48000]; -float g_ChannelRouterProfilingOutput[8][48000]; -double g_ChannelRouterTime_Reference = 0; -double g_ChannelRouterTime_SSE2 = 0; -double g_ChannelRouterTime_AVX2 = 0; -double g_ChannelRouterTime_AVX512 = 0; -double g_ChannelRouterTime_NEON = 0; - -ma_sine_wave g_sineWave; - -ma_bool32 channel_router_test(ma_uint32 channels, ma_uint64 frameCount, float** ppFramesA, float** ppFramesB) -{ - for (ma_uint32 iChannel = 0; iChannel < channels; ++iChannel) { - for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) { - if (ppFramesA[iChannel][iFrame] != ppFramesB[iChannel][iFrame]) { - return MA_FALSE; - } - } - } - - return MA_TRUE; -} - -ma_uint32 channel_router_on_read(ma_channel_router* pRouter, ma_uint32 frameCount, void** ppSamplesOut, void* pUserData) -{ - (void)pUserData; - (void)pRouter; - - float** ppSamplesOutF = (float**)ppSamplesOut; - - for (ma_uint32 iChannel = 0; iChannel < pRouter->config.channelsIn; ++iChannel) { - ma_sine_wave_init(1/(iChannel+1), 400, 48000, &g_sineWave); - ma_sine_wave_read_f32(&g_sineWave, frameCount, ppSamplesOutF[iChannel]); - } - - return frameCount; -} - -int do_profiling__channel_routing() -{ - ma_result result; - - // When profiling we need to compare against a benchmark to ensure the optimization is implemented correctly. We always - // use the reference implementation for our benchmark. - ma_uint32 channels = ma_countof(g_ChannelRouterProfilingOutputBenchmark); - ma_channel channelMapIn[MA_MAX_CHANNELS]; - ma_get_standard_channel_map(ma_standard_channel_map_default, channels, channelMapIn); - ma_channel channelMapOut[MA_MAX_CHANNELS]; - ma_get_standard_channel_map(ma_standard_channel_map_default, channels, channelMapOut); - - ma_channel_router_config routerConfig = ma_channel_router_config_init(channels, channelMapIn, channels, channelMapOut, ma_channel_mix_mode_planar_blend, channel_router_on_read, NULL); - - ma_channel_router router; - result = ma_channel_router_init(&routerConfig, &router); - if (result != MA_SUCCESS) { - return -1; - } - - // Disable optimizations for our tests. - router.isPassthrough = MA_FALSE; - router.isSimpleShuffle = MA_FALSE; - router.useSSE2 = MA_FALSE; - router.useAVX2 = MA_FALSE; - router.useAVX512 = MA_FALSE; - router.useNEON = MA_FALSE; - - ma_uint64 framesToRead = ma_countof(g_ChannelRouterProfilingOutputBenchmark[0]); - - // Benchmark - void* ppOutBenchmark[8]; - for (int i = 0; i < 8; ++i) { - ppOutBenchmark[i] = (void*)g_ChannelRouterProfilingOutputBenchmark[i]; - } - - ma_sine_wave_init(1, 400, 48000, &g_sineWave); - ma_uint64 framesRead = ma_channel_router_read_deinterleaved(&router, framesToRead, ppOutBenchmark, NULL); - if (framesRead != framesToRead) { - printf("Channel Router: An error occurred while reading benchmark data.\n"); - } - - void* ppOut[8]; - for (int i = 0; i < 8; ++i) { - ppOut[i] = (void*)g_ChannelRouterProfilingOutput[i]; - } - - - printf("Channel Routing\n"); - printf("===============\n"); - - // Reference - { - ma_timer timer; - ma_timer_init(&timer); - double startTime = ma_timer_get_time_in_seconds(&timer); - - framesRead = ma_channel_router_read_deinterleaved(&router, framesToRead, ppOut, NULL); - if (framesRead != framesToRead) { - printf("Channel Router: An error occurred while reading reference data.\n"); - } - - if (!channel_router_test(channels, framesRead, (float**)ppOutBenchmark, (float**)ppOut)) { - printf(" [ERROR] "); - } else { - printf(" [PASSED] "); - } - - g_ChannelRouterTime_Reference = ma_timer_get_time_in_seconds(&timer) - startTime; - printf("Reference: %.4fms (%.2f%%)\n", g_ChannelRouterTime_Reference*1000, g_ChannelRouterTime_Reference/g_ChannelRouterTime_Reference*100); - } - - // SSE2 - if (ma_has_sse2()) { - router.useSSE2 = MA_TRUE; - ma_timer timer; - ma_timer_init(&timer); - double startTime = ma_timer_get_time_in_seconds(&timer); - - framesRead = ma_channel_router_read_deinterleaved(&router, framesToRead, ppOut, NULL); - if (framesRead != framesToRead) { - printf("Channel Router: An error occurred while reading SSE2 data.\n"); - } - - g_ChannelRouterTime_SSE2 = ma_timer_get_time_in_seconds(&timer) - startTime; - router.useSSE2 = MA_FALSE; - - if (!channel_router_test(channels, framesRead, (float**)ppOutBenchmark, (float**)ppOut)) { - printf(" [ERROR] "); - } else { - printf(" [PASSED] "); - } - - printf("SSE2: %.4fms (%.2f%%)\n", g_ChannelRouterTime_SSE2*1000, g_ChannelRouterTime_Reference/g_ChannelRouterTime_SSE2*100); - } - - // AVX2 - if (ma_has_avx2()) { - router.useAVX2 = MA_TRUE; - ma_timer timer; - ma_timer_init(&timer); - double startTime = ma_timer_get_time_in_seconds(&timer); - - framesRead = ma_channel_router_read_deinterleaved(&router, framesToRead, ppOut, NULL); - if (framesRead != framesToRead) { - printf("Channel Router: An error occurred while reading AVX2 data.\n"); - } - - g_ChannelRouterTime_AVX2 = ma_timer_get_time_in_seconds(&timer) - startTime; - router.useAVX2 = MA_FALSE; - - if (!channel_router_test(channels, framesRead, (float**)ppOutBenchmark, (float**)ppOut)) { - printf(" [ERROR] "); - } else { - printf(" [PASSED] "); - } - - printf("AVX2: %.4fms (%.2f%%)\n", g_ChannelRouterTime_AVX2*1000, g_ChannelRouterTime_Reference/g_ChannelRouterTime_AVX2*100); - } - - // NEON - if (ma_has_neon()) { - router.useNEON = MA_TRUE; - ma_timer timer; - ma_timer_init(&timer); - double startTime = ma_timer_get_time_in_seconds(&timer); - - framesRead = ma_channel_router_read_deinterleaved(&router, framesToRead, ppOut, NULL); - if (framesRead != framesToRead) { - printf("Channel Router: An error occurred while reading NEON data.\n"); - } - - g_ChannelRouterTime_NEON = ma_timer_get_time_in_seconds(&timer) - startTime; - router.useNEON = MA_FALSE; - - if (!channel_router_test(channels, framesRead, (float**)ppOutBenchmark, (float**)ppOut)) { - printf(" [ERROR] "); - } else { - printf(" [PASSED] "); - } - - printf("NEON: %.4fms (%.2f%%)\n", g_ChannelRouterTime_NEON*1000, g_ChannelRouterTime_Reference/g_ChannelRouterTime_NEON*100); - } - - return 0; -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// SRC -// -/////////////////////////////////////////////////////////////////////////////// - -typedef struct -{ - float* pFrameData[MA_MAX_CHANNELS]; - ma_uint64 frameCount; - ma_uint32 channels; - double timeTaken; -} src_reference_data; - -typedef struct -{ - float* pFrameData[MA_MAX_CHANNELS]; - ma_uint64 frameCount; - ma_uint64 iNextFrame; - ma_uint32 channels; -} src_data; - -ma_uint32 do_profiling__src__on_read(ma_src* pSRC, ma_uint32 frameCount, void** ppSamplesOut, void* pUserData) -{ - src_data* pBaseData = (src_data*)pUserData; - ma_assert(pBaseData != NULL); - ma_assert(pBaseData->iNextFrame <= pBaseData->frameCount); - - ma_uint64 framesToRead = frameCount; - - ma_uint64 framesAvailable = pBaseData->frameCount - pBaseData->iNextFrame; - if (framesToRead > framesAvailable) { - framesToRead = framesAvailable; - } - - if (framesToRead > 0) { - for (ma_uint32 iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) { - ma_copy_memory(ppSamplesOut[iChannel], pBaseData->pFrameData[iChannel], (size_t)(framesToRead * sizeof(float))); - } - } - - pBaseData->iNextFrame += framesToRead; - return (ma_uint32)framesToRead; -} - -ma_result init_src(src_data* pBaseData, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut, ma_src_algorithm algorithm, simd_mode mode, ma_src* pSRC) -{ - ma_assert(pBaseData != NULL); - ma_assert(pSRC != NULL); - - ma_src_config srcConfig = ma_src_config_init(sampleRateIn, sampleRateOut, pBaseData->channels, do_profiling__src__on_read, pBaseData); - srcConfig.sinc.windowWidth = 17; // <-- Make this an odd number to test unaligned section in the SIMD implementations. - srcConfig.algorithm = algorithm; - srcConfig.noSSE2 = MA_TRUE; - srcConfig.noAVX2 = MA_TRUE; - srcConfig.noAVX512 = MA_TRUE; - srcConfig.noNEON = MA_TRUE; - switch (mode) { - case simd_mode_sse2: srcConfig.noSSE2 = MA_FALSE; break; - case simd_mode_avx2: srcConfig.noAVX2 = MA_FALSE; break; - case simd_mode_avx512: srcConfig.noAVX512 = MA_FALSE; break; - case simd_mode_neon: srcConfig.noNEON = MA_FALSE; break; - case simd_mode_scalar: - default: break; - } - - ma_result result = ma_src_init(&srcConfig, pSRC); - if (result != MA_SUCCESS) { - printf("Failed to initialize sample rate converter.\n"); - return (int)result; - } - - return result; -} - -int do_profiling__src__profile_individual(src_data* pBaseData, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut, ma_src_algorithm algorithm, simd_mode mode, src_reference_data* pReferenceData) -{ - ma_assert(pBaseData != NULL); - ma_assert(pReferenceData != NULL); - - ma_result result = MA_ERROR; - - // Make sure the base data is moved back to the start. - pBaseData->iNextFrame = 0; - - ma_src src; - result = init_src(pBaseData, sampleRateIn, sampleRateOut, algorithm, mode, &src); - if (result != MA_SUCCESS) { - return (int)result; - } - - - // Profiling. - ma_uint64 sz = pReferenceData->frameCount * sizeof(float); - ma_assert(sz <= SIZE_MAX); - - float* pFrameData[MA_MAX_CHANNELS]; - for (ma_uint32 iChannel = 0; iChannel < pBaseData->channels; iChannel += 1) { - pFrameData[iChannel] = (float*)ma_aligned_malloc((size_t)sz, MA_SIMD_ALIGNMENT); - if (pFrameData[iChannel] == NULL) { - printf("Out of memory.\n"); - return -2; - } - ma_zero_memory(pFrameData[iChannel], (size_t)sz); - } - - ma_timer timer; - ma_timer_init(&timer); - double startTime = ma_timer_get_time_in_seconds(&timer); - { - ma_src_read_deinterleaved(&src, pReferenceData->frameCount, (void**)pFrameData, pBaseData); - } - double timeTaken = ma_timer_get_time_in_seconds(&timer) - startTime; - - - // Correctness test. - ma_bool32 passed = MA_TRUE; - for (ma_uint32 iChannel = 0; iChannel < pReferenceData->channels; iChannel += 1) { - for (ma_uint32 iFrame = 0; iFrame < pReferenceData->frameCount; iFrame += 1) { - float s0 = pReferenceData->pFrameData[iChannel][iFrame]; - float s1 = pFrameData[iChannel][iFrame]; - //if (s0 != s1) { - if (fabs(s0 - s1) > 0.000001) { - printf("(Channel %d, Sample %d) %f != %f\n", iChannel, iFrame, s0, s1); - passed = MA_FALSE; - } - } - } - - - // Print results. - if (passed) { - printf(" [PASSED] "); - } else { - printf(" [FAILED] "); - } - printf("%s %d -> %d (%s): %.4fms (%.2f%%)\n", ma_src_algorithm_to_string(algorithm), sampleRateIn, sampleRateOut, simd_mode_to_string(mode), timeTaken*1000, pReferenceData->timeTaken/timeTaken*100); - - - for (ma_uint32 iChannel = 0; iChannel < pBaseData->channels; iChannel += 1) { - ma_aligned_free(pFrameData[iChannel]); - } - - return (int)result; -} - -int do_profiling__src__profile_set(src_data* pBaseData, ma_uint32 sampleRateIn, ma_uint32 sampleRateOut, ma_src_algorithm algorithm) -{ - ma_assert(pBaseData != NULL); - - // Make sure the base data is back at the start. - pBaseData->iNextFrame = 0; - - src_reference_data referenceData; - ma_zero_object(&referenceData); - referenceData.channels = pBaseData->channels; - - // The first thing to do is to perform a sample rate conversion using the scalar/reference implementation. This reference is used to compare - // the results of the optimized implementation. - referenceData.frameCount = ma_calculate_frame_count_after_src(sampleRateOut, sampleRateIn, pBaseData->frameCount); - if (referenceData.frameCount == 0) { - printf("Failed to calculate output frame count.\n"); - return -1; - } - - ma_uint64 sz = referenceData.frameCount * sizeof(float); - ma_assert(sz <= SIZE_MAX); - - for (ma_uint32 iChannel = 0; iChannel < referenceData.channels; iChannel += 1) { - referenceData.pFrameData[iChannel] = (float*)ma_aligned_malloc((size_t)sz, MA_SIMD_ALIGNMENT); - if (referenceData.pFrameData[iChannel] == NULL) { - printf("Out of memory.\n"); - return -2; - } - ma_zero_memory(referenceData.pFrameData[iChannel], (size_t)sz); - } - - - // Generate the reference data. - ma_src src; - ma_result result = init_src(pBaseData, sampleRateIn, sampleRateOut, algorithm, simd_mode_scalar, &src); - if (result != MA_SUCCESS) { - return (int)result; - } - - ma_timer timer; - ma_timer_init(&timer); - double startTime = ma_timer_get_time_in_seconds(&timer); - { - ma_src_read_deinterleaved(&src, referenceData.frameCount, (void**)referenceData.pFrameData, pBaseData); - } - referenceData.timeTaken = ma_timer_get_time_in_seconds(&timer) - startTime; - - - // Now that we have the reference data to compare against we can go ahead and measure the SIMD optimizations. - do_profiling__src__profile_individual(pBaseData, sampleRateIn, sampleRateOut, algorithm, simd_mode_scalar, &referenceData); - if (ma_has_sse2()) { - do_profiling__src__profile_individual(pBaseData, sampleRateIn, sampleRateOut, algorithm, simd_mode_sse2, &referenceData); - } - if (ma_has_avx2()) { - do_profiling__src__profile_individual(pBaseData, sampleRateIn, sampleRateOut, algorithm, simd_mode_avx2, &referenceData); - } - if (ma_has_avx512f()) { - do_profiling__src__profile_individual(pBaseData, sampleRateIn, sampleRateOut, algorithm, simd_mode_avx512, &referenceData); - } - if (ma_has_neon()) { - do_profiling__src__profile_individual(pBaseData, sampleRateIn, sampleRateOut, algorithm, simd_mode_neon, &referenceData); - } - - - for (ma_uint32 iChannel = 0; iChannel < referenceData.channels; iChannel += 1) { - ma_aligned_free(referenceData.pFrameData[iChannel]); - } - - return 0; -} - -int do_profiling__src() -{ - printf("Sample Rate Conversion\n"); - printf("======================\n"); - - // Set up base data. - src_data baseData; - ma_zero_object(&baseData); - baseData.channels = 8; - baseData.frameCount = 100000; - for (ma_uint32 iChannel = 0; iChannel < baseData.channels; ++iChannel) { - baseData.pFrameData[iChannel] = (float*)ma_aligned_malloc((size_t)(baseData.frameCount * sizeof(float)), MA_SIMD_ALIGNMENT); - if (baseData.pFrameData[iChannel] == NULL) { - printf("Out of memory.\n"); - return -1; - } - - ma_sine_wave sineWave; - ma_sine_wave_init(1.0f, 400 + (iChannel*50), 48000, &sineWave); - ma_sine_wave_read_f32(&sineWave, baseData.frameCount, baseData.pFrameData[iChannel]); - } - - - // Upsampling. - do_profiling__src__profile_set(&baseData, 44100, 48000, ma_src_algorithm_sinc); - - // Downsampling. - do_profiling__src__profile_set(&baseData, 48000, 44100, ma_src_algorithm_sinc); - - - for (ma_uint32 iChannel = 0; iChannel < baseData.channels; iChannel += 1) { - ma_aligned_free(baseData.pFrameData[iChannel]); - } - - return 0; -} - -#if 0 -// Converts two 4xf32 vectors to one 8xi16 vector with signed saturation. -__m128i drmath_vf32_to_vi16__sse2(__m128 f32_0, __m128 f32_1) -{ - return _mm_packs_epi32(_mm_cvttps_epi32(f32_0), _mm_cvttps_epi32(f32_1)); -} - -__m256i drmath_vf32_to_vi16__avx(__m256 f32_0, __m256 f32_1) -{ - __m256i i0 = _mm256_cvttps_epi32(f32_0); - __m256i i1 = _mm256_cvttps_epi32(f32_1); - __m256i p0 = _mm256_permute2x128_si256(i0, i1, 32); - __m256i p1 = _mm256_permute2x128_si256(i0, i1, 49); - __m256i r = _mm256_packs_epi32(p0, p1); - return r; -} -#endif - -int main(int argc, char** argv) -{ - (void)argc; - (void)argv; - - - { - //__m128 f0 = _mm_set_ps(32780, 2, 1, 0); - //__m128 f1 = _mm_set_ps(-32780, 6, 5, 4); - //__m128i r = drmath_vf32_to_vi16__sse2(f0, f1); - - //__m256 f0 = _mm256_set_ps(7, 6, 5, 4, 3, 2, 1, 0); - //__m256 f1 = _mm256_set_ps(15, 14, 13, 12, 11, 10, 9, 8); - //__m256i r = drmath_vf32_to_vi16__avx(f0, f1); - // - //int a = 5; - } - - - - // Summary. - if (ma_has_sse2()) { - printf("Has SSE2: YES\n"); - } else { - printf("Has SSE2: NO\n"); - } - if (ma_has_avx2()) { - printf("Has AVX2: YES\n"); - } else { - printf("Has AVX2: NO\n"); - } - if (ma_has_avx512f()) { - printf("Has AVX-512F: YES\n"); - } else { - printf("Has AVX-512F: NO\n"); - } - if (ma_has_neon()) { - printf("Has NEON: YES\n"); - } else { - printf("Has NEON: NO\n"); - } - - - printf("\n"); - - // Format conversion. - do_profiling__format_conversion(); - printf("\n\n"); - - // Channel routing. - do_profiling__channel_routing(); - printf("\n\n"); - - // Sample rate conversion. - do_profiling__src(); - printf("\n\n"); - - - printf("Press any key to quit...\n"); - getchar(); - - return 0; -} \ No newline at end of file diff --git a/tests/ma_resampling.c b/tests/ma_resampling.c deleted file mode 100644 index cca40dc6..00000000 --- a/tests/ma_resampling.c +++ /dev/null @@ -1,143 +0,0 @@ - -#define MA_NO_SSE2 -#define MA_NO_AVX2 - -#define MINIAUDIO_IMPLEMENTATION -#include "../miniaudio.h" - -// There is a usage pattern for resampling that miniaudio does not properly support which is where the client continuously -// reads samples until ma_src_read() returns 0. The problem with this pattern is that is consumes the samples sitting -// in the window which are needed to compute the next samples in future calls to ma_src_read() (assuming the client -// has re-filled the resampler's input data). - -/* -for (;;) { - fill_src_input_data(&src, someData); - - float buffer[4096] - while ((framesRead = ma_src_read(&src, ...) != 0) { - do_something_with_resampled_data(buffer); - } -} -*/ - -// In the use case above, the very last samples that are read from ma_src_read() will not have future samples to draw -// from in order to calculate the correct interpolation factor which in turn results in crackling. - -ma_uint32 sampleRateIn = 0; -ma_uint32 sampleRateOut = 0; -ma_sine_wave sineWave; // <-- This is the source data. -ma_src src; -float srcInput[1024]; -ma_uint32 srcNextSampleIndex = ma_countof(srcInput); - -void reload_src_input() -{ - ma_sine_wave_read_f32(&sineWave, ma_countof(srcInput), srcInput); - srcNextSampleIndex = 0; -} - -ma_uint32 on_src(ma_src* pSRC, ma_uint32 frameCount, void** ppSamplesOut, void* pUserData) -{ - ma_assert(pSRC != NULL); - ma_assert(pSRC->config.channels == 1); - - (void)pUserData; - - // Only read as much as is available in the input buffer. Do not reload the buffer here. - ma_uint32 framesAvailable = ma_countof(srcInput) - srcNextSampleIndex; - ma_uint32 framesToRead = frameCount; - if (framesToRead > framesAvailable) { - framesToRead = framesAvailable; - } - - ma_copy_memory(ppSamplesOut[0], srcInput + srcNextSampleIndex, sizeof(float)*framesToRead); - srcNextSampleIndex += framesToRead; - - return framesToRead; -} - -void on_send_to_device(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) -{ - (void)pDevice; - (void)pInput; - - ma_assert(pDevice->playback.format == ma_format_f32); - ma_assert(pDevice->playback.channels == 1); - - float* pFramesF32 = (float*)pOutput; - - // To reproduce the case we are needing to test, we need to read from the SRC in a very specific way. We keep looping - // until we've read the requested frame count, however we have an inner loop that keeps running until ma_src_read() - // returns 0, in which case we need to reload the SRC's input data and keep going. - ma_uint32 totalFramesRead = 0; - while (totalFramesRead < frameCount) { - ma_uint32 framesRemaining = frameCount - totalFramesRead; - - ma_uint32 maxFramesToRead = 128; - ma_uint32 framesToRead = framesRemaining; - if (framesToRead > maxFramesToRead) { - framesToRead = maxFramesToRead; - } - - ma_uint32 framesRead = (ma_uint32)ma_src_read_deinterleaved(&src, framesToRead, (void**)&pFramesF32, NULL); - if (framesRead == 0) { - reload_src_input(); - } - - totalFramesRead += framesRead; - pFramesF32 += framesRead; - } - - ma_assert(totalFramesRead == frameCount); -} - -int main(int argc, char** argv) -{ - (void)argc; - (void)argv; - - - ma_device_config config = ma_device_config_init(ma_device_type_playback); - config.playback.format = ma_format_f32; - config.playback.channels = 1; - config.dataCallback = on_send_to_device; - - ma_device device; - ma_result result; - - config.bufferSizeInFrames = 8192*1; - - // We first play the sound the way it's meant to be played. - result = ma_device_init(NULL, &config, &device); - if (result != MA_SUCCESS) { - return -1; - } - - - // For this test, we need the sine wave to be a different format to the device. - sampleRateOut = device.sampleRate; - sampleRateIn = (sampleRateOut == 44100) ? 48000 : 44100; - ma_sine_wave_init(0.2, 400, sampleRateIn, &sineWave); - - ma_src_config srcConfig = ma_src_config_init(sampleRateIn, sampleRateOut, 1, on_src, NULL); - srcConfig.algorithm = ma_src_algorithm_sinc; - srcConfig.neverConsumeEndOfInput = MA_TRUE; - - result = ma_src_init(&srcConfig, &src); - if (result != MA_SUCCESS) { - printf("Failed to create SRC.\n"); - return -1; - } - - result = ma_device_start(&device); - if (result != MA_SUCCESS) { - return -2; - } - - printf("Press Enter to quit...\n"); - getchar(); - ma_device_uninit(&device); - - return 0; -} diff --git a/tests/ma_stop.c b/tests/ma_stop.c deleted file mode 100644 index e32f28a8..00000000 --- a/tests/ma_stop.c +++ /dev/null @@ -1,98 +0,0 @@ -#include - -#define MINIAUDIO_IMPLEMENTATION -#include "../miniaudio.h" - -ma_sine_wave sineWave; -ma_uint32 framesWritten; -ma_event stopEvent; -ma_bool32 isInitialRun = MA_TRUE; - -void on_stop(ma_device* pDevice) -{ - (void)pDevice; - printf("STOPPED\n"); -} - -void on_data(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) -{ - (void)pInput; /* Not used yet. */ - - /* Output exactly one second of data. Pad the end with silence. */ - ma_uint32 framesRemaining = pDevice->sampleRate - framesWritten; - ma_uint32 framesToProcess = frameCount; - if (framesToProcess > framesRemaining && isInitialRun) { - framesToProcess = framesRemaining; - } - - ma_sine_wave_read_f32_ex(&sineWave, framesToProcess, pDevice->playback.channels, ma_stream_layout_interleaved, (float**)&pOutput); - if (isInitialRun) { - framesWritten += framesToProcess; - } - - ma_assert(framesWritten <= pDevice->sampleRate); - if (framesWritten >= pDevice->sampleRate) { - if (isInitialRun) { - printf("STOPPING [AUDIO THREAD]...\n"); - ma_event_signal(&stopEvent); - isInitialRun = MA_FALSE; - } - } -} - -int main(int argc, char** argv) -{ - ma_result result; - - (void)argc; - (void)argv; - - ma_backend backend = ma_backend_wasapi; - - ma_sine_wave_init(0.25, 400, 44100, &sineWave); - - ma_device_config config = ma_device_config_init(ma_device_type_playback); - config.playback.format = ma_format_f32; - config.playback.channels = 2; - config.sampleRate = 44100; - config.dataCallback = on_data; - config.stopCallback = on_stop; - config.bufferSizeInFrames = 16384; - - ma_device device; - result = ma_device_init_ex(&backend, 1, NULL, &config, &device); - if (result != MA_SUCCESS) { - printf("Failed to initialize device.\n"); - return result; - } - - result = ma_event_init(device.pContext, &stopEvent); - if (result != MA_SUCCESS) { - printf("Failed to initialize stop event.\n"); - return result; - } - - ma_device_start(&device); - - /* We wait for the stop event, stop the device, then ask the user to press any key to restart. This checks that the device can restart after stopping. */ - ma_event_wait(&stopEvent); - - printf("STOPPING [MAIN THREAD]...\n"); - ma_device_stop(&device); - - printf("Press Enter to restart...\n"); - getchar(); - - result = ma_device_start(&device); - if (result != MA_SUCCESS) { - printf("Failed to restart the device.\n"); - ma_device_uninit(&device); - return -1; - } - - printf("Press Enter to quit...\n"); - getchar(); - - ma_device_uninit(&device); - return 0; -} \ No newline at end of file diff --git a/tests/ma_webaudio_test_0.html b/tests/ma_webaudio_test_0.html deleted file mode 100644 index 0826943f..00000000 --- a/tests/ma_webaudio_test_0.html +++ /dev/null @@ -1,330 +0,0 @@ - - - - - This is a test of the Web Audio API - -
-
- -
Playback Devices
-
- [Playback Devices] -
- -
Capture Devices
-
- [Capture Devices] -
- - - - - -
- - - - - - - - - - \ No newline at end of file