diff --git a/.gitignore b/.gitignore index efb0101e..909d900a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,6 @@ tests/x64/ tests/Debug/ tests/Release/ tests/bin/ -!./tests/DO_NOT_DELETE -*.vcxproj.user \ No newline at end of file +!/tests/DO_NOT_DELETE +/tests/SDL2.dll +*.vcxproj.user diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..e35f9e4c --- /dev/null +++ b/tests/README.md @@ -0,0 +1,7 @@ +Build and run these test from this folder. Example: + + clear && ./mal_test_0_build && ./bin/mal_test_0 + +These tests load resources from hard coded paths which point to the "res" folder. These +paths are based on the assumption that the current directory is where the build files +are located. \ No newline at end of file diff --git a/tests/bin/DO_NOT_DELETE b/tests/bin/DO_NOT_DELETE new file mode 100644 index 00000000..e69de29b diff --git a/tests/mal_test_0.c b/tests/mal_test_0.c new file mode 100644 index 00000000..fe72caff --- /dev/null +++ b/tests/mal_test_0.c @@ -0,0 +1,318 @@ +// Uncomment this to include Vorbis decoding tests, albeit with some annoying warnings with MinGW. +//#define MAL_INCLUDE_VORBIS_TESTS + +#include "../extras/dr_flac.h" +#include "../extras/dr_mp3.h" +#include "../extras/dr_wav.h" + +#ifdef MAL_INCLUDE_VORBIS_TESTS + #define STB_VORBIS_HEADER_ONLY + #include "../extras/stb_vorbis.c" +#endif + +#define MAL_IMPLEMENTATION +#include "../mini_al.h" + +mal_backend g_Backends[] = { + mal_backend_wasapi, + mal_backend_dsound, + mal_backend_winmm, + mal_backend_oss, + mal_backend_pulseaudio, + mal_backend_alsa, + mal_backend_jack, + mal_backend_opensl, + mal_backend_openal, + mal_backend_sdl, + mal_backend_null +}; + +void on_log(mal_context* pContext, mal_device* pDevice, const char* message) +{ + (void)pContext; + (void)pDevice; + printf("%s\n", message); +} + + +int do_backend_test(mal_backend backend) +{ + mal_result result = MAL_SUCCESS; + mal_context context; + mal_device_info* pPlaybackDeviceInfos; + mal_uint32 playbackDeviceCount; + mal_device_info* pCaptureDeviceInfos; + mal_uint32 captureDeviceCount; + + printf("--- %s ---\n", mal_get_backend_name(backend)); + + // Context. + printf(" Creating Context... "); + { + mal_context_config contextConfig = mal_context_config_init(on_log); + + result = mal_context_init(&backend, 1, &contextConfig, &context); + if (result == MAL_SUCCESS) { + printf(" Done\n"); + } else { + if (result == MAL_NO_BACKEND) { + printf(" Not supported\n"); + printf("--- End %s ---\n", mal_get_backend_name(backend)); + printf("\n"); + return 0; + } else { + printf(" Failed\n"); + goto done; + } + } + } + + // Enumeration. + printf(" Enumerating Devices... "); + { + result = mal_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount); + if (result == MAL_SUCCESS) { + printf("Done\n"); + } else { + printf("Failed\n"); + goto done; + } + + printf(" Playback Devices (%d)\n", playbackDeviceCount); + for (mal_uint32 iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) { + printf(" %d: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name); + } + + printf(" Capture Devices (%d)\n", captureDeviceCount); + for (mal_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 (mal_uint32 iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) { + printf(" %d: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name); + + result = mal_context_get_device_info(&context, mal_device_type_playback, &pPlaybackDeviceInfos[iDevice].id, mal_share_mode_shared, &pPlaybackDeviceInfos[iDevice]); + if (result == MAL_SUCCESS) { + printf(" Name: %s\n", pPlaybackDeviceInfos[iDevice].name); + } else { + printf(" ERROR\n"); + } + } + + printf(" Capture Devices (%d)\n", captureDeviceCount); + for (mal_uint32 iDevice = 0; iDevice < captureDeviceCount; ++iDevice) { + printf(" %d: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name); + + result = mal_context_get_device_info(&context, mal_device_type_capture, &pCaptureDeviceInfos[iDevice].id, mal_share_mode_shared, &pCaptureDeviceInfos[iDevice]); + if (result == MAL_SUCCESS) { + printf(" Name: %s\n", pCaptureDeviceInfos[iDevice].name); + } else { + printf(" ERROR\n"); + } + } + } + +done: + printf("--- End %s ---\n", mal_get_backend_name(backend)); + printf("\n"); + + mal_context_uninit(&context); + return (result == MAL_SUCCESS) ? 0 : -1; +} + +int do_backend_tests() +{ + mal_bool32 hasErrorOccurred = MAL_FALSE; + + // Tests are performed on a per-backend basis. + for (size_t iBackend = 0; iBackend < mal_countof(g_Backends); ++iBackend) { + int result = do_backend_test(g_Backends[iBackend]); + if (result < 0) { + hasErrorOccurred = MAL_TRUE; + } + } + + return (hasErrorOccurred) ? -1 : 0; +} + + +typedef struct +{ + mal_decoder* pDecoder; + mal_event endOfPlaybackEvent; +} playback_test_callback_data; + +mal_uint32 on_send__playback_test(mal_device* pDevice, mal_uint32 frameCount, void* pFrames) +{ + playback_test_callback_data* pData = (playback_test_callback_data*)pDevice->pUserData; + mal_assert(pData != NULL); + + mal_uint64 framesRead = mal_decoder_read(pData->pDecoder, frameCount, pFrames); + if (framesRead == 0) { + mal_event_signal(&pData->endOfPlaybackEvent); + } + + return (mal_uint32)framesRead; +} + +int do_playback_test(mal_backend backend) +{ + mal_result result = MAL_SUCCESS; + mal_device device; + mal_decoder decoder; + mal_bool32 haveDevice = MAL_FALSE; + mal_bool32 haveDecoder = MAL_FALSE; + + playback_test_callback_data callbackData; + callbackData.pDecoder = &decoder; + + printf("--- %s ---\n", mal_get_backend_name(backend)); + + // Device. + printf(" Opening Device... "); + { + mal_context_config contextConfig = mal_context_config_init(on_log); + mal_device_config deviceConfig = mal_device_config_init_default_playback(on_send__playback_test); + + result = mal_device_init_ex(&backend, 1, &contextConfig, mal_device_type_playback, NULL, &deviceConfig, &callbackData, &device); + if (result == MAL_SUCCESS) { + printf("Done\n"); + } else { + if (result == MAL_NO_BACKEND) { + printf(" Not supported\n"); + printf("--- End %s ---\n", mal_get_backend_name(backend)); + printf("\n"); + return 0; + } else { + printf(" Failed\n"); + goto done; + } + } + haveDevice = MAL_TRUE; + } + + printf(" Opening Decoder... "); + { + result = mal_event_init(device.pContext, &callbackData.endOfPlaybackEvent); + if (result != MAL_SUCCESS) { + printf("Failed to init event.\n"); + goto done; + } + + mal_decoder_config decoderConfig = mal_decoder_config_init(device.format, device.channels, device.sampleRate); + result = mal_decoder_init_file("res/sine_s16_mono_48000.wav", &decoderConfig, &decoder); + if (result == MAL_SUCCESS) { + printf("Done\n"); + } else { + printf("Failed to init decoder.\n"); + goto done; + } + haveDecoder = MAL_TRUE; + } + + printf(" Press Enter to start playback... "); + getchar(); + { + result = mal_device_start(&device); + if (result != MAL_SUCCESS) { + printf("Failed to start device.\n"); + goto done; + } + + mal_event_wait(&callbackData.endOfPlaybackEvent); // Wait for the sound to finish. + printf("Done\n"); + } + +done: + printf("--- End %s ---\n", mal_get_backend_name(backend)); + printf("\n"); + + if (haveDevice) { + mal_device_uninit(&device); + } + if (haveDecoder) { + mal_decoder_uninit(&decoder); + } + return (result == MAL_SUCCESS) ? 0 : -1; +} + +int do_playback_tests() +{ + mal_bool32 hasErrorOccurred = MAL_FALSE; + + for (size_t iBackend = 0; iBackend < mal_countof(g_Backends); ++iBackend) { + int result = do_playback_test(g_Backends[iBackend]); + if (result < 0) { + hasErrorOccurred = MAL_TRUE; + } + } + + return (hasErrorOccurred) ? -1 : 0; +} + +int main(int argc, char** argv) +{ + (void)argc; + (void)argv; + + mal_bool32 hasErrorOccurred = MAL_FALSE; + int result = 0; + + printf("=== TESTING BACKENDS ===\n"); + result = do_backend_tests(); + if (result < 0) { + hasErrorOccurred = MAL_TRUE; + } + printf("=== END TESTING BACKENDS ===\n"); + + printf("\n"); + + printf("=== TESTING DEFAULT PLAYBACK DEVICES ===\n"); + result = do_playback_tests(); + if (result < 0) { + hasErrorOccurred = MAL_TRUE; + } + printf("=== END TESTING DEFAULT PLAYBACK DEVICES ===\n"); + + return (hasErrorOccurred) ? -1 : 0; +} + +#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" + +#ifdef MAL_INCLUDE_VORBIS_TESTS + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable:4456) + #pragma warning(disable:4457) + #pragma warning(disable:4100) + #pragma warning(disable:4244) + #pragma warning(disable:4701) + #pragma warning(disable:4245) + #endif + #if defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-value" + #pragma GCC diagnostic ignored "-Wunused-parameter" + #ifndef __clang__ + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + #endif + #endif + #undef STB_VORBIS_HEADER_ONLY + #include "../extras/stb_vorbis.c" + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + #if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif +#endif \ No newline at end of file diff --git a/tests/mal_test_0.cpp b/tests/mal_test_0.cpp new file mode 100644 index 00000000..5a18a33d --- /dev/null +++ b/tests/mal_test_0.cpp @@ -0,0 +1 @@ +#include "mal_test_0.c" \ No newline at end of file diff --git a/tests/mal_test_0.vcxproj b/tests/mal_test_0.vcxproj new file mode 100644 index 00000000..cc96a905 --- /dev/null +++ b/tests/mal_test_0.vcxproj @@ -0,0 +1,196 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {3430EEA2-AC6E-4DC7-B684-1F698D01FAE8} + Win32Proj + mal_test_0 + 10.0.15063.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + ../../../mal/ + $(IncludePath) + C:\dev-other\SDL2-2.0.3\lib\x86;C:\dev-other\openal-soft-1.16.0-bin\libs\Win32;$(LibraryPath) + + + true + ../../../mal/ + $(IncludePath) + + + false + ../../../mal/ + $(IncludePath) + C:\dev-other\SDL2-2.0.3\lib\x86;$(LibraryPath) + + + false + ../../../mal/ + $(IncludePath) + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + %(AdditionalIncludeDirectories) + MultiThreadedDebug + Default + + + Console + true + %(AdditionalDependencies) + + + + + + + + + Level4 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + %(AdditionalIncludeDirectories) + MultiThreadedDebug + Default + + + Console + true + %(AdditionalDependencies) + + + + + Level4 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + %(AdditionalIncludeDirectories) + Default + + + Console + true + true + true + %(AdditionalDependencies) + + + + + + + Level4 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + %(AdditionalIncludeDirectories) + Default + + + Console + true + true + true + %(AdditionalDependencies) + + + + + false + false + false + false + + + true + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/tests/mal_test_0.vcxproj.filters b/tests/mal_test_0.vcxproj.filters new file mode 100644 index 00000000..93ad1440 --- /dev/null +++ b/tests/mal_test_0.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/tests/mal_test_0_build b/tests/mal_test_0_build new file mode 100644 index 00000000..fcc72cd3 --- /dev/null +++ b/tests/mal_test_0_build @@ -0,0 +1,3 @@ +#!/bin/bash +cc mal_test_0.c -o ./bin/mal_test_0 -Wall -ldl -lpthread +c++ mal_test_0.cpp -o ./bin/mal_test_0_cpp -Wall -ldl -lpthread \ No newline at end of file diff --git a/tests/mal_test_0_build.bat b/tests/mal_test_0_build.bat new file mode 100644 index 00000000..b03dd118 --- /dev/null +++ b/tests/mal_test_0_build.bat @@ -0,0 +1,2 @@ +gcc mal_test_0.c -o bin/mal_test_0.exe -Wall +g++ mal_test_0.cpp -o bin/mal_test_0_cpp.exe -Wall \ No newline at end of file diff --git a/tests/res/sine_s16_mono_48000.wav b/tests/res/sine_s16_mono_48000.wav new file mode 100644 index 00000000..b73ec500 Binary files /dev/null and b/tests/res/sine_s16_mono_48000.wav differ