diff --git a/mini_al.h b/mini_al.h index e33cd2e2..29b536c8 100644 --- a/mini_al.h +++ b/mini_al.h @@ -212,6 +212,7 @@ extern "C" { #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable:4201) // nonstandard extension used: nameless struct/union + #pragma warning(disable:4324) // structure was padded due to alignment specifier #endif // Platform/backend detection. @@ -317,30 +318,63 @@ extern "C" { #include // For size_t. -#if defined(_MSC_VER) && _MSC_VER < 1600 -typedef signed char mal_int8; -typedef unsigned char mal_uint8; -typedef signed short mal_int16; -typedef unsigned short mal_uint16; -typedef signed int mal_int32; -typedef unsigned int mal_uint32; -typedef signed __int64 mal_int64; -typedef unsigned __int64 mal_uint64; +#ifndef MAL_HAS_STDINT + #if defined(_MSC_VER) + #if _MSC_VER >= 1600 + #define MAL_HAS_STDINT + #endif + #else + #if defined(__has_include) && __has_include() + #define MAL_HAS_STDINT + #endif + #endif +#endif + +#ifndef MAL_HAS_STDINT +typedef signed char mal_int8; +typedef unsigned char mal_uint8; +typedef signed short mal_int16; +typedef unsigned short mal_uint16; +typedef signed int mal_int32; +typedef unsigned int mal_uint32; + #if defined(_MSC_VER) + typedef signed __int64 mal_int64; + typedef unsigned __int64 mal_uint64; + #elif defined(__GNUC__) + typedef signed long long int mal_int64; + typedef unsigned long long int mal_uint64; + #endif + #if defined(_WIN32) + #if defined(_WIN64) + typedef mal_uint64 mal_uintptr; + #else + typedef mal_uint32 mal_uintptr; + #endif + #elif defined(__GNUC__) + #if defined(__LP64__) + typedef mal_uint64 mal_uintptr; + #else + typedef mal_uint32 mal_uintptr; + #endif + #else + typedef mal_uint64 mal_uintptr; // Fallback. + #endif #else #include -typedef int8_t mal_int8; -typedef uint8_t mal_uint8; -typedef int16_t mal_int16; -typedef uint16_t mal_uint16; -typedef int32_t mal_int32; -typedef uint32_t mal_uint32; -typedef int64_t mal_int64; -typedef uint64_t mal_uint64; +typedef int8_t mal_int8; +typedef uint8_t mal_uint8; +typedef int16_t mal_int16; +typedef uint16_t mal_uint16; +typedef int32_t mal_int32; +typedef uint32_t mal_uint32; +typedef int64_t mal_int64; +typedef uint64_t mal_uint64; +typedef uintptr_t mal_uintptr; #endif -typedef mal_uint8 mal_bool8; -typedef mal_uint32 mal_bool32; -#define MAL_TRUE 1 -#define MAL_FALSE 0 +typedef mal_uint8 mal_bool8; +typedef mal_uint32 mal_bool32; +#define MAL_TRUE 1 +#define MAL_FALSE 0 typedef void* mal_handle; typedef void* mal_ptr; @@ -349,6 +383,40 @@ typedef void (* mal_proc)(); typedef struct mal_context mal_context; typedef struct mal_device mal_device; +#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED) +typedef mal_uint16 wchar_t; +#endif + +// Define NULL for some compilers. +#ifndef NULL +#define NULL 0 +#endif + +#ifdef _MSC_VER +#define MAL_INLINE __forceinline +#else +#ifdef __GNUC__ +#define MAL_INLINE inline __attribute__((always_inline)) +#else +#define MAL_INLINE inline +#endif +#endif + +#ifdef _MSC_VER +#define MAL_ALIGN(alignment) __declspec(align(alignment)) +#else +#define MAL_ALIGN(alignment) __attribute__((aligned(alignment))) +#endif + +#ifdef _MSC_VER +#define MAL_ALIGNED_STRUCT(alignment) MAL_ALIGN(alignment) struct +#else +#define MAL_ALIGNED_STRUCT(alignment) struct MAL_ALIGN(alignment) +#endif + +// SIMD alignment in bytes. Currently set to 64 bytes in preparation for future AVX-512 optimizations. +#define MAL_SIMD_ALIGNMENT 64 + // Thread priorties should be ordered such that the default priority of the worker thread is 0. typedef enum { @@ -433,14 +501,6 @@ typedef struct }; } mal_event; -#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED) -typedef mal_uint16 wchar_t; -#endif - -// Define NULL for some compilers. -#ifndef NULL -#define NULL 0 -#endif #define MAL_MAX_PERIODS_DSOUND 4 #define MAL_MAX_PERIODS_OPENAL 4 @@ -757,15 +817,6 @@ typedef enum mal_src_algorithm_default = mal_src_algorithm_linear } mal_src_algorithm; -#define MAL_SRC_CACHE_SIZE_IN_FRAMES 256 -typedef struct -{ - mal_src* pSRC; - float cachedFrames[MAL_MAX_CHANNELS][MAL_SRC_CACHE_SIZE_IN_FRAMES]; - mal_uint32 cachedFrameCount; - mal_uint32 iNextFrame; -} mal_src_cache; - typedef struct { mal_uint32 sampleRateIn; @@ -776,16 +827,15 @@ typedef struct void* pUserData; } mal_src_config; -struct mal_src +MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_src { + float samplesFromClient[MAL_MAX_CHANNELS][256]; mal_src_config config; - float bin[MAL_MAX_CHANNELS][32]; union { struct { - float samplesFromClient[MAL_MAX_CHANNELS][256]; float t; mal_uint32 leftoverFrames; } linear; @@ -812,7 +862,7 @@ typedef struct void* pUserData; } mal_dsp_config; -struct mal_dsp +MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_dsp { mal_dsp_read_proc onRead; void* pUserData; @@ -1234,7 +1284,7 @@ struct mal_context }; }; -struct mal_device +MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device { mal_context* pContext; mal_device_type type; @@ -1705,7 +1755,7 @@ mal_uint32 mal_device_get_buffer_size_in_bytes(mal_device* pDevice); // Thread Safety: SAFE // This is API is pure. mal_uint32 mal_get_bytes_per_sample(mal_format format); -static inline mal_uint32 mal_get_bytes_per_frame(mal_format format, mal_uint32 channels) { return mal_get_bytes_per_sample(format) * channels; } +static MAL_INLINE mal_uint32 mal_get_bytes_per_frame(mal_format format, mal_uint32 channels) { return mal_get_bytes_per_sample(format) * channels; } // Helper function for initializing a mal_context_config object. mal_context_config mal_context_config_init(mal_log_proc onLog); @@ -1789,15 +1839,15 @@ mal_device_config mal_device_config_init_default_playback(mal_send_proc onSendCa mal_device_config mal_device_config_init_ex(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_channel channelMap[MAL_MAX_CHANNELS], mal_recv_proc onRecvCallback, mal_send_proc onSendCallback); // A simplified version of mal_device_config_init_ex(). -static inline mal_device_config mal_device_config_init(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_recv_proc onRecvCallback, mal_send_proc onSendCallback) { return mal_device_config_init_ex(format, channels, sampleRate, NULL, onRecvCallback, onSendCallback); } +static MAL_INLINE mal_device_config mal_device_config_init(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_recv_proc onRecvCallback, mal_send_proc onSendCallback) { return mal_device_config_init_ex(format, channels, sampleRate, NULL, onRecvCallback, onSendCallback); } // A simplified version of mal_device_config_init() for capture devices. -static inline mal_device_config mal_device_config_init_capture_ex(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_channel channelMap[MAL_MAX_CHANNELS], mal_recv_proc onRecvCallback) { return mal_device_config_init_ex(format, channels, sampleRate, channelMap, onRecvCallback, NULL); } -static inline mal_device_config mal_device_config_init_capture(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_recv_proc onRecvCallback) { return mal_device_config_init_capture_ex(format, channels, sampleRate, NULL, onRecvCallback); } +static MAL_INLINE mal_device_config mal_device_config_init_capture_ex(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_channel channelMap[MAL_MAX_CHANNELS], mal_recv_proc onRecvCallback) { return mal_device_config_init_ex(format, channels, sampleRate, channelMap, onRecvCallback, NULL); } +static MAL_INLINE mal_device_config mal_device_config_init_capture(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_recv_proc onRecvCallback) { return mal_device_config_init_capture_ex(format, channels, sampleRate, NULL, onRecvCallback); } // A simplified version of mal_device_config_init() for playback devices. -static inline mal_device_config mal_device_config_init_playback_ex(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_channel channelMap[MAL_MAX_CHANNELS], mal_send_proc onSendCallback) { return mal_device_config_init_ex(format, channels, sampleRate, channelMap, NULL, onSendCallback); } -static inline mal_device_config mal_device_config_init_playback(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_send_proc onSendCallback) { return mal_device_config_init_playback_ex(format, channels, sampleRate, NULL, onSendCallback); } +static MAL_INLINE mal_device_config mal_device_config_init_playback_ex(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_channel channelMap[MAL_MAX_CHANNELS], mal_send_proc onSendCallback) { return mal_device_config_init_ex(format, channels, sampleRate, channelMap, NULL, onSendCallback); } +static MAL_INLINE mal_device_config mal_device_config_init_playback(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_send_proc onSendCallback) { return mal_device_config_init_playback_ex(format, channels, sampleRate, NULL, onSendCallback); } // Helper for retrieving a standard channel map. @@ -2033,6 +2083,12 @@ void mal_mutex_unlock(mal_mutex* pMutex); // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Performs an aligned malloc, with the assumption that the alignment is a power of 2. +void* mal_aligned_malloc(size_t sz, size_t alignment); + +// Free's an aligned malloc'd buffer. +void mal_aligned_free(void* p); + // Retrieves a friendly name for a backend. const char* mal_get_backend_name(mal_backend backend); @@ -2680,7 +2736,7 @@ int mal_strcmp(const char* str1, const char* str2) // Thanks to good old Bit Twiddling Hacks for this one: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 -static inline unsigned int mal_next_power_of_2(unsigned int x) +static MAL_INLINE unsigned int mal_next_power_of_2(unsigned int x) { x--; x |= x >> 1; @@ -2693,12 +2749,12 @@ static inline unsigned int mal_next_power_of_2(unsigned int x) return x; } -static inline unsigned int mal_prev_power_of_2(unsigned int x) +static MAL_INLINE unsigned int mal_prev_power_of_2(unsigned int x) { return mal_next_power_of_2(x) >> 1; } -static inline unsigned int mal_round_to_power_of_2(unsigned int x) +static MAL_INLINE unsigned int mal_round_to_power_of_2(unsigned int x) { unsigned int prev = mal_prev_power_of_2(x); unsigned int next = mal_next_power_of_2(x); @@ -2712,14 +2768,14 @@ static inline unsigned int mal_round_to_power_of_2(unsigned int x) // Clamps an f32 sample to -1..1 -static inline float mal_clip_f32(float x) +static MAL_INLINE float mal_clip_f32(float x) { if (x < -1) return -1; if (x > +1) return +1; return x; } -static inline float mal_mix_f32(float x, float y, float a) +static MAL_INLINE float mal_mix_f32(float x, float y, float a) { return x*(1-a) + y*a; } @@ -3331,7 +3387,7 @@ mal_result mal_post_error(mal_device* pDevice, const char* message, mal_result r // The callback for reading from the client -> DSP -> device. -static inline mal_uint32 mal_device__on_read_from_client(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData) +mal_uint32 mal_device__on_read_from_client(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData) { (void)pDSP; @@ -3347,7 +3403,7 @@ static inline mal_uint32 mal_device__on_read_from_client(mal_dsp* pDSP, mal_uint } // The callback for reading from the device -> DSP -> client. -static inline mal_uint32 mal_device__on_read_from_device(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData) +mal_uint32 mal_device__on_read_from_device(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData) { (void)pDSP; @@ -3373,7 +3429,7 @@ static inline mal_uint32 mal_device__on_read_from_device(mal_dsp* pDSP, mal_uint // A helper function for reading sample data from the client. Returns the number of samples read from the client. Remaining samples // are filled with silence. -static inline mal_uint32 mal_device__read_frames_from_client(mal_device* pDevice, mal_uint32 frameCount, void* pSamples) +static MAL_INLINE mal_uint32 mal_device__read_frames_from_client(mal_device* pDevice, mal_uint32 frameCount, void* pSamples) { mal_assert(pDevice != NULL); mal_assert(frameCount > 0); @@ -3390,7 +3446,7 @@ static inline mal_uint32 mal_device__read_frames_from_client(mal_device* pDevice } // A helper for sending sample data to the client. -static inline void mal_device__send_frames_to_client(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples) +static MAL_INLINE void mal_device__send_frames_to_client(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples) { mal_assert(pDevice != NULL); mal_assert(frameCount > 0); @@ -3420,13 +3476,13 @@ static inline void mal_device__send_frames_to_client(mal_device* pDevice, mal_ui } // A helper for changing the state of the device. -static inline void mal_device__set_state(mal_device* pDevice, mal_uint32 newState) +static MAL_INLINE void mal_device__set_state(mal_device* pDevice, mal_uint32 newState) { mal_atomic_exchange_32(&pDevice->state, newState); } // A helper for getting the state of the device. -static inline mal_uint32 mal_device__get_state(mal_device* pDevice) +static MAL_INLINE mal_uint32 mal_device__get_state(mal_device* pDevice) { return pDevice->state; } @@ -4047,7 +4103,7 @@ typedef struct #endif // Some compilers don't define PropVariantInit(). We just do this ourselves since it's just a memset(). -static inline void mal_PropVariantInit(PROPVARIANT* pProp) +static MAL_INLINE void mal_PropVariantInit(PROPVARIANT* pProp) { mal_zero_object(pProp); } @@ -17167,7 +17223,7 @@ typedef struct float z; } mal_vec3; -static inline mal_vec3 mal_vec3f(float x, float y, float z) +static MAL_INLINE mal_vec3 mal_vec3f(float x, float y, float z) { mal_vec3 r; r.x = x; @@ -17177,7 +17233,7 @@ static inline mal_vec3 mal_vec3f(float x, float y, float z) return r; } -static inline mal_vec3 mal_vec3_add(mal_vec3 a, mal_vec3 b) +static MAL_INLINE mal_vec3 mal_vec3_add(mal_vec3 a, mal_vec3 b) { return mal_vec3f( a.x + b.x, @@ -17186,7 +17242,7 @@ static inline mal_vec3 mal_vec3_add(mal_vec3 a, mal_vec3 b) ); } -static inline mal_vec3 mal_vec3_sub(mal_vec3 a, mal_vec3 b) +static MAL_INLINE mal_vec3 mal_vec3_sub(mal_vec3 a, mal_vec3 b) { return mal_vec3f( a.x - b.x, @@ -17195,7 +17251,7 @@ static inline mal_vec3 mal_vec3_sub(mal_vec3 a, mal_vec3 b) ); } -static inline mal_vec3 mal_vec3_mul(mal_vec3 a, mal_vec3 b) +static MAL_INLINE mal_vec3 mal_vec3_mul(mal_vec3 a, mal_vec3 b) { return mal_vec3f( a.x * b.x, @@ -17204,7 +17260,7 @@ static inline mal_vec3 mal_vec3_mul(mal_vec3 a, mal_vec3 b) ); } -static inline mal_vec3 mal_vec3_div(mal_vec3 a, mal_vec3 b) +static MAL_INLINE mal_vec3 mal_vec3_div(mal_vec3 a, mal_vec3 b) { return mal_vec3f( a.x / b.x, @@ -17213,22 +17269,22 @@ static inline mal_vec3 mal_vec3_div(mal_vec3 a, mal_vec3 b) ); } -static inline float mal_vec3_dot(mal_vec3 a, mal_vec3 b) +static MAL_INLINE float mal_vec3_dot(mal_vec3 a, mal_vec3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; } -static inline float mal_vec3_length2(mal_vec3 a) +static MAL_INLINE float mal_vec3_length2(mal_vec3 a) { return mal_vec3_dot(a, a); } -static inline float mal_vec3_length(mal_vec3 a) +static MAL_INLINE float mal_vec3_length(mal_vec3 a) { return (float)sqrt(mal_vec3_length2(a)); } -static inline mal_vec3 mal_vec3_normalize(mal_vec3 a) +static MAL_INLINE mal_vec3 mal_vec3_normalize(mal_vec3 a) { float len = 1 / mal_vec3_length(a); @@ -17240,7 +17296,7 @@ static inline mal_vec3 mal_vec3_normalize(mal_vec3 a) return r; } -static inline float mal_vec3_distance(mal_vec3 a, mal_vec3 b) +static MAL_INLINE float mal_vec3_distance(mal_vec3 a, mal_vec3 b) { return mal_vec3_length(mal_vec3_sub(a, b)); } @@ -17855,7 +17911,7 @@ mal_uint64 mal_src_read_deinterleaved__linear(mal_src* pSRC, mal_uint64 frameCou float factor = (float)pSRC->config.sampleRateIn / pSRC->config.sampleRateOut; - mal_uint32 maxFrameCountPerChunkIn = mal_countof(pSRC->linear.samplesFromClient[0]); + mal_uint32 maxFrameCountPerChunkIn = mal_countof(pSRC->samplesFromClient[0]); mal_uint64 totalFramesRead = 0; while (totalFramesRead < frameCount) { @@ -17878,7 +17934,7 @@ mal_uint64 mal_src_read_deinterleaved__linear(mal_src* pSRC, mal_uint64 frameCou float* ppSamplesFromClient[MAL_MAX_CHANNELS]; for (mal_uint32 iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) { - ppSamplesFromClient[iChannel] = pSRC->linear.samplesFromClient[iChannel] + pSRC->linear.leftoverFrames; + ppSamplesFromClient[iChannel] = pSRC->samplesFromClient[iChannel] + pSRC->linear.leftoverFrames; } mal_uint32 framesReadFromClient = 0; @@ -17892,7 +17948,7 @@ mal_uint64 mal_src_read_deinterleaved__linear(mal_src* pSRC, mal_uint64 frameCou } for (mal_uint32 iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) { - ppSamplesFromClient[iChannel] = pSRC->linear.samplesFromClient[iChannel]; + ppSamplesFromClient[iChannel] = pSRC->samplesFromClient[iChannel]; } @@ -18596,6 +18652,30 @@ mal_uint64 mal_convert_frames_ex(void* pOut, mal_format formatOut, mal_uint32 ch ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void* mal_aligned_malloc(size_t sz, size_t alignment) +{ + if (alignment == 0) { + return 0; + } + + size_t extraBytes = alignment-1 + sizeof(void*); + + void* pUnaligned = mal_malloc(sz + extraBytes); + if (pUnaligned == NULL) { + return NULL; + } + + void* pAligned = (void*)(((mal_uintptr)pUnaligned + extraBytes) & ~((mal_uintptr)(alignment-1))); + ((void**)pAligned)[-1] = pUnaligned; + + return pAligned; +} + +void mal_aligned_free(void* p) +{ + mal_free(((void**)p)[-1]); +} + const char* mal_get_backend_name(mal_backend backend) { switch (backend) diff --git a/tests/mal_test_0.c b/tests/mal_test_0.c index af7f6b32..c52be124 100644 --- a/tests/mal_test_0.c +++ b/tests/mal_test_0.c @@ -96,6 +96,158 @@ void* open_and_read_file_data(const char* filePath, size_t* pSizeOut) return pFileData; } + +int do_types_tests() +{ + int result = 0; + + int sizeof_int8 = sizeof(mal_int8); + int sizeof_uint8 = sizeof(mal_uint8); + int sizeof_int16 = sizeof(mal_int16); + int sizeof_uint16 = sizeof(mal_uint16); + int sizeof_int32 = sizeof(mal_int32); + int sizeof_uint32 = sizeof(mal_uint32); + int sizeof_int64 = sizeof(mal_int64); + int sizeof_uint64 = sizeof(mal_uint64); + int sizeof_float32 = sizeof(float); + int sizeof_float64 = sizeof(double); + int sizeof_uintptr = sizeof(mal_uintptr); + + printf("sizeof(mal_int8) 1 = %d", sizeof_int8); + if (sizeof_int8 != 1) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + printf("sizeof(mal_uint8) 1 = %d", sizeof_uint8); + if (sizeof_uint8 != 1) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + + printf("sizeof(mal_int16) 2 = %d", sizeof_int16); + if (sizeof_int16 != 2) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + printf("sizeof(mal_uint16) 2 = %d", sizeof_uint16); + if (sizeof_uint16 != 2) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + + printf("sizeof(mal_int32) 4 = %d", sizeof_int32); + if (sizeof_int32 != 4) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + printf("sizeof(mal_uint32) 4 = %d", sizeof_uint32); + if (sizeof_uint32 != 4) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + + printf("sizeof(mal_int64) 8 = %d", sizeof_int64); + if (sizeof_int64 != 8) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + printf("sizeof(mal_uint64) 8 = %d", sizeof_uint64); + if (sizeof_uint64 != 8) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + + printf("sizeof(float) 4 = %d", sizeof_float32); + if (sizeof_float32 != 4) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + printf("sizeof(double) 8 = %d", sizeof_float64); + if (sizeof_float64 != 8) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + + printf("sizeof(mal_uintptr) %d = %d", (int)sizeof(void*), sizeof_uintptr); + if (sizeof_uintptr != sizeof(void*)) { + printf(" - FAILED\n"); + result = -1; + } else { + printf(" - PASSED\n"); + } + + return result; +} + +int do_aligned_malloc_tests() +{ + int result = 0; + + // We just do a whole bunch of malloc's and check them. This can probably be made more exhaustive. + void* p[1024]; + for (mal_uint32 i = 0; i < mal_countof(p); ++i) { + mal_uintptr alignment = MAL_SIMD_ALIGNMENT; + + p[i] = mal_aligned_malloc(1024, alignment); + if (((mal_uintptr)p[i] & (alignment-1)) != 0) { + printf("FAILED\n"); + result = -1; + } + } + + // Free. + for (mal_uint32 i = 0; i < mal_countof(p); ++i) { + mal_aligned_free(p[i]); + } + + if (result == 0) { + printf("PASSED\n"); + } + + return result; +} + +int do_core_tests() +{ + int result = 0; + + printf("Types...\n"); + if (do_types_tests() != 0) { + printf("FAILED\n"); + result = -1; + } else { + printf("PASSED\n"); + } + + printf("Aligned malloc... "); + if (do_aligned_malloc_tests() != 0) { + result = -1; + } + + return result; +} + + void* load_raw_audio_data(const char* filePath, mal_format format, mal_uint64* pBenchmarkFrameCount) { mal_assert(pBenchmarkFrameCount != NULL); @@ -2130,6 +2282,16 @@ int main(int argc, char** argv) mal_bool32 hasErrorOccurred = MAL_FALSE; int result = 0; + // Aligned malloc/free + printf("=== TESTING CORE ===\n"); + result = do_core_tests(); + if (result < 0) { + hasErrorOccurred = MAL_TRUE; + } + printf("=== END TESTING CORE ===\n"); + + printf("\n"); + // Format Conversion printf("=== TESTING FORMAT CONVERSION ===\n"); result = do_format_conversion_tests();