mirror of
https://github.com/raysan5/raylib.git
synced 2025-10-04 17:06:27 +00:00
Bring up to date with changes to mini_al.
This commit is contained in:
26
src/audio.c
26
src/audio.c
@@ -257,7 +257,7 @@ static AudioStreamData* lastAudioStream;
|
|||||||
|
|
||||||
static void AppendSound(SoundData* internalSound)
|
static void AppendSound(SoundData* internalSound)
|
||||||
{
|
{
|
||||||
mal_mutex_lock(&context, &soundLock);
|
mal_mutex_lock(&soundLock);
|
||||||
{
|
{
|
||||||
if (firstSound == NULL) {
|
if (firstSound == NULL) {
|
||||||
firstSound = internalSound;
|
firstSound = internalSound;
|
||||||
@@ -268,12 +268,12 @@ static void AppendSound(SoundData* internalSound)
|
|||||||
|
|
||||||
lastSound = internalSound;
|
lastSound = internalSound;
|
||||||
}
|
}
|
||||||
mal_mutex_unlock(&context, &soundLock);
|
mal_mutex_unlock(&soundLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RemoveSound(SoundData* internalSound)
|
static void RemoveSound(SoundData* internalSound)
|
||||||
{
|
{
|
||||||
mal_mutex_lock(&context, &soundLock);
|
mal_mutex_lock(&soundLock);
|
||||||
{
|
{
|
||||||
if (internalSound->prev == NULL) {
|
if (internalSound->prev == NULL) {
|
||||||
firstSound = internalSound->next;
|
firstSound = internalSound->next;
|
||||||
@@ -287,12 +287,12 @@ static void RemoveSound(SoundData* internalSound)
|
|||||||
internalSound->next->prev = internalSound->prev;
|
internalSound->next->prev = internalSound->prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mal_mutex_unlock(&context, &soundLock);
|
mal_mutex_unlock(&soundLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AppendAudioStream(AudioStreamData* internalAudioStream)
|
static void AppendAudioStream(AudioStreamData* internalAudioStream)
|
||||||
{
|
{
|
||||||
mal_mutex_lock(&context, &soundLock);
|
mal_mutex_lock(&soundLock);
|
||||||
{
|
{
|
||||||
if (firstAudioStream == NULL) {
|
if (firstAudioStream == NULL) {
|
||||||
firstAudioStream = internalAudioStream;
|
firstAudioStream = internalAudioStream;
|
||||||
@@ -303,12 +303,12 @@ static void AppendAudioStream(AudioStreamData* internalAudioStream)
|
|||||||
|
|
||||||
lastAudioStream = internalAudioStream;
|
lastAudioStream = internalAudioStream;
|
||||||
}
|
}
|
||||||
mal_mutex_unlock(&context, &soundLock);
|
mal_mutex_unlock(&soundLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RemoveAudioStream(AudioStreamData* internalAudioStream)
|
static void RemoveAudioStream(AudioStreamData* internalAudioStream)
|
||||||
{
|
{
|
||||||
mal_mutex_lock(&context, &soundLock);
|
mal_mutex_lock(&soundLock);
|
||||||
{
|
{
|
||||||
if (internalAudioStream->prev == NULL) {
|
if (internalAudioStream->prev == NULL) {
|
||||||
firstAudioStream = internalAudioStream->next;
|
firstAudioStream = internalAudioStream->next;
|
||||||
@@ -322,7 +322,7 @@ static void RemoveAudioStream(AudioStreamData* internalAudioStream)
|
|||||||
internalAudioStream->next->prev = internalAudioStream->prev;
|
internalAudioStream->next->prev = internalAudioStream->prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mal_mutex_unlock(&context, &soundLock);
|
mal_mutex_unlock(&soundLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ static mal_uint32 OnSendAudioDataToDevice(mal_device* pDevice, mal_uint32 frameC
|
|||||||
|
|
||||||
// Using a mutex here for thread-safety which makes things not real-time. This is unlikely to be necessary for this project, but may
|
// Using a mutex here for thread-safety which makes things not real-time. This is unlikely to be necessary for this project, but may
|
||||||
// want to consider how you might want to avoid this.
|
// want to consider how you might want to avoid this.
|
||||||
mal_mutex_lock(&context, &soundLock);
|
mal_mutex_lock(&soundLock);
|
||||||
{
|
{
|
||||||
float* pFramesOutF = (float*)pFramesOut; // <-- Just for convenience.
|
float* pFramesOutF = (float*)pFramesOut; // <-- Just for convenience.
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ static mal_uint32 OnSendAudioDataToDevice(mal_device* pDevice, mal_uint32 frameC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mal_mutex_unlock(&context, &soundLock);
|
mal_mutex_unlock(&soundLock);
|
||||||
|
|
||||||
return frameCount; // We always output the same number of frames that were originally requested.
|
return frameCount; // We always output the same number of frames that were originally requested.
|
||||||
}
|
}
|
||||||
@@ -493,7 +493,7 @@ void InitAudioDevice(void)
|
|||||||
|
|
||||||
// Mixing happens on a seperate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
|
// Mixing happens on a seperate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
|
||||||
// want to look at something a bit smarter later on to keep everything real-time, if that's necessary.
|
// want to look at something a bit smarter later on to keep everything real-time, if that's necessary.
|
||||||
if (!mal_mutex_create(&context, &soundLock))
|
if (mal_mutex_init(&context, &soundLock) != MAL_SUCCESS)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_ERROR, "Failed to create mutex for audio mixing");
|
TraceLog(LOG_ERROR, "Failed to create mutex for audio mixing");
|
||||||
mal_device_uninit(&device);
|
mal_device_uninit(&device);
|
||||||
@@ -550,7 +550,7 @@ void CloseAudioDevice(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_mutex_delete(&context, &soundLock);
|
mal_mutex_uninit(&soundLock);
|
||||||
mal_device_uninit(&device);
|
mal_device_uninit(&device);
|
||||||
mal_context_uninit(&context);
|
mal_context_uninit(&context);
|
||||||
#else
|
#else
|
||||||
@@ -1573,7 +1573,7 @@ float GetMusicTimePlayed(Music music)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static mal_uint32 UpdateAudioStream_OnDSPRead(mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
static mal_uint32 UpdateAudioStream_OnDSPRead(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
||||||
{
|
{
|
||||||
AudioStreamData* internalData = (AudioStreamData*)pUserData;
|
AudioStreamData* internalData = (AudioStreamData*)pUserData;
|
||||||
|
|
||||||
|
464
src/external/mini_al.h
vendored
464
src/external/mini_al.h
vendored
@@ -292,21 +292,80 @@ typedef void* mal_handle;
|
|||||||
typedef void* mal_ptr;
|
typedef void* mal_ptr;
|
||||||
typedef void (* mal_proc)();
|
typedef void (* mal_proc)();
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
typedef struct mal_context mal_context;
|
||||||
typedef mal_handle mal_thread;
|
typedef struct mal_device mal_device;
|
||||||
typedef mal_handle mal_mutex;
|
|
||||||
typedef mal_handle mal_event;
|
|
||||||
#else
|
|
||||||
typedef pthread_t mal_thread;
|
|
||||||
typedef pthread_mutex_t mal_mutex;
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
{
|
||||||
|
mal_context* pContext;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
#ifdef MAL_WIN32
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/*HANDLE*/ mal_handle hThread;
|
||||||
|
} win32;
|
||||||
|
#endif
|
||||||
|
#ifdef MAL_POSIX
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
pthread_t thread;
|
||||||
|
} posix;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int _unused;
|
||||||
|
};
|
||||||
|
} mal_thread;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
mal_context* pContext;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
#ifdef MAL_WIN32
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/*HANDLE*/ mal_handle hMutex;
|
||||||
|
} win32;
|
||||||
|
#endif
|
||||||
|
#ifdef MAL_POSIX
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
} posix;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int _unused;
|
||||||
|
};
|
||||||
|
} mal_mutex;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
mal_context* pContext;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
#ifdef MAL_WIN32
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/*HANDLE*/ mal_handle hEvent;
|
||||||
|
} win32;
|
||||||
|
#endif
|
||||||
|
#ifdef MAL_POSIX
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t condition;
|
pthread_cond_t condition;
|
||||||
mal_uint32 value;
|
mal_uint32 value;
|
||||||
} mal_event;
|
} posix;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int _unused;
|
||||||
|
};
|
||||||
|
} mal_event;
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
|
#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
|
||||||
typedef mal_uint16 wchar_t;
|
typedef mal_uint16 wchar_t;
|
||||||
#endif
|
#endif
|
||||||
@@ -393,9 +452,6 @@ typedef int mal_result;
|
|||||||
#define MAL_WINMM_FAILED_TO_GET_DEVICE_CAPS -4096
|
#define MAL_WINMM_FAILED_TO_GET_DEVICE_CAPS -4096
|
||||||
#define MAL_WINMM_FAILED_TO_GET_SUPPORTED_FORMATS -4097
|
#define MAL_WINMM_FAILED_TO_GET_SUPPORTED_FORMATS -4097
|
||||||
|
|
||||||
typedef struct mal_context mal_context;
|
|
||||||
typedef struct mal_device mal_device;
|
|
||||||
|
|
||||||
typedef void (* mal_log_proc) (mal_context* pContext, mal_device* pDevice, const char* message);
|
typedef void (* mal_log_proc) (mal_context* pContext, mal_device* pDevice, const char* message);
|
||||||
typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples);
|
typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples);
|
||||||
typedef mal_uint32 (* mal_send_proc)(mal_device* pDevice, mal_uint32 frameCount, void* pSamples);
|
typedef mal_uint32 (* mal_send_proc)(mal_device* pDevice, mal_uint32 frameCount, void* pSamples);
|
||||||
@@ -481,7 +537,7 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
typedef struct mal_src mal_src;
|
typedef struct mal_src mal_src;
|
||||||
typedef mal_uint32 (* mal_src_read_proc)(mal_uint32 frameCount, void* pFramesOut, void* pUserData); // Returns the number of frames that were read.
|
typedef mal_uint32 (* mal_src_read_proc)(mal_src* pSRC, mal_uint32 frameCount, void* pFramesOut, void* pUserData); // Returns the number of frames that were read.
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -530,7 +586,7 @@ struct mal_src
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct mal_dsp mal_dsp;
|
typedef struct mal_dsp mal_dsp;
|
||||||
typedef mal_uint32 (* mal_dsp_read_proc)(mal_uint32 frameCount, void* pSamplesOut, void* pUserData);
|
typedef mal_uint32 (* mal_dsp_read_proc)(mal_dsp* pDSP, mal_uint32 frameCount, void* pSamplesOut, void* pUserData);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -1032,7 +1088,6 @@ mal_result mal_context_uninit(mal_context* pContext);
|
|||||||
// application ensures mutal exclusion to the output buffer at their level.
|
// application ensures mutal exclusion to the output buffer at their level.
|
||||||
//
|
//
|
||||||
// Efficiency: LOW
|
// Efficiency: LOW
|
||||||
// This API dynamically links to backend DLLs/SOs (such as dsound.dll).
|
|
||||||
mal_result mal_enumerate_devices(mal_context* pContext, mal_device_type type, mal_uint32* pCount, mal_device_info* pInfo);
|
mal_result mal_enumerate_devices(mal_context* pContext, mal_device_type type, mal_uint32* pCount, mal_device_info* pInfo);
|
||||||
|
|
||||||
// Initializes a device.
|
// Initializes a device.
|
||||||
@@ -1332,10 +1387,19 @@ mal_uint32 mal_convert_frames(void* pOut, mal_format formatOut, mal_uint32 chann
|
|||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
mal_bool32 mal_mutex_create(mal_context* pContext, mal_mutex* pMutex);
|
// Creates a mutex.
|
||||||
void mal_mutex_delete(mal_context* pContext, mal_mutex* pMutex);
|
//
|
||||||
void mal_mutex_lock(mal_context* pContext, mal_mutex* pMutex);
|
// A mutex must be created from a valid context. A mutex is initially unlocked.
|
||||||
void mal_mutex_unlock(mal_context* pContext, mal_mutex* pMutex);
|
mal_result mal_mutex_init(mal_context* pContext, mal_mutex* pMutex);
|
||||||
|
|
||||||
|
// Deletes a mutex.
|
||||||
|
void mal_mutex_uninit(mal_mutex* pMutex);
|
||||||
|
|
||||||
|
// Locks a mutex with an infinite timeout.
|
||||||
|
void mal_mutex_lock(mal_mutex* pMutex);
|
||||||
|
|
||||||
|
// Unlocks a mutex.
|
||||||
|
void mal_mutex_unlock(mal_mutex* pMutex);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1913,23 +1977,21 @@ mal_proc mal_dlsym(mal_handle handle, const char* symbol)
|
|||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
mal_bool32 mal_thread_create__win32(mal_context* pContext, mal_thread* pThread, mal_thread_entry_proc entryProc, void* pData)
|
mal_result mal_thread_create__win32(mal_context* pContext, mal_thread* pThread, mal_thread_entry_proc entryProc, void* pData)
|
||||||
{
|
{
|
||||||
(void)pContext;
|
(void)pContext;
|
||||||
|
|
||||||
*pThread = CreateThread(NULL, 0, entryProc, pData, 0, NULL);
|
pThread->win32.hThread = CreateThread(NULL, 0, entryProc, pData, 0, NULL);
|
||||||
if (*pThread == NULL) {
|
if (pThread->win32.hThread == NULL) {
|
||||||
return MAL_FALSE;
|
return MAL_FAILED_TO_CREATE_THREAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MAL_TRUE;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_thread_wait__win32(mal_context* pContext, mal_thread* pThread)
|
void mal_thread_wait__win32(mal_thread* pThread)
|
||||||
{
|
{
|
||||||
(void)pContext;
|
WaitForSingleObject(pThread->win32.hThread, INFINITE);
|
||||||
|
|
||||||
WaitForSingleObject(*pThread, INFINITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_sleep__win32(mal_uint32 milliseconds)
|
void mal_sleep__win32(mal_uint32 milliseconds)
|
||||||
@@ -1938,71 +2000,59 @@ void mal_sleep__win32(mal_uint32 milliseconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mal_bool32 mal_mutex_create__win32(mal_context* pContext, mal_mutex* pMutex)
|
mal_result mal_mutex_init__win32(mal_context* pContext, mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
(void)pContext;
|
(void)pContext;
|
||||||
|
|
||||||
*pMutex = CreateEventA(NULL, FALSE, TRUE, NULL);
|
pMutex->win32.hMutex = CreateEventA(NULL, FALSE, TRUE, NULL);
|
||||||
if (*pMutex == NULL) {
|
if (pMutex->win32.hMutex == NULL) {
|
||||||
return MAL_FALSE;
|
return MAL_FAILED_TO_CREATE_MUTEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MAL_TRUE;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_delete__win32(mal_context* pContext, mal_mutex* pMutex)
|
void mal_mutex_uninit__win32(mal_mutex* pMutex)
|
||||||
|
{
|
||||||
|
CloseHandle(pMutex->win32.hMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mal_mutex_lock__win32(mal_mutex* pMutex)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(pMutex->win32.hMutex, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mal_mutex_unlock__win32(mal_mutex* pMutex)
|
||||||
|
{
|
||||||
|
SetEvent(pMutex->win32.hMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mal_result mal_event_init__win32(mal_context* pContext, mal_event* pEvent)
|
||||||
{
|
{
|
||||||
(void)pContext;
|
(void)pContext;
|
||||||
|
|
||||||
CloseHandle(*pMutex);
|
pEvent->win32.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
if (pEvent->win32.hEvent == NULL) {
|
||||||
|
return MAL_FAILED_TO_CREATE_EVENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_lock__win32(mal_context* pContext, mal_mutex* pMutex)
|
return MAL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mal_event_uninit__win32(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
(void)pContext;
|
CloseHandle(pEvent->win32.hEvent);
|
||||||
|
|
||||||
WaitForSingleObject(*pMutex, INFINITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_unlock__win32(mal_context* pContext, mal_mutex* pMutex)
|
mal_bool32 mal_event_wait__win32(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
(void)pContext;
|
return WaitForSingleObject(pEvent->win32.hEvent, INFINITE) == WAIT_OBJECT_0;
|
||||||
|
|
||||||
SetEvent(*pMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mal_bool32 mal_event_signal__win32(mal_event* pEvent)
|
||||||
mal_bool32 mal_event_create__win32(mal_context* pContext, mal_event* pEvent)
|
|
||||||
{
|
{
|
||||||
(void)pContext;
|
return SetEvent(pEvent->win32.hEvent);
|
||||||
|
|
||||||
*pEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
||||||
if (*pEvent == NULL) {
|
|
||||||
return MAL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MAL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mal_event_delete__win32(mal_context* pContext, mal_event* pEvent)
|
|
||||||
{
|
|
||||||
(void)pContext;
|
|
||||||
|
|
||||||
CloseHandle(*pEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
mal_bool32 mal_event_wait__win32(mal_context* pContext, mal_event* pEvent)
|
|
||||||
{
|
|
||||||
(void)pContext;
|
|
||||||
|
|
||||||
return WaitForSingleObject(*pEvent, INFINITE) == WAIT_OBJECT_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mal_bool32 mal_event_signal__win32(mal_context* pContext, mal_event* pEvent)
|
|
||||||
{
|
|
||||||
(void)pContext;
|
|
||||||
|
|
||||||
return SetEvent(*pEvent);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2021,12 +2071,17 @@ typedef int (* mal_pthread_cond_wait_proc)(pthread_cond_t *__restrict __cond, pt
|
|||||||
|
|
||||||
mal_bool32 mal_thread_create__posix(mal_context* pContext, mal_thread* pThread, mal_thread_entry_proc entryProc, void* pData)
|
mal_bool32 mal_thread_create__posix(mal_context* pContext, mal_thread* pThread, mal_thread_entry_proc entryProc, void* pData)
|
||||||
{
|
{
|
||||||
return ((mal_pthread_create_proc)pContext->posix.pthread_create)(pThread, NULL, entryProc, pData) == 0;
|
int result = ((mal_pthread_create_proc)pContext->posix.pthread_create)(&pThread->posix.thread, NULL, entryProc, pData);
|
||||||
|
if (result != 0) {
|
||||||
|
return MAL_FAILED_TO_CREATE_THREAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_thread_wait__posix(mal_context* pContext, mal_thread* pThread)
|
return MAL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mal_thread_wait__posix(mal_thread* pThread)
|
||||||
{
|
{
|
||||||
((mal_pthread_join_proc)pContext->posix.pthread_join)(*pThread, NULL);
|
((mal_pthread_join_proc)pThread->pContext->posix.pthread_join)(pThread->posix.thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_sleep__posix(mal_uint32 milliseconds)
|
void mal_sleep__posix(mal_uint32 milliseconds)
|
||||||
@@ -2035,78 +2090,85 @@ void mal_sleep__posix(mal_uint32 milliseconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mal_bool32 mal_mutex_create__posix(mal_context* pContext, mal_mutex* pMutex)
|
mal_result mal_mutex_init__posix(mal_context* pContext, mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
return ((mal_pthread_mutex_init_proc)pContext->posix.pthread_mutex_init)(pMutex, NULL) == 0;
|
int result = ((mal_pthread_mutex_init_proc)pContext->posix.pthread_mutex_init)(&pMutex->posix.mutex, NULL);
|
||||||
|
if (result != 0) {
|
||||||
|
return MAL_FAILED_TO_CREATE_MUTEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_delete__posix(mal_context* pContext, mal_mutex* pMutex)
|
return MAL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mal_mutex_uninit__posix(mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
((mal_pthread_mutex_destroy_proc)pContext->posix.pthread_mutex_destroy)(pMutex);
|
((mal_pthread_mutex_destroy_proc)pMutex->pContext->posix.pthread_mutex_destroy)(&pMutex->posix.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_lock__posix(mal_context* pContext, mal_mutex* pMutex)
|
void mal_mutex_lock__posix(mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
((mal_pthread_mutex_lock_proc)pContext->posix.pthread_mutex_lock)(pMutex);
|
((mal_pthread_mutex_lock_proc)pMutex->pContext->posix.pthread_mutex_lock)(&pMutex->posix.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_unlock__posix(mal_context* pContext, mal_mutex* pMutex)
|
void mal_mutex_unlock__posix(mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
((mal_pthread_mutex_unlock_proc)pContext->posix.pthread_mutex_unlock)(pMutex);
|
((mal_pthread_mutex_unlock_proc)pMutex->pContext->posix.pthread_mutex_unlock)(&pMutex->posix.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mal_bool32 mal_event_create__posix(mal_context* pContext, mal_event* pEvent)
|
mal_result mal_event_init__posix(mal_context* pContext, mal_event* pEvent)
|
||||||
{
|
{
|
||||||
if (((mal_pthread_mutex_init_proc)pContext->posix.pthread_mutex_init)(&pEvent->mutex, NULL) != 0) {
|
if (((mal_pthread_mutex_init_proc)pContext->posix.pthread_mutex_init)(&pEvent->posix.mutex, NULL) != 0) {
|
||||||
return MAL_FALSE;
|
return MAL_FAILED_TO_CREATE_MUTEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((mal_pthread_cond_init_proc)pContext->posix.pthread_cond_init)(&pEvent->condition, NULL) != 0) {
|
if (((mal_pthread_cond_init_proc)pContext->posix.pthread_cond_init)(&pEvent->posix.condition, NULL) != 0) {
|
||||||
return MAL_FALSE;
|
return MAL_FAILED_TO_CREATE_EVENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pEvent->value = 0;
|
pEvent->posix.value = 0;
|
||||||
return MAL_TRUE;
|
return MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_event_delete__posix(mal_context* pContext, mal_event* pEvent)
|
void mal_event_uninit__posix(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
((mal_pthread_cond_destroy_proc)pContext->posix.pthread_cond_destroy)(&pEvent->condition);
|
((mal_pthread_cond_destroy_proc)pEvent->pContext->posix.pthread_cond_destroy)(&pEvent->posix.condition);
|
||||||
((mal_pthread_mutex_destroy_proc)pContext->posix.pthread_mutex_destroy)(&pEvent->mutex);
|
((mal_pthread_mutex_destroy_proc)pEvent->pContext->posix.pthread_mutex_destroy)(&pEvent->posix.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_bool32 mal_event_wait__posix(mal_context* pContext, mal_event* pEvent)
|
mal_bool32 mal_event_wait__posix(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
((mal_pthread_mutex_lock_proc)pContext->posix.pthread_mutex_lock)(&pEvent->mutex);
|
((mal_pthread_mutex_lock_proc)pEvent->pContext->posix.pthread_mutex_lock)(&pEvent->posix.mutex);
|
||||||
{
|
{
|
||||||
while (pEvent->value == 0) {
|
while (pEvent->posix.value == 0) {
|
||||||
((mal_pthread_cond_wait_proc)pContext->posix.pthread_cond_wait)(&pEvent->condition, &pEvent->mutex);
|
((mal_pthread_cond_wait_proc)pEvent->pContext->posix.pthread_cond_wait)(&pEvent->posix.condition, &pEvent->posix.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
pEvent->value = 0; // Auto-reset.
|
pEvent->posix.value = 0; // Auto-reset.
|
||||||
}
|
}
|
||||||
((mal_pthread_mutex_unlock_proc)pContext->posix.pthread_mutex_unlock)(&pEvent->mutex);
|
((mal_pthread_mutex_unlock_proc)pEvent->pContext->posix.pthread_mutex_unlock)(&pEvent->posix.mutex);
|
||||||
|
|
||||||
return MAL_TRUE;
|
return MAL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_bool32 mal_event_signal__posix(mal_context* pContext, mal_event* pEvent)
|
mal_bool32 mal_event_signal__posix(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
((mal_pthread_mutex_lock_proc)pContext->posix.pthread_mutex_lock)(&pEvent->mutex);
|
((mal_pthread_mutex_lock_proc)pEvent->pContext->posix.pthread_mutex_lock)(&pEvent->posix.mutex);
|
||||||
{
|
{
|
||||||
pEvent->value = 1;
|
pEvent->posix.value = 1;
|
||||||
((mal_pthread_cond_signal_proc)pContext->posix.pthread_cond_signal)(&pEvent->condition);
|
((mal_pthread_cond_signal_proc)pEvent->pContext->posix.pthread_cond_signal)(&pEvent->posix.condition);
|
||||||
}
|
}
|
||||||
((mal_pthread_mutex_unlock_proc)pContext->posix.pthread_mutex_unlock)(&pEvent->mutex);
|
((mal_pthread_mutex_unlock_proc)pEvent->pContext->posix.pthread_mutex_unlock)(&pEvent->posix.mutex);
|
||||||
|
|
||||||
return MAL_TRUE;
|
return MAL_TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mal_bool32 mal_thread_create(mal_context* pContext, mal_thread* pThread, mal_thread_entry_proc entryProc, void* pData)
|
mal_result mal_thread_create(mal_context* pContext, mal_thread* pThread, mal_thread_entry_proc entryProc, void* pData)
|
||||||
{
|
{
|
||||||
if (pThread == NULL || entryProc == NULL) return MAL_FALSE;
|
if (pContext == NULL || pThread == NULL || entryProc == NULL) return MAL_FALSE;
|
||||||
|
|
||||||
|
pThread->pContext = pContext;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
return mal_thread_create__win32(pContext, pThread, entryProc, pData);
|
return mal_thread_create__win32(pContext, pThread, entryProc, pData);
|
||||||
@@ -2116,15 +2178,15 @@ mal_bool32 mal_thread_create(mal_context* pContext, mal_thread* pThread, mal_thr
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_thread_wait(mal_context* pContext, mal_thread* pThread)
|
void mal_thread_wait(mal_thread* pThread)
|
||||||
{
|
{
|
||||||
if (pThread == NULL) return;
|
if (pThread == NULL) return;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
mal_thread_wait__win32(pContext, pThread);
|
mal_thread_wait__win32(pThread);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
mal_thread_wait__posix(pContext, pThread);
|
mal_thread_wait__posix(pThread);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2139,100 +2201,104 @@ void mal_sleep(mal_uint32 milliseconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mal_bool32 mal_mutex_create(mal_context* pContext, mal_mutex* pMutex)
|
mal_result mal_mutex_init(mal_context* pContext, mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
if (pMutex == NULL) return MAL_FALSE;
|
if (pContext == NULL || pMutex == NULL) return MAL_INVALID_ARGS;
|
||||||
|
|
||||||
|
pMutex->pContext = pContext;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
return mal_mutex_create__win32(pContext, pMutex);
|
return mal_mutex_init__win32(pContext, pMutex);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
return mal_mutex_create__posix(pContext, pMutex);
|
return mal_mutex_init__posix(pContext, pMutex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_delete(mal_context* pContext, mal_mutex* pMutex)
|
void mal_mutex_uninit(mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
if (pMutex == NULL) return;
|
if (pMutex == NULL || pMutex->pContext == NULL) return;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
mal_mutex_delete__win32(pContext, pMutex);
|
mal_mutex_uninit__win32(pMutex);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
mal_mutex_delete__posix(pContext, pMutex);
|
mal_mutex_uninit__posix(pMutex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_lock(mal_context* pContext, mal_mutex* pMutex)
|
void mal_mutex_lock(mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
if (pMutex == NULL) return;
|
if (pMutex == NULL || pMutex->pContext == NULL) return;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
mal_mutex_lock__win32(pContext, pMutex);
|
mal_mutex_lock__win32(pMutex);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
mal_mutex_lock__posix(pContext, pMutex);
|
mal_mutex_lock__posix(pMutex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_mutex_unlock(mal_context* pContext, mal_mutex* pMutex)
|
void mal_mutex_unlock(mal_mutex* pMutex)
|
||||||
{
|
{
|
||||||
if (pMutex == NULL) return;
|
if (pMutex == NULL || pMutex->pContext == NULL) return;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
mal_mutex_unlock__win32(pContext, pMutex);
|
mal_mutex_unlock__win32(pMutex);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
mal_mutex_unlock__posix(pContext, pMutex);
|
mal_mutex_unlock__posix(pMutex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mal_bool32 mal_event_create(mal_context* pContext, mal_event* pEvent)
|
mal_result mal_event_init(mal_context* pContext, mal_event* pEvent)
|
||||||
{
|
{
|
||||||
if (pEvent == NULL) return MAL_FALSE;
|
if (pContext == NULL || pEvent == NULL) return MAL_FALSE;
|
||||||
|
|
||||||
|
pEvent->pContext = pContext;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
return mal_event_create__win32(pContext, pEvent);
|
return mal_event_init__win32(pContext, pEvent);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
return mal_event_create__posix(pContext, pEvent);
|
return mal_event_init__posix(pContext, pEvent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mal_event_delete(mal_context* pContext, mal_event* pEvent)
|
void mal_event_uninit(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
if (pEvent == NULL) return;
|
if (pEvent == NULL || pEvent->pContext == NULL) return;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
mal_event_delete__win32(pContext, pEvent);
|
mal_event_uninit__win32(pEvent);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
mal_event_delete__posix(pContext, pEvent);
|
mal_event_uninit__posix(pEvent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_bool32 mal_event_wait(mal_context* pContext, mal_event* pEvent)
|
mal_bool32 mal_event_wait(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
if (pEvent == NULL) return MAL_FALSE;
|
if (pEvent == NULL || pEvent->pContext == NULL) return MAL_FALSE;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
return mal_event_wait__win32(pContext, pEvent);
|
return mal_event_wait__win32(pEvent);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
return mal_event_wait__posix(pContext, pEvent);
|
return mal_event_wait__posix(pEvent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_bool32 mal_event_signal(mal_context* pContext, mal_event* pEvent)
|
mal_bool32 mal_event_signal(mal_event* pEvent)
|
||||||
{
|
{
|
||||||
if (pEvent == NULL) return MAL_FALSE;
|
if (pEvent == NULL || pEvent->pContext == NULL) return MAL_FALSE;
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
return mal_event_signal__win32(pContext, pEvent);
|
return mal_event_signal__win32(pEvent);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_POSIX
|
#ifdef MAL_POSIX
|
||||||
return mal_event_signal__posix(pContext, pEvent);
|
return mal_event_signal__posix(pEvent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2340,8 +2406,10 @@ static void mal_get_default_channel_mapping(mal_backend backend, mal_uint32 chan
|
|||||||
|
|
||||||
|
|
||||||
// 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_uint32 frameCount, void* pFramesOut, void* pUserData)
|
static inline mal_uint32 mal_device__on_read_from_client(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
||||||
{
|
{
|
||||||
|
(void)pDSP;
|
||||||
|
|
||||||
mal_device* pDevice = (mal_device*)pUserData;
|
mal_device* pDevice = (mal_device*)pUserData;
|
||||||
mal_assert(pDevice != NULL);
|
mal_assert(pDevice != NULL);
|
||||||
|
|
||||||
@@ -2354,8 +2422,10 @@ static inline mal_uint32 mal_device__on_read_from_client(mal_uint32 frameCount,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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_uint32 frameCount, void* pFramesOut, void* pUserData)
|
static inline mal_uint32 mal_device__on_read_from_device(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
||||||
{
|
{
|
||||||
|
(void)pDSP;
|
||||||
|
|
||||||
mal_device* pDevice = (mal_device*)pUserData;
|
mal_device* pDevice = (mal_device*)pUserData;
|
||||||
mal_assert(pDevice != NULL);
|
mal_assert(pDevice != NULL);
|
||||||
|
|
||||||
@@ -2705,7 +2775,7 @@ static mal_result mal_device__main_loop__null(mal_device* pDevice)
|
|||||||
|
|
||||||
// The SDK that comes with old versions of MSVC (VC6, for example) does not appear to define WAVEFORMATEXTENSIBLE. We
|
// The SDK that comes with old versions of MSVC (VC6, for example) does not appear to define WAVEFORMATEXTENSIBLE. We
|
||||||
// define our own implementation in this case.
|
// define our own implementation in this case.
|
||||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
#if defined(_MSC_VER) && !defined(_WAVEFORMATEXTENSIBLE_)
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
WAVEFORMATEX Format;
|
WAVEFORMATEX Format;
|
||||||
@@ -7452,7 +7522,7 @@ mal_result mal_context_init__openal(mal_context* pContext)
|
|||||||
libName = "libopenal.so";
|
libName = "libopenal.so";
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAL_APPLE
|
#ifdef MAL_APPLE
|
||||||
// I don't own a Mac so a contribution here would be much appreciated! Just don't know what the library is called...
|
libName = "OpenAL.framework/OpenAL";
|
||||||
#endif
|
#endif
|
||||||
if (libName == NULL) {
|
if (libName == NULL) {
|
||||||
return MAL_NO_BACKEND; // Don't know what the library name is called.
|
return MAL_NO_BACKEND; // Don't know what the library name is called.
|
||||||
@@ -8230,10 +8300,10 @@ mal_thread_result MAL_THREADCALL mal_worker_thread(void* pData)
|
|||||||
|
|
||||||
// Let the other threads know that the device has stopped.
|
// Let the other threads know that the device has stopped.
|
||||||
mal_device__set_state(pDevice, MAL_STATE_STOPPED);
|
mal_device__set_state(pDevice, MAL_STATE_STOPPED);
|
||||||
mal_event_signal(pDevice->pContext, &pDevice->stopEvent);
|
mal_event_signal(&pDevice->stopEvent);
|
||||||
|
|
||||||
// We use an event to wait for a request to wake up.
|
// We use an event to wait for a request to wake up.
|
||||||
mal_event_wait(pDevice->pContext, &pDevice->wakeupEvent);
|
mal_event_wait(&pDevice->wakeupEvent);
|
||||||
|
|
||||||
// Default result code.
|
// Default result code.
|
||||||
pDevice->workResult = MAL_SUCCESS;
|
pDevice->workResult = MAL_SUCCESS;
|
||||||
@@ -8250,21 +8320,21 @@ mal_thread_result MAL_THREADCALL mal_worker_thread(void* pData)
|
|||||||
|
|
||||||
pDevice->workResult = mal_device__start_backend(pDevice);
|
pDevice->workResult = mal_device__start_backend(pDevice);
|
||||||
if (pDevice->workResult != MAL_SUCCESS) {
|
if (pDevice->workResult != MAL_SUCCESS) {
|
||||||
mal_event_signal(pDevice->pContext, &pDevice->startEvent);
|
mal_event_signal(&pDevice->startEvent);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The thread that requested the device to start playing is waiting for this thread to start the
|
// The thread that requested the device to start playing is waiting for this thread to start the
|
||||||
// device for real, which is now.
|
// device for real, which is now.
|
||||||
mal_device__set_state(pDevice, MAL_STATE_STARTED);
|
mal_device__set_state(pDevice, MAL_STATE_STARTED);
|
||||||
mal_event_signal(pDevice->pContext, &pDevice->startEvent);
|
mal_event_signal(&pDevice->startEvent);
|
||||||
|
|
||||||
// Now we just enter the main loop. The main loop can be broken with mal_device__break_main_loop().
|
// Now we just enter the main loop. The main loop can be broken with mal_device__break_main_loop().
|
||||||
mal_device__main_loop(pDevice);
|
mal_device__main_loop(pDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we aren't continuously waiting on a stop event.
|
// Make sure we aren't continuously waiting on a stop event.
|
||||||
mal_event_signal(pDevice->pContext, &pDevice->stopEvent); // <-- Is this still needed?
|
mal_event_signal(&pDevice->stopEvent); // <-- Is this still needed?
|
||||||
|
|
||||||
#ifdef MAL_WIN32
|
#ifdef MAL_WIN32
|
||||||
mal_CoUninitialize(pDevice->pContext);
|
mal_CoUninitialize(pDevice->pContext);
|
||||||
@@ -8334,7 +8404,8 @@ mal_result mal_context_init_backend_apis__nix(mal_context* pContext)
|
|||||||
// pthread
|
// pthread
|
||||||
const char* libpthreadFileNames[] = {
|
const char* libpthreadFileNames[] = {
|
||||||
"libpthread.so",
|
"libpthread.so",
|
||||||
"libpthread.so.0"
|
"libpthread.so.0",
|
||||||
|
"libpthread.dylib"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(libpthreadFileNames) / sizeof(libpthreadFileNames[0]); ++i) {
|
for (size_t i = 0; i < sizeof(libpthreadFileNames) / sizeof(libpthreadFileNames[0]); ++i) {
|
||||||
@@ -8691,7 +8762,7 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
|
|||||||
pDevice->internalSampleRate = pDevice->sampleRate;
|
pDevice->internalSampleRate = pDevice->sampleRate;
|
||||||
mal_copy_memory(pDevice->internalChannelMap, pDevice->channelMap, sizeof(pDevice->channelMap));
|
mal_copy_memory(pDevice->internalChannelMap, pDevice->channelMap, sizeof(pDevice->channelMap));
|
||||||
|
|
||||||
if (!mal_mutex_create(pContext, &pDevice->lock)) {
|
if (mal_mutex_init(pContext, &pDevice->lock) != MAL_SUCCESS) {
|
||||||
return mal_post_error(pDevice, "Failed to create mutex.", MAL_FAILED_TO_CREATE_MUTEX);
|
return mal_post_error(pDevice, "Failed to create mutex.", MAL_FAILED_TO_CREATE_MUTEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8700,19 +8771,19 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
|
|||||||
//
|
//
|
||||||
// Each of these semaphores is released internally by the worker thread when the work is completed. The start
|
// Each of these semaphores is released internally by the worker thread when the work is completed. The start
|
||||||
// semaphore is also used to wake up the worker thread.
|
// semaphore is also used to wake up the worker thread.
|
||||||
if (!mal_event_create(pContext, &pDevice->wakeupEvent)) {
|
if (mal_event_init(pContext, &pDevice->wakeupEvent) != MAL_SUCCESS) {
|
||||||
mal_mutex_delete(pContext, &pDevice->lock);
|
mal_mutex_uninit(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "Failed to create worker thread wakeup event.", MAL_FAILED_TO_CREATE_EVENT);
|
return mal_post_error(pDevice, "Failed to create worker thread wakeup event.", MAL_FAILED_TO_CREATE_EVENT);
|
||||||
}
|
}
|
||||||
if (!mal_event_create(pContext, &pDevice->startEvent)) {
|
if (mal_event_init(pContext, &pDevice->startEvent) != MAL_SUCCESS) {
|
||||||
mal_event_delete(pContext, &pDevice->wakeupEvent);
|
mal_event_uninit(&pDevice->wakeupEvent);
|
||||||
mal_mutex_delete(pContext, &pDevice->lock);
|
mal_mutex_uninit(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "Failed to create worker thread start event.", MAL_FAILED_TO_CREATE_EVENT);
|
return mal_post_error(pDevice, "Failed to create worker thread start event.", MAL_FAILED_TO_CREATE_EVENT);
|
||||||
}
|
}
|
||||||
if (!mal_event_create(pContext, &pDevice->stopEvent)) {
|
if (mal_event_init(pContext, &pDevice->stopEvent) != MAL_SUCCESS) {
|
||||||
mal_event_delete(pContext, &pDevice->startEvent);
|
mal_event_uninit(&pDevice->startEvent);
|
||||||
mal_event_delete(pContext, &pDevice->wakeupEvent);
|
mal_event_uninit(&pDevice->wakeupEvent);
|
||||||
mal_mutex_delete(pContext, &pDevice->lock);
|
mal_mutex_uninit(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "Failed to create worker thread stop event.", MAL_FAILED_TO_CREATE_EVENT);
|
return mal_post_error(pDevice, "Failed to create worker thread stop event.", MAL_FAILED_TO_CREATE_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8809,13 +8880,13 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
|
|||||||
// Some backends don't require the worker thread.
|
// Some backends don't require the worker thread.
|
||||||
if (pContext->backend != mal_backend_opensl) {
|
if (pContext->backend != mal_backend_opensl) {
|
||||||
// The worker thread.
|
// The worker thread.
|
||||||
if (!mal_thread_create(pContext, &pDevice->thread, mal_worker_thread, pDevice)) {
|
if (mal_thread_create(pContext, &pDevice->thread, mal_worker_thread, pDevice) != MAL_SUCCESS) {
|
||||||
mal_device_uninit(pDevice);
|
mal_device_uninit(pDevice);
|
||||||
return mal_post_error(pDevice, "Failed to create worker thread.", MAL_FAILED_TO_CREATE_THREAD);
|
return mal_post_error(pDevice, "Failed to create worker thread.", MAL_FAILED_TO_CREATE_THREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the worker thread to put the device into it's stopped state for real.
|
// Wait for the worker thread to put the device into it's stopped state for real.
|
||||||
mal_event_wait(pContext, &pDevice->stopEvent);
|
mal_event_wait(&pDevice->stopEvent);
|
||||||
} else {
|
} else {
|
||||||
mal_device__set_state(pDevice, MAL_STATE_STOPPED);
|
mal_device__set_state(pDevice, MAL_STATE_STOPPED);
|
||||||
}
|
}
|
||||||
@@ -8841,14 +8912,14 @@ void mal_device_uninit(mal_device* pDevice)
|
|||||||
|
|
||||||
// Wake up the worker thread and wait for it to properly terminate.
|
// Wake up the worker thread and wait for it to properly terminate.
|
||||||
if (pDevice->pContext->backend != mal_backend_opensl) {
|
if (pDevice->pContext->backend != mal_backend_opensl) {
|
||||||
mal_event_signal(pDevice->pContext, &pDevice->wakeupEvent);
|
mal_event_signal(&pDevice->wakeupEvent);
|
||||||
mal_thread_wait(pDevice->pContext, &pDevice->thread);
|
mal_thread_wait(&pDevice->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_event_delete(pDevice->pContext, &pDevice->stopEvent);
|
mal_event_uninit(&pDevice->stopEvent);
|
||||||
mal_event_delete(pDevice->pContext, &pDevice->startEvent);
|
mal_event_uninit(&pDevice->startEvent);
|
||||||
mal_event_delete(pDevice->pContext, &pDevice->wakeupEvent);
|
mal_event_uninit(&pDevice->wakeupEvent);
|
||||||
mal_mutex_delete(pDevice->pContext, &pDevice->lock);
|
mal_mutex_uninit(&pDevice->lock);
|
||||||
|
|
||||||
#ifdef MAL_ENABLE_WASAPI
|
#ifdef MAL_ENABLE_WASAPI
|
||||||
if (pDevice->pContext->backend == mal_backend_wasapi) {
|
if (pDevice->pContext->backend == mal_backend_wasapi) {
|
||||||
@@ -8918,22 +8989,22 @@ mal_result mal_device_start(mal_device* pDevice)
|
|||||||
if (mal_device__get_state(pDevice) == MAL_STATE_UNINITIALIZED) return mal_post_error(pDevice, "mal_device_start() called for an uninitialized device.", MAL_DEVICE_NOT_INITIALIZED);
|
if (mal_device__get_state(pDevice) == MAL_STATE_UNINITIALIZED) return mal_post_error(pDevice, "mal_device_start() called for an uninitialized device.", MAL_DEVICE_NOT_INITIALIZED);
|
||||||
|
|
||||||
mal_result result = MAL_ERROR;
|
mal_result result = MAL_ERROR;
|
||||||
mal_mutex_lock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_lock(&pDevice->lock);
|
||||||
{
|
{
|
||||||
// Be a bit more descriptive if the device is already started or is already in the process of starting. This is likely
|
// Be a bit more descriptive if the device is already started or is already in the process of starting. This is likely
|
||||||
// a bug with the application.
|
// a bug with the application.
|
||||||
if (mal_device__get_state(pDevice) == MAL_STATE_STARTING) {
|
if (mal_device__get_state(pDevice) == MAL_STATE_STARTING) {
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "mal_device_start() called while another thread is already starting it.", MAL_DEVICE_ALREADY_STARTING);
|
return mal_post_error(pDevice, "mal_device_start() called while another thread is already starting it.", MAL_DEVICE_ALREADY_STARTING);
|
||||||
}
|
}
|
||||||
if (mal_device__get_state(pDevice) == MAL_STATE_STARTED) {
|
if (mal_device__get_state(pDevice) == MAL_STATE_STARTED) {
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "mal_device_start() called for a device that's already started.", MAL_DEVICE_ALREADY_STARTED);
|
return mal_post_error(pDevice, "mal_device_start() called for a device that's already started.", MAL_DEVICE_ALREADY_STARTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The device needs to be in a stopped state. If it's not, we just let the caller know the device is busy.
|
// The device needs to be in a stopped state. If it's not, we just let the caller know the device is busy.
|
||||||
if (mal_device__get_state(pDevice) != MAL_STATE_STOPPED) {
|
if (mal_device__get_state(pDevice) != MAL_STATE_STOPPED) {
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "mal_device_start() called while another thread is in the process of stopping it.", MAL_DEVICE_BUSY);
|
return mal_post_error(pDevice, "mal_device_start() called while another thread is in the process of stopping it.", MAL_DEVICE_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8948,15 +9019,15 @@ mal_result mal_device_start(mal_device* pDevice)
|
|||||||
#endif
|
#endif
|
||||||
// Synchronous backends.
|
// Synchronous backends.
|
||||||
{
|
{
|
||||||
mal_event_signal(pDevice->pContext, &pDevice->wakeupEvent);
|
mal_event_signal(&pDevice->wakeupEvent);
|
||||||
|
|
||||||
// Wait for the worker thread to finish starting the device. Note that the worker thread will be the one
|
// Wait for the worker thread to finish starting the device. Note that the worker thread will be the one
|
||||||
// who puts the device into the started state. Don't call mal_device__set_state() here.
|
// who puts the device into the started state. Don't call mal_device__set_state() here.
|
||||||
mal_event_wait(pDevice->pContext, &pDevice->startEvent);
|
mal_event_wait(&pDevice->startEvent);
|
||||||
result = pDevice->workResult;
|
result = pDevice->workResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -8967,22 +9038,22 @@ mal_result mal_device_stop(mal_device* pDevice)
|
|||||||
if (mal_device__get_state(pDevice) == MAL_STATE_UNINITIALIZED) return mal_post_error(pDevice, "mal_device_stop() called for an uninitialized device.", MAL_DEVICE_NOT_INITIALIZED);
|
if (mal_device__get_state(pDevice) == MAL_STATE_UNINITIALIZED) return mal_post_error(pDevice, "mal_device_stop() called for an uninitialized device.", MAL_DEVICE_NOT_INITIALIZED);
|
||||||
|
|
||||||
mal_result result = MAL_ERROR;
|
mal_result result = MAL_ERROR;
|
||||||
mal_mutex_lock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_lock(&pDevice->lock);
|
||||||
{
|
{
|
||||||
// Be a bit more descriptive if the device is already stopped or is already in the process of stopping. This is likely
|
// Be a bit more descriptive if the device is already stopped or is already in the process of stopping. This is likely
|
||||||
// a bug with the application.
|
// a bug with the application.
|
||||||
if (mal_device__get_state(pDevice) == MAL_STATE_STOPPING) {
|
if (mal_device__get_state(pDevice) == MAL_STATE_STOPPING) {
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "mal_device_stop() called while another thread is already stopping it.", MAL_DEVICE_ALREADY_STOPPING);
|
return mal_post_error(pDevice, "mal_device_stop() called while another thread is already stopping it.", MAL_DEVICE_ALREADY_STOPPING);
|
||||||
}
|
}
|
||||||
if (mal_device__get_state(pDevice) == MAL_STATE_STOPPED) {
|
if (mal_device__get_state(pDevice) == MAL_STATE_STOPPED) {
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "mal_device_stop() called for a device that's already stopped.", MAL_DEVICE_ALREADY_STOPPED);
|
return mal_post_error(pDevice, "mal_device_stop() called for a device that's already stopped.", MAL_DEVICE_ALREADY_STOPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The device needs to be in a started state. If it's not, we just let the caller know the device is busy.
|
// The device needs to be in a started state. If it's not, we just let the caller know the device is busy.
|
||||||
if (mal_device__get_state(pDevice) != MAL_STATE_STARTED) {
|
if (mal_device__get_state(pDevice) != MAL_STATE_STARTED) {
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
return mal_post_error(pDevice, "mal_device_stop() called while another thread is in the process of starting it.", MAL_DEVICE_BUSY);
|
return mal_post_error(pDevice, "mal_device_stop() called while another thread is in the process of starting it.", MAL_DEVICE_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9004,11 +9075,11 @@ mal_result mal_device_stop(mal_device* pDevice)
|
|||||||
|
|
||||||
// We need to wait for the worker thread to become available for work before returning. Note that the worker thread will be
|
// We need to wait for the worker thread to become available for work before returning. Note that the worker thread will be
|
||||||
// the one who puts the device into the stopped state. Don't call mal_device__set_state() here.
|
// the one who puts the device into the stopped state. Don't call mal_device__set_state() here.
|
||||||
mal_event_wait(pDevice->pContext, &pDevice->stopEvent);
|
mal_event_wait(&pDevice->stopEvent);
|
||||||
result = MAL_SUCCESS;
|
result = MAL_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mal_mutex_unlock(pDevice->pContext, &pDevice->lock);
|
mal_mutex_unlock(&pDevice->lock);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -9186,7 +9257,7 @@ mal_uint32 mal_src_cache_read_frames(mal_src_cache* pCache, mal_uint32 frameCoun
|
|||||||
framesToReadFromClient = pCache->pSRC->config.cacheSizeInFrames;
|
framesToReadFromClient = pCache->pSRC->config.cacheSizeInFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
pCache->cachedFrameCount = pCache->pSRC->onRead(framesToReadFromClient, pCache->pCachedFrames, pCache->pSRC->pUserData);
|
pCache->cachedFrameCount = pCache->pSRC->onRead(pCache->pSRC, framesToReadFromClient, pCache->pCachedFrames, pCache->pSRC->pUserData);
|
||||||
} else {
|
} else {
|
||||||
// A format conversion is required which means we need to use an intermediary buffer.
|
// A format conversion is required which means we need to use an intermediary buffer.
|
||||||
mal_uint8 pIntermediaryBuffer[sizeof(pCache->pCachedFrames)];
|
mal_uint8 pIntermediaryBuffer[sizeof(pCache->pCachedFrames)];
|
||||||
@@ -9195,7 +9266,7 @@ mal_uint32 mal_src_cache_read_frames(mal_src_cache* pCache, mal_uint32 frameCoun
|
|||||||
framesToReadFromClient = pCache->pSRC->config.cacheSizeInFrames;
|
framesToReadFromClient = pCache->pSRC->config.cacheSizeInFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
pCache->cachedFrameCount = pCache->pSRC->onRead(framesToReadFromClient, pIntermediaryBuffer, pCache->pSRC->pUserData);
|
pCache->cachedFrameCount = pCache->pSRC->onRead(pCache->pSRC, framesToReadFromClient, pIntermediaryBuffer, pCache->pSRC->pUserData);
|
||||||
|
|
||||||
// Convert to f32.
|
// Convert to f32.
|
||||||
mal_pcm_convert(pCache->pCachedFrames, mal_format_f32, pIntermediaryBuffer, pCache->pSRC->config.formatIn, pCache->cachedFrameCount * channels);
|
mal_pcm_convert(pCache->pCachedFrames, mal_format_f32, pIntermediaryBuffer, pCache->pSRC->config.formatIn, pCache->cachedFrameCount * channels);
|
||||||
@@ -9263,7 +9334,7 @@ mal_uint32 mal_src_read_frames_passthrough(mal_src* pSRC, mal_uint32 frameCount,
|
|||||||
|
|
||||||
// Fast path. No need for data conversion - just pass right through.
|
// Fast path. No need for data conversion - just pass right through.
|
||||||
if (pSRC->config.formatIn == pSRC->config.formatOut) {
|
if (pSRC->config.formatIn == pSRC->config.formatOut) {
|
||||||
return pSRC->onRead(frameCount, pFramesOut, pSRC->pUserData);
|
return pSRC->onRead(pSRC, frameCount, pFramesOut, pSRC->pUserData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slower path. Need to do a format conversion.
|
// Slower path. Need to do a format conversion.
|
||||||
@@ -9276,7 +9347,7 @@ mal_uint32 mal_src_read_frames_passthrough(mal_src* pSRC, mal_uint32 frameCount,
|
|||||||
framesToRead = frameCount;
|
framesToRead = frameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_uint32 framesRead = pSRC->onRead(framesToRead, pStagingBuffer, pSRC->pUserData);
|
mal_uint32 framesRead = pSRC->onRead(pSRC, framesToRead, pStagingBuffer, pSRC->pUserData);
|
||||||
if (framesRead == 0) {
|
if (framesRead == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -9791,12 +9862,14 @@ static void mal_dsp_mix_channels(float* pFramesOut, mal_uint32 channelsOut, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mal_uint32 mal_dsp__src_on_read(mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
mal_uint32 mal_dsp__src_on_read(mal_src* pSRC, mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
||||||
{
|
{
|
||||||
|
(void)pSRC;
|
||||||
|
|
||||||
mal_dsp* pDSP = (mal_dsp*)pUserData;
|
mal_dsp* pDSP = (mal_dsp*)pUserData;
|
||||||
mal_assert(pDSP != NULL);
|
mal_assert(pDSP != NULL);
|
||||||
|
|
||||||
return pDSP->onRead(frameCount, pFramesOut, pDSP->pUserDataForOnRead);
|
return pDSP->onRead(pDSP, frameCount, pFramesOut, pDSP->pUserDataForOnRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_result mal_dsp_init(mal_dsp_config* pConfig, mal_dsp_read_proc onRead, void* pUserData, mal_dsp* pDSP)
|
mal_result mal_dsp_init(mal_dsp_config* pConfig, mal_dsp_read_proc onRead, void* pUserData, mal_dsp* pDSP)
|
||||||
@@ -9899,7 +9972,7 @@ mal_uint32 mal_dsp_read_frames(mal_dsp* pDSP, mal_uint32 frameCount, void* pFram
|
|||||||
|
|
||||||
// Fast path.
|
// Fast path.
|
||||||
if (pDSP->isPassthrough) {
|
if (pDSP->isPassthrough) {
|
||||||
return pDSP->onRead(frameCount, pFramesOut, pDSP->pUserDataForOnRead);
|
return pDSP->onRead(pDSP, frameCount, pFramesOut, pDSP->pUserDataForOnRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -9923,7 +9996,7 @@ mal_uint32 mal_dsp_read_frames(mal_dsp* pDSP, mal_uint32 frameCount, void* pFram
|
|||||||
framesRead = mal_src_read_frames(&pDSP->src, framesToRead, pFrames[iFrames]);
|
framesRead = mal_src_read_frames(&pDSP->src, framesToRead, pFrames[iFrames]);
|
||||||
pFramesFormat[iFrames] = pDSP->src.config.formatOut; // Should always be f32.
|
pFramesFormat[iFrames] = pDSP->src.config.formatOut; // Should always be f32.
|
||||||
} else {
|
} else {
|
||||||
framesRead = pDSP->onRead(framesToRead, pFrames[iFrames], pDSP->pUserDataForOnRead);
|
framesRead = pDSP->onRead(pDSP, framesToRead, pFrames[iFrames], pDSP->pUserDataForOnRead);
|
||||||
pFramesFormat[iFrames] = pDSP->config.formatIn;
|
pFramesFormat[iFrames] = pDSP->config.formatIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9990,8 +10063,10 @@ typedef struct
|
|||||||
mal_uint32 iNextFrame;
|
mal_uint32 iNextFrame;
|
||||||
} mal_convert_frames__data;
|
} mal_convert_frames__data;
|
||||||
|
|
||||||
mal_uint32 mal_convert_frames__on_read(mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
mal_uint32 mal_convert_frames__on_read(mal_dsp* pDSP, mal_uint32 frameCount, void* pFramesOut, void* pUserData)
|
||||||
{
|
{
|
||||||
|
(void)pDSP;
|
||||||
|
|
||||||
mal_convert_frames__data* pData = (mal_convert_frames__data*)pUserData;
|
mal_convert_frames__data* pData = (mal_convert_frames__data*)pUserData;
|
||||||
mal_assert(pData != NULL);
|
mal_assert(pData != NULL);
|
||||||
mal_assert(pData->totalFrameCount >= pData->iNextFrame);
|
mal_assert(pData->totalFrameCount >= pData->iNextFrame);
|
||||||
@@ -10333,9 +10408,12 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
|
|||||||
// ================
|
// ================
|
||||||
//
|
//
|
||||||
// v0.x - 2017-xx-xx
|
// v0.x - 2017-xx-xx
|
||||||
|
// - API CHANGE: Expose and improve mutex APIs. If you were using the mutex APIs before this version you'll
|
||||||
|
// need to update.
|
||||||
|
// - API CHANGE: SRC and DSP callbacks now take a pointer to a mal_src and mal_dsp object respectively.
|
||||||
|
// - API CHANGE: Improvements to event and thread APIs. These changes make these APIs more consistent.
|
||||||
// - Add mal_convert_frames(). This is a high-level helper API for performing a one-time, bulk conversion of
|
// - Add mal_convert_frames(). This is a high-level helper API for performing a one-time, bulk conversion of
|
||||||
// audio data to a different format.
|
// audio data to a different format.
|
||||||
// - Expose the mutex APIs.
|
|
||||||
//
|
//
|
||||||
// v0.5 - 2017-11-11
|
// v0.5 - 2017-11-11
|
||||||
// - API CHANGE: The mal_context_init() function now takes a pointer to a mal_context_config object for
|
// - API CHANGE: The mal_context_init() function now takes a pointer to a mal_context_config object for
|
||||||
|
Reference in New Issue
Block a user