Commit 9245dce6 authored by David Reid's avatar David Reid

Prep work for some SIMD optimizations.

parent e7bc174b
...@@ -212,6 +212,7 @@ extern "C" { ...@@ -212,6 +212,7 @@ extern "C" {
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4201) // nonstandard extension used: nameless struct/union #pragma warning(disable:4201) // nonstandard extension used: nameless struct/union
#pragma warning(disable:4324) // structure was padded due to alignment specifier
#endif #endif
// Platform/backend detection. // Platform/backend detection.
...@@ -317,30 +318,63 @@ extern "C" { ...@@ -317,30 +318,63 @@ extern "C" {
#include <stddef.h> // For size_t. #include <stddef.h> // For size_t.
#if defined(_MSC_VER) && _MSC_VER < 1600 #ifndef MAL_HAS_STDINT
typedef signed char mal_int8; #if defined(_MSC_VER)
typedef unsigned char mal_uint8; #if _MSC_VER >= 1600
typedef signed short mal_int16; #define MAL_HAS_STDINT
typedef unsigned short mal_uint16; #endif
typedef signed int mal_int32; #else
typedef unsigned int mal_uint32; #if defined(__has_include) && __has_include(<stdint.h>)
typedef signed __int64 mal_int64; #define MAL_HAS_STDINT
typedef unsigned __int64 mal_uint64; #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 #else
#include <stdint.h> #include <stdint.h>
typedef int8_t mal_int8; typedef int8_t mal_int8;
typedef uint8_t mal_uint8; typedef uint8_t mal_uint8;
typedef int16_t mal_int16; typedef int16_t mal_int16;
typedef uint16_t mal_uint16; typedef uint16_t mal_uint16;
typedef int32_t mal_int32; typedef int32_t mal_int32;
typedef uint32_t mal_uint32; typedef uint32_t mal_uint32;
typedef int64_t mal_int64; typedef int64_t mal_int64;
typedef uint64_t mal_uint64; typedef uint64_t mal_uint64;
#endif typedef uintptr_t mal_uintptr;
typedef mal_uint8 mal_bool8; #endif
typedef mal_uint32 mal_bool32; typedef mal_uint8 mal_bool8;
#define MAL_TRUE 1 typedef mal_uint32 mal_bool32;
#define MAL_FALSE 0 #define MAL_TRUE 1
#define MAL_FALSE 0
typedef void* mal_handle; typedef void* mal_handle;
typedef void* mal_ptr; typedef void* mal_ptr;
...@@ -349,6 +383,40 @@ typedef void (* mal_proc)(); ...@@ -349,6 +383,40 @@ typedef void (* mal_proc)();
typedef struct mal_context mal_context; typedef struct mal_context mal_context;
typedef struct mal_device mal_device; 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. // Thread priorties should be ordered such that the default priority of the worker thread is 0.
typedef enum typedef enum
{ {
...@@ -433,14 +501,6 @@ typedef struct ...@@ -433,14 +501,6 @@ typedef struct
}; };
} mal_event; } 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_DSOUND 4
#define MAL_MAX_PERIODS_OPENAL 4 #define MAL_MAX_PERIODS_OPENAL 4
...@@ -757,15 +817,6 @@ typedef enum ...@@ -757,15 +817,6 @@ typedef enum
mal_src_algorithm_default = mal_src_algorithm_linear mal_src_algorithm_default = mal_src_algorithm_linear
} mal_src_algorithm; } 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 typedef struct
{ {
mal_uint32 sampleRateIn; mal_uint32 sampleRateIn;
...@@ -776,16 +827,15 @@ typedef struct ...@@ -776,16 +827,15 @@ typedef struct
void* pUserData; void* pUserData;
} mal_src_config; } mal_src_config;
struct mal_src MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_src
{ {
float samplesFromClient[MAL_MAX_CHANNELS][256];
mal_src_config config; mal_src_config config;
float bin[MAL_MAX_CHANNELS][32];
union union
{ {
struct struct
{ {
float samplesFromClient[MAL_MAX_CHANNELS][256];
float t; float t;
mal_uint32 leftoverFrames; mal_uint32 leftoverFrames;
} linear; } linear;
...@@ -812,7 +862,7 @@ typedef struct ...@@ -812,7 +862,7 @@ typedef struct
void* pUserData; void* pUserData;
} mal_dsp_config; } mal_dsp_config;
struct mal_dsp MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_dsp
{ {
mal_dsp_read_proc onRead; mal_dsp_read_proc onRead;
void* pUserData; void* pUserData;
...@@ -1234,7 +1284,7 @@ struct mal_context ...@@ -1234,7 +1284,7 @@ struct mal_context
}; };
}; };
struct mal_device MAL_ALIGNED_STRUCT(MAL_SIMD_ALIGNMENT) mal_device
{ {
mal_context* pContext; mal_context* pContext;
mal_device_type type; mal_device_type type;
...@@ -1705,7 +1755,7 @@ mal_uint32 mal_device_get_buffer_size_in_bytes(mal_device* pDevice); ...@@ -1705,7 +1755,7 @@ mal_uint32 mal_device_get_buffer_size_in_bytes(mal_device* pDevice);
// Thread Safety: SAFE // Thread Safety: SAFE
// This is API is pure. // This is API is pure.
mal_uint32 mal_get_bytes_per_sample(mal_format format); 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. // Helper function for initializing a mal_context_config object.
mal_context_config mal_context_config_init(mal_log_proc onLog); 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 ...@@ -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); 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(). // 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. // 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 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 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(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. // 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 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 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(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. // Helper for retrieving a standard channel map.
...@@ -2033,6 +2083,12 @@ void mal_mutex_unlock(mal_mutex* pMutex); ...@@ -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. // Retrieves a friendly name for a backend.
const char* mal_get_backend_name(mal_backend backend); const char* mal_get_backend_name(mal_backend backend);
...@@ -2680,7 +2736,7 @@ int mal_strcmp(const char* str1, const char* str2) ...@@ -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 // 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 |= x >> 1; x |= x >> 1;
...@@ -2693,12 +2749,12 @@ static inline unsigned int mal_next_power_of_2(unsigned int x) ...@@ -2693,12 +2749,12 @@ static inline unsigned int mal_next_power_of_2(unsigned int x)
return 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; 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 prev = mal_prev_power_of_2(x);
unsigned int next = mal_next_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) ...@@ -2712,14 +2768,14 @@ static inline unsigned int mal_round_to_power_of_2(unsigned int x)
// Clamps an f32 sample to -1..1 // 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;
if (x > +1) return +1; if (x > +1) return +1;
return x; 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; return x*(1-a) + y*a;
} }
...@@ -3331,7 +3387,7 @@ mal_result mal_post_error(mal_device* pDevice, const char* message, mal_result r ...@@ -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. // 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; (void)pDSP;
...@@ -3347,7 +3403,7 @@ static inline mal_uint32 mal_device__on_read_from_client(mal_dsp* pDSP, mal_uint ...@@ -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. // 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; (void)pDSP;
...@@ -3373,7 +3429,7 @@ static inline mal_uint32 mal_device__on_read_from_device(mal_dsp* pDSP, mal_uint ...@@ -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 // 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. // 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(pDevice != NULL);
mal_assert(frameCount > 0); mal_assert(frameCount > 0);
...@@ -3390,7 +3446,7 @@ static inline mal_uint32 mal_device__read_frames_from_client(mal_device* pDevice ...@@ -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. // 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(pDevice != NULL);
mal_assert(frameCount > 0); mal_assert(frameCount > 0);
...@@ -3420,13 +3476,13 @@ static inline void mal_device__send_frames_to_client(mal_device* pDevice, mal_ui ...@@ -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. // 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); mal_atomic_exchange_32(&pDevice->state, newState);
} }
// A helper for getting the state of the device. // 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; return pDevice->state;
} }
...@@ -4047,7 +4103,7 @@ typedef struct ...@@ -4047,7 +4103,7 @@ typedef struct
#endif #endif
// Some compilers don't define PropVariantInit(). We just do this ourselves since it's just a memset(). // 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); mal_zero_object(pProp);
} }
...@@ -17167,7 +17223,7 @@ typedef struct ...@@ -17167,7 +17223,7 @@ typedef struct
float z; float z;
} mal_vec3; } 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; mal_vec3 r;
r.x = x; r.x = x;
...@@ -17177,7 +17233,7 @@ static inline mal_vec3 mal_vec3f(float x, float y, float z) ...@@ -17177,7 +17233,7 @@ static inline mal_vec3 mal_vec3f(float x, float y, float z)
return r; 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( return mal_vec3f(
a.x + b.x, a.x + b.x,
...@@ -17186,7 +17242,7 @@ static inline mal_vec3 mal_vec3_add(mal_vec3 a, mal_vec3 b) ...@@ -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( return mal_vec3f(
a.x - b.x, a.x - b.x,
...@@ -17195,7 +17251,7 @@ static inline mal_vec3 mal_vec3_sub(mal_vec3 a, mal_vec3 b) ...@@ -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( return mal_vec3f(
a.x * b.x, a.x * b.x,
...@@ -17204,7 +17260,7 @@ static inline mal_vec3 mal_vec3_mul(mal_vec3 a, mal_vec3 b) ...@@ -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( return mal_vec3f(
a.x / b.x, a.x / b.x,
...@@ -17213,22 +17269,22 @@ static inline mal_vec3 mal_vec3_div(mal_vec3 a, mal_vec3 b) ...@@ -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; 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); 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)); 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); float len = 1 / mal_vec3_length(a);
...@@ -17240,7 +17296,7 @@ static inline mal_vec3 mal_vec3_normalize(mal_vec3 a) ...@@ -17240,7 +17296,7 @@ static inline mal_vec3 mal_vec3_normalize(mal_vec3 a)
return r; 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)); 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 ...@@ -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; 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; mal_uint64 totalFramesRead = 0;
while (totalFramesRead < frameCount) { while (totalFramesRead < frameCount) {
...@@ -17878,7 +17934,7 @@ mal_uint64 mal_src_read_deinterleaved__linear(mal_src* pSRC, mal_uint64 frameCou ...@@ -17878,7 +17934,7 @@ mal_uint64 mal_src_read_deinterleaved__linear(mal_src* pSRC, mal_uint64 frameCou
float* ppSamplesFromClient[MAL_MAX_CHANNELS]; float* ppSamplesFromClient[MAL_MAX_CHANNELS];
for (mal_uint32 iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) { 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; mal_uint32 framesReadFromClient = 0;
...@@ -17892,7 +17948,7 @@ mal_uint64 mal_src_read_deinterleaved__linear(mal_src* pSRC, mal_uint64 frameCou ...@@ -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) { 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 ...@@ -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) const char* mal_get_backend_name(mal_backend backend)
{ {
switch (backend) switch (backend)
......
...@@ -96,6 +96,158 @@ void* open_and_read_file_data(const char* filePath, size_t* pSizeOut) ...@@ -96,6 +96,158 @@ void* open_and_read_file_data(const char* filePath, size_t* pSizeOut)
return pFileData; 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) void* load_raw_audio_data(const char* filePath, mal_format format, mal_uint64* pBenchmarkFrameCount)
{ {
mal_assert(pBenchmarkFrameCount != NULL); mal_assert(pBenchmarkFrameCount != NULL);
...@@ -2130,6 +2282,16 @@ int main(int argc, char** argv) ...@@ -2130,6 +2282,16 @@ int main(int argc, char** argv)
mal_bool32 hasErrorOccurred = MAL_FALSE; mal_bool32 hasErrorOccurred = MAL_FALSE;
int result = 0; 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 // Format Conversion
printf("=== TESTING FORMAT CONVERSION ===\n"); printf("=== TESTING FORMAT CONVERSION ===\n");
result = do_format_conversion_tests(); result = do_format_conversion_tests();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment