From 8b9c60448d4031de388d8e5a6b400114067111cc Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Fri, 16 Feb 2024 14:56:50 +0100 Subject: [PATCH] Protect the audio2 callbacks with a mutex --- .../Sources/kinc/backend/DirectSound.cpp | 10 +--- .../WASAPI/Sources/kinc/backend/wasapi.c | 23 ++------- .../Sources/kinc/backend/WASAPI.winrt.cpp | 22 ++------ .../Android/Sources/kinc/backend/audio.c.h | 22 ++------ .../Emscripten/Sources/kinc/backend/audio.c.h | 19 +------ .../Linux/Sources/kinc/backend/sound.c.h | 19 +------ .../Wasm/Sources/kinc/backend/audio.c.h | 18 ++----- .../System/iOS/Sources/kinc/backend/audio.m.h | 25 ++-------- .../macOS/Sources/kinc/backend/audio.c.h | 25 ++-------- Sources/kinc/audio2/audio.h | 50 ++++++++++++++++++- 10 files changed, 77 insertions(+), 156 deletions(-) diff --git a/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp b/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp index ea57965d2..cf2bcc6c0 100644 --- a/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp +++ b/Backends/Audio2/DirectSound/Sources/kinc/backend/DirectSound.cpp @@ -21,8 +21,6 @@ namespace { const int gap = 10 * 1024; DWORD writePos = gap; - void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = nullptr; - void *a2_userdata = nullptr; kinc_a2_buffer_t a2_buffer; } @@ -33,6 +31,7 @@ void kinc_a2_init() { return; } + kinc_a2_internal_init(); initialized = true; a2_buffer.read_location = 0; @@ -81,11 +80,6 @@ uint32_t kinc_a2_samples_per_second(void) { return samplesPerSecond; } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - namespace { void copySample(uint8_t *buffer, DWORD &index, bool left) { float value = *(float *)&a2_buffer.channels[left ? 0 : 1][a2_buffer.read_location]; @@ -133,7 +127,7 @@ void kinc_a2_update() { } } - a2_callback(&a2_buffer, (uint32_t)(gap / 4), a2_userdata); + kinc_a2_internal_callback(&a2_buffer, (uint32_t)(gap / 4)); DWORD size1; uint8_t *buffer1; diff --git a/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c b/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c index ca0aa2022..f730ac361 100644 --- a/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c +++ b/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c @@ -68,8 +68,6 @@ DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0x #endif // based on the implementation in soloud and Microsoft sample code -static void (*volatile a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; -static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; static IMMDeviceEnumerator *deviceEnumerator; @@ -83,18 +81,11 @@ static WAVEFORMATEX requestedFormat; static WAVEFORMATEX *closestFormat; static WAVEFORMATEX *format; static uint32_t samples_per_second = 44100; -static void (*sample_rate_callback)(void *userdata) = NULL; -static void *sample_rate_callback_userdata = NULL; uint32_t kinc_a2_samples_per_second(void) { return samples_per_second; } -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - sample_rate_callback_userdata = userdata; - sample_rate_callback = kinc_a2_sample_rate_callback; -} - static bool initDefaultDevice() { if (renderClient != NULL) { renderClient->lpVtbl->Release(renderClient); @@ -150,8 +141,8 @@ static bool initDefaultDevice() { uint32_t old_samples_per_second = samples_per_second; samples_per_second = format->nSamplesPerSec; - if (samples_per_second != old_samples_per_second && sample_rate_callback != NULL) { - sample_rate_callback(sample_rate_callback_userdata); + if (samples_per_second != old_samples_per_second) { + kinc_a2_internal_sample_rate_callback(); } a2_buffer.channel_count = 2; @@ -218,9 +209,7 @@ static void submitBuffer(unsigned frames) { return; } - if (a2_callback != NULL) { - a2_callback(&a2_buffer, frames, a2_userdata); - memset(buffer, 0, frames * format->nBlockAlign); + if (kinc_a2_internal_callback(&a2_buffer, frames)) { if (format->wFormatTag == WAVE_FORMAT_PCM) { for (UINT32 i = 0; i < frames; ++i) { copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign], (int16_t *)&buffer[i * format->nBlockAlign + 2]); @@ -276,6 +265,7 @@ void kinc_a2_init() { return; } + kinc_a2_internal_init(); initialized = true; a2_buffer.read_location = 0; @@ -296,11 +286,6 @@ void kinc_a2_init() { } } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - void kinc_a2_update() {} #define SAFE_RELEASE(punk) \ diff --git a/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp b/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp index cb218b120..76091ccbe 100644 --- a/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp +++ b/Backends/Audio2/WASAPI_WinRT/Sources/kinc/backend/WASAPI.winrt.cpp @@ -40,8 +40,6 @@ template void SafeRelease(__deref_inout_opt T **ppT) { // based on the implementation in soloud and Microsoft sample code namespace { kinc_thread_t thread; - void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; - void *a2_userdata = nullptr; kinc_a2_buffer_t a2_buffer; IMMDeviceEnumerator *deviceEnumerator; @@ -55,8 +53,6 @@ namespace { WAVEFORMATEX *closestFormat; WAVEFORMATEX *format; static uint32_t samples_per_second = 44100; - static void (*sample_rate_callback)(void *userdata) = NULL; - static void *sample_rate_callback_userdata = NULL; bool initDefaultDevice(); void audioThread(LPVOID); @@ -138,8 +134,8 @@ namespace { uint32_t old_samples_per_second = samples_per_second; samples_per_second = format->nSamplesPerSec; - if (samples_per_second != old_samples_per_second && sample_rate_callback != NULL) { - sample_rate_callback(sample_rate_callback_userdata); + if (samples_per_second != old_samples_per_second) { + kinc_a2_internal_sample_rate_callback(); } a2_buffer.channel_count = 2; @@ -206,9 +202,7 @@ namespace { return; } - if (a2_callback != nullptr) { - a2_callback(&a2_buffer, frames, a2_userdata); - memset(buffer, 0, frames * format->nBlockAlign); + if (kinc_a2_internal_callback(&a2_buffer, frames) { if (format->wFormatTag == WAVE_FORMAT_PCM) { for (UINT32 i = 0; i < frames; ++i) { copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign], (int16_t *)&buffer[i * format->nBlockAlign + 2]); @@ -267,6 +261,7 @@ void kinc_a2_init() { return; } + kinc_a2_internal_init(); initialized = true; a2_buffer.read_location = 0; @@ -297,19 +292,10 @@ void kinc_a2_init() { #endif } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - uint32_t kinc_a2_samples_per_second(void) { return samples_per_second; } -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - sample_rate_callback = kinc_a2_sample_rate_callback; -} - void kinc_a2_update() {} void kinc_a2_shutdown() { diff --git a/Backends/System/Android/Sources/kinc/backend/audio.c.h b/Backends/System/Android/Sources/kinc/backend/audio.c.h index 4b6b91a22..e33a7fd89 100644 --- a/Backends/System/Android/Sources/kinc/backend/audio.c.h +++ b/Backends/System/Android/Sources/kinc/backend/audio.c.h @@ -6,8 +6,6 @@ #include #include -static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; -static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; static SLObjectItf engineObject; @@ -31,17 +29,15 @@ static void copySample(void *buffer) { } static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf caller, void *context) { - if (a2_callback != NULL) { - a2_callback(&a2_buffer, AUDIO_BUFFER_SIZE / 2, a2_userdata); + if (kinc_a2_internal_callback(&a2_buffer, AUDIO_BUFFER_SIZE / 2)) { for (int i = 0; i < AUDIO_BUFFER_SIZE; i += 2) { copySample(&tempBuffer[i]); } - SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, tempBuffer, AUDIO_BUFFER_SIZE * 2); } else { memset(tempBuffer, 0, sizeof(tempBuffer)); - SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, tempBuffer, AUDIO_BUFFER_SIZE * 2); } + SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, tempBuffer, AUDIO_BUFFER_SIZE * 2); } static bool initialized = false; @@ -51,6 +47,7 @@ void kinc_a2_init() { return; } + kinc_a2_internal_init(); initialized = true; a2_buffer.read_location = 0; @@ -131,19 +128,6 @@ void kinc_a2_shutdown() { } } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - -static void (*sample_rate_callback)(void *userdata) = NULL; -static void *sample_rate_callback_userdata = NULL; - uint32_t kinc_a2_samples_per_second(void) { return 44100; } - -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - sample_rate_callback_userdata = userdata; - sample_rate_callback = kinc_a2_sample_rate_callback; -} diff --git a/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h b/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h index e55c9254a..b2ce47d20 100644 --- a/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h +++ b/Backends/System/Emscripten/Sources/kinc/backend/audio.c.h @@ -6,8 +6,6 @@ #include #include -static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; -static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; static ALCdevice *device = NULL; @@ -36,8 +34,7 @@ static void copySample(void *buffer) { } static void streamBuffer(ALuint buffer) { - if (a2_callback != NULL) { - a2_callback(&a2_buffer, BUFSIZE / 2, a2_userdata); + if (kinc_a2_internal_callback(&a2_buffer, BUFSIZE / 2)) { for (int i = 0; i < BUFSIZE; i += 2) { copySample(&buf[i]); } @@ -78,6 +75,7 @@ void kinc_a2_init() { return; } + kinc_a2_internal_init(); a2_initialized = true; a2_buffer.read_location = 0; @@ -115,19 +113,6 @@ void kinc_a2_shutdown() { audioRunning = false; } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - -static void (*sample_rate_callback)(void *userdata) = NULL; -static void *sample_rate_callback_userdata = NULL; - uint32_t kinc_a2_samples_per_second(void) { return samples_per_second; } - -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - sample_rate_callback_userdata = userdata; - sample_rate_callback = kinc_a2_sample_rate_callback; -} diff --git a/Backends/System/Linux/Sources/kinc/backend/sound.c.h b/Backends/System/Linux/Sources/kinc/backend/sound.c.h index 256823a1d..6a26044a3 100644 --- a/Backends/System/Linux/Sources/kinc/backend/sound.c.h +++ b/Backends/System/Linux/Sources/kinc/backend/sound.c.h @@ -9,8 +9,6 @@ // apt-get install libasound2-dev -void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; -void *a2_userdata = NULL; kinc_a2_buffer_t a2_buffer; pthread_t threadid; @@ -20,18 +18,10 @@ short buf[4096 * 4]; static unsigned int samples_per_second = 44100; -static void (*sample_rate_callback)(void *userdata) = NULL; -static void *sample_rate_callback_userdata = NULL; - uint32_t kinc_a2_samples_per_second(void) { return samples_per_second; } -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - sample_rate_callback_userdata = userdata; - sample_rate_callback = kinc_a2_sample_rate_callback; -} - void copySample(void *buffer) { float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location]; float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location]; @@ -45,8 +35,7 @@ void copySample(void *buffer) { int playback_callback(snd_pcm_sframes_t nframes) { int err = 0; - if (a2_callback != NULL) { - a2_callback(&a2_buffer, nframes, a2_userdata); + if (kinc_a2_internal_callback(&a2_buffer, nframes)) { int ni = 0; while (ni < nframes) { int i = 0; @@ -223,6 +212,7 @@ void kinc_a2_init() { return; } + kinc_a2_internal_init(); initialized = true; a2_buffer.read_location = 0; @@ -241,8 +231,3 @@ void kinc_a2_update() {} void kinc_a2_shutdown() { audioRunning = false; } - -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} diff --git a/Backends/System/Wasm/Sources/kinc/backend/audio.c.h b/Backends/System/Wasm/Sources/kinc/backend/audio.c.h index 3efcfcba8..3be8307a5 100644 --- a/Backends/System/Wasm/Sources/kinc/backend/audio.c.h +++ b/Backends/System/Wasm/Sources/kinc/backend/audio.c.h @@ -1,30 +1,18 @@ #include #include -static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; -static void *a2_userdata = NULL; static kinc_a2_buffer_t a2_buffer; -void kinc_a2_init() {} +void kinc_a2_init() { + kinc_a2_internal_init(); +} void kinc_a2_update() {} void kinc_a2_shutdown() {} -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - static uint32_t samples_per_second = 44100; -static void (*sample_rate_callback)(void *userdata) = NULL; -static void *sample_rate_callback_userdata = NULL; uint32_t kinc_a2_samples_per_second(void) { return samples_per_second; } - -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - sample_rate_callback_userdata = userdata; - sample_rate_callback = kinc_a2_sample_rate_callback; -} diff --git a/Backends/System/iOS/Sources/kinc/backend/audio.m.h b/Backends/System/iOS/Sources/kinc/backend/audio.m.h index 822070148..ab1a03a68 100644 --- a/Backends/System/iOS/Sources/kinc/backend/audio.m.h +++ b/Backends/System/iOS/Sources/kinc/backend/audio.m.h @@ -32,10 +32,6 @@ static AudioComponentInstance audioUnit; static bool isFloat = false; static bool isInterleaved = true; -static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; -static void *a2_userdata = NULL; -static void (*a2_sample_rate_callback)(void *userdata) = NULL; -static void *a2_sample_rate_userdata = NULL; static kinc_a2_buffer_t a2_buffer; static void copySample(void *buffer, void *secondary_buffer) { @@ -81,7 +77,7 @@ static void copySample(void *buffer, void *secondary_buffer) { static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *outOutputData) { - a2_callback(&a2_buffer, inNumberFrames, a2_userdata); + kinc_a2_internal_callback(&a2_buffer, inNumberFrames); if (isInterleaved) { if (isFloat) { float *output = (float *)outOutputData->mBuffers[0].mData; @@ -126,9 +122,7 @@ static void sampleRateListener(void *inRefCon, AudioUnit inUnit, AudioUnitProper if (samples_per_second != (uint32_t)sampleRate) { samples_per_second = (uint32_t)sampleRate; - if (a2_sample_rate_callback != NULL) { - a2_sample_rate_callback(a2_sample_rate_userdata); - } + kinc_a2_internal_sample_rate_callback(); } } @@ -139,6 +133,7 @@ void kinc_a2_init(void) { return; } + kinc_a2_internal_init(); initialized = true; a2_buffer.read_location = 0; @@ -199,9 +194,7 @@ void kinc_a2_init(void) { if (samples_per_second != (uint32_t)deviceFormat.mSampleRate) { samples_per_second = (uint32_t)deviceFormat.mSampleRate; - if (a2_sample_rate_callback != NULL) { - a2_sample_rate_callback(a2_sample_rate_userdata); - } + kinc_a2_internal_sample_rate_callback(); } AURenderCallbackStruct callbackStruct; @@ -225,16 +218,6 @@ void kinc_a2_shutdown(void) { soundPlaying = false; } -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - a2_sample_rate_callback = kinc_a2_sample_rate_callback; - a2_sample_rate_userdata = userdata; -} - uint32_t kinc_a2_samples_per_second(void) { return samples_per_second; } diff --git a/Backends/System/macOS/Sources/kinc/backend/audio.c.h b/Backends/System/macOS/Sources/kinc/backend/audio.c.h index 19f18feee..59d5a84cc 100644 --- a/Backends/System/macOS/Sources/kinc/backend/audio.c.h +++ b/Backends/System/macOS/Sources/kinc/backend/audio.c.h @@ -33,10 +33,6 @@ static AudioObjectPropertyAddress address; static AudioDeviceIOProcID theIOProcID = NULL; -static void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples, void *userdata) = NULL; -static void *a2_userdata = NULL; -static void (*a2_sample_rate_callback)(void *userdata) = NULL; -static void *a2_sample_rate_userdata = NULL; static kinc_a2_buffer_t a2_buffer; static uint32_t samples_per_second = 44100; @@ -61,12 +57,10 @@ static OSStatus appIOProc(AudioDeviceID inDevice, const AudioTimeStamp *inNow, c affirm(AudioObjectGetPropertyData(device, &address, 0, NULL, &size, &deviceFormat)); if (samples_per_second != (int)deviceFormat.mSampleRate) { samples_per_second = (int)deviceFormat.mSampleRate; - if (a2_sample_rate_callback != NULL) { - a2_sample_rate_callback(a2_sample_rate_userdata); - } + kinc_a2_internal_sample_rate_callback(); } int num_frames = deviceBufferSize / deviceFormat.mBytesPerFrame; - a2_callback(&a2_buffer, num_frames, a2_userdata); + kinc_a2_internal_callback(&a2_buffer, num_frames); float *output = (float *)outOutputData->mBuffers[0].mData; for (int i = 0; i < num_frames; ++i) { copySample(output); @@ -82,6 +76,7 @@ void kinc_a2_init(void) { return; } + kinc_a2_internal_init(); initialized = true; a2_buffer.read_location = 0; @@ -126,9 +121,7 @@ void kinc_a2_init(void) { if (samples_per_second != (int)deviceFormat.mSampleRate) { samples_per_second = (int)deviceFormat.mSampleRate; - if (a2_sample_rate_callback != NULL) { - a2_sample_rate_callback(a2_sample_rate_userdata); - } + kinc_a2_internal_sample_rate_callback(); } initialized = true; @@ -163,13 +156,3 @@ void kinc_a2_shutdown(void) { soundPlaying = false; } - -void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { - a2_callback = kinc_a2_audio_callback; - a2_userdata = userdata; -} - -void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { - a2_sample_rate_callback = kinc_a2_sample_rate_callback; - a2_sample_rate_userdata = userdata; -} diff --git a/Sources/kinc/audio2/audio.h b/Sources/kinc/audio2/audio.h index d1b476e10..55367ef1c 100644 --- a/Sources/kinc/audio2/audio.h +++ b/Sources/kinc/audio2/audio.h @@ -58,13 +58,61 @@ KINC_FUNC void kinc_a2_update(void); /// KINC_FUNC void kinc_a2_shutdown(void); +void kinc_a2_internal_init(void); +bool kinc_a2_internal_callback(kinc_a2_buffer_t *buffer, int samples); +void kinc_a2_internal_sample_rate_callback(void); + #ifdef KINC_IMPLEMENTATION_AUDIO2 #define KINC_IMPLEMENTATION #endif #ifdef KINC_IMPLEMENTATION -// BACKENDS-PLACEHOLDER +#include + +static kinc_mutex_t mutex; + +static void (*a2_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) = NULL; +static void *a2_userdata = NULL; + +void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata), void *userdata) { + kinc_mutex_lock(&mutex); + a2_callback = kinc_a2_audio_callback; + a2_userdata = userdata; + kinc_mutex_unlock(&mutex); +} + +static void (*a2_sample_rate_callback)(void *userdata) = NULL; +static void *a2_sample_rate_userdata = NULL; + +void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void *userdata), void *userdata) { + kinc_mutex_lock(&mutex); + a2_sample_rate_callback = kinc_a2_sample_rate_callback; + a2_sample_rate_userdata = userdata; + kinc_mutex_unlock(&mutex); +} + +void kinc_a2_internal_init(void) { + kinc_mutex_init(&mutex); +} + +bool kinc_a2_internal_callback(kinc_a2_buffer_t *buffer, int samples) { + kinc_mutex_lock(&mutex); + bool has_callback = a2_callback != NULL; + if (has_callback) { + a2_callback(buffer, samples, a2_userdata); + } + kinc_mutex_unlock(&mutex); + return has_callback; +} + +void kinc_a2_internal_sample_rate_callback(void) { + kinc_mutex_lock(&mutex); + if (a2_sample_rate_callback != NULL) { + a2_sample_rate_callback(a2_sample_rate_userdata); + } + kinc_mutex_unlock(&mutex); +} #endif