mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
thirdparty: update all sokol and fontstash headers with their upstream versions (#16940)
This commit is contained in:
327
thirdparty/sokol/sokol_audio.h
vendored
327
thirdparty/sokol/sokol_audio.h
vendored
@@ -17,9 +17,6 @@
|
||||
|
||||
SOKOL_DUMMY_BACKEND - use a dummy backend
|
||||
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
|
||||
SOKOL_LOG(msg) - your own logging function (default: puts(msg))
|
||||
SOKOL_MALLOC(s) - your own malloc() implementation (default: malloc(s))
|
||||
SOKOL_FREE(p) - your own free() implementation (default: free(p))
|
||||
SOKOL_AUDIO_API_DECL- public function declaration prefix (default: extern)
|
||||
SOKOL_API_DECL - same as SOKOL_AUDIO_API_DECL
|
||||
SOKOL_API_IMPL - public function implementation prefix (default: -)
|
||||
@@ -316,6 +313,8 @@
|
||||
|
||||
"Blob URLs": https://www.html5rocks.com/en/tutorials/workers/basics/
|
||||
|
||||
Also see: https://blog.paul.cx/post/a-wait-free-spsc-ringbuffer-for-the-web/
|
||||
|
||||
THE COREAUDIO BACKEND
|
||||
=====================
|
||||
The CoreAudio backend is selected on macOS and iOS (__APPLE__ is defined).
|
||||
@@ -365,6 +364,62 @@
|
||||
header must be present (usually both are installed with some sort
|
||||
of ALSA development package).
|
||||
|
||||
|
||||
MEMORY ALLOCATION OVERRIDE
|
||||
==========================
|
||||
You can override the memory allocation functions at initialization time
|
||||
like this:
|
||||
|
||||
void* my_alloc(size_t size, void* user_data) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void my_free(void* ptr, void* user_data) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
...
|
||||
saudio_setup(&(saudio_desc){
|
||||
// ...
|
||||
.allocator = {
|
||||
.alloc = my_alloc,
|
||||
.free = my_free,
|
||||
.user_data = ...,
|
||||
}
|
||||
});
|
||||
...
|
||||
|
||||
If no overrides are provided, malloc and free will be used.
|
||||
|
||||
This only affects memory allocation calls done by sokol_audio.h
|
||||
itself though, not any allocations in OS libraries.
|
||||
|
||||
Memory allocation will only happen on the same thread where saudio_setup()
|
||||
was called, so you don't need to worry about thread-safety.
|
||||
|
||||
|
||||
LOG FUNCTION OVERRIDE
|
||||
=====================
|
||||
You can override the log function at initialization time like this:
|
||||
|
||||
void my_log(const char* message, void* user_data) {
|
||||
printf("saudio says: \s\n", message);
|
||||
}
|
||||
|
||||
...
|
||||
saudio_setup(&(saudio_desc){
|
||||
// ...
|
||||
.logger = {
|
||||
.log_cb = my_log,
|
||||
.user_data = ...,
|
||||
}
|
||||
});
|
||||
...
|
||||
|
||||
If no overrides are provided, puts will be used on most platforms.
|
||||
On Android, __android_log_write will be used instead.
|
||||
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
|
||||
@@ -392,6 +447,7 @@
|
||||
distribution.
|
||||
*/
|
||||
#define SOKOL_AUDIO_INCLUDED (1)
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -412,15 +468,42 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
saudio_allocator
|
||||
|
||||
Used in saudio_desc to provide custom memory-alloc and -free functions
|
||||
to sokol_audio.h. If memory management should be overridden, both the
|
||||
alloc and free function must be provided (e.g. it's not valid to
|
||||
override one function but not the other).
|
||||
*/
|
||||
typedef struct saudio_allocator {
|
||||
void* (*alloc)(size_t size, void* user_data);
|
||||
void (*free)(void* ptr, void* user_data);
|
||||
void* user_data;
|
||||
} saudio_allocator;
|
||||
|
||||
/*
|
||||
saudio_logger
|
||||
|
||||
Used in saudio_desc to provide custom log callbacks to sokol_audio.h.
|
||||
Default behavior is SOKOL_LOG(message).
|
||||
*/
|
||||
typedef struct saudio_logger {
|
||||
void (*log_cb)(const char* message, void* user_data);
|
||||
void* user_data;
|
||||
} saudio_logger;
|
||||
|
||||
typedef struct saudio_desc {
|
||||
int sample_rate; /* requested sample rate */
|
||||
int num_channels; /* number of channels, default: 1 (mono) */
|
||||
int buffer_frames; /* number of frames in streaming buffer */
|
||||
int packet_frames; /* number of frames in a packet */
|
||||
int num_packets; /* number of packets in packet queue */
|
||||
void (*stream_cb)(float* buffer, int num_frames, int num_channels); /* optional streaming callback (no user data) */
|
||||
void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data); /*... and with user data */
|
||||
void* user_data; /* optional user data argument for stream_userdata_cb */
|
||||
int sample_rate; // requested sample rate
|
||||
int num_channels; // number of channels, default: 1 (mono)
|
||||
int buffer_frames; // number of frames in streaming buffer
|
||||
int packet_frames; // number of frames in a packet
|
||||
int num_packets; // number of packets in packet queue
|
||||
void (*stream_cb)(float* buffer, int num_frames, int num_channels); // optional streaming callback (no user data)
|
||||
void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data); //... and with user data
|
||||
void* user_data; // optional user data argument for stream_userdata_cb
|
||||
saudio_allocator allocator; // optional allocation override functions
|
||||
saudio_logger logger; // optional log override functions
|
||||
} saudio_desc;
|
||||
|
||||
/* setup sokol-audio */
|
||||
@@ -458,6 +541,12 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc);
|
||||
/*=== IMPLEMENTATION =========================================================*/
|
||||
#ifdef SOKOL_AUDIO_IMPL
|
||||
#define SOKOL_AUDIO_IMPL_INCLUDED (1)
|
||||
|
||||
#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)
|
||||
#error "SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use saudio_desc.allocator to override memory allocation functions"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> // alloc, free
|
||||
#include <string.h> // memset, memcpy
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
@@ -466,24 +555,26 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc);
|
||||
#endif
|
||||
#ifndef SOKOL_DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define SOKOL_DEBUG (1)
|
||||
#define SOKOL_DEBUG
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SOKOL_ASSERT
|
||||
#include <assert.h>
|
||||
#define SOKOL_ASSERT(c) assert(c)
|
||||
#endif
|
||||
#ifndef SOKOL_MALLOC
|
||||
#include <stdlib.h>
|
||||
#define SOKOL_MALLOC(s) malloc(s)
|
||||
#define SOKOL_FREE(p) free(p)
|
||||
#endif
|
||||
#ifndef SOKOL_LOG
|
||||
#ifdef SOKOL_DEBUG
|
||||
#include <stdio.h>
|
||||
#define SOKOL_LOG(s) { SOKOL_ASSERT(s); puts(s); }
|
||||
#else
|
||||
#define SOKOL_LOG(s)
|
||||
|
||||
#if !defined(SOKOL_DEBUG)
|
||||
#define SAUDIO_LOG(s)
|
||||
#else
|
||||
#define SAUDIO_LOG(s) _saudio_log(s)
|
||||
#ifndef SOKOL_LOG
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#define SOKOL_LOG(s) __android_log_write(ANDROID_LOG_INFO, "SOKOL_AUDIO", s)
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define SOKOL_LOG(s) puts(s)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -670,6 +761,9 @@ typedef OSStatus _saudio_OSStatus;
|
||||
#define _saudio_kAudioFormatFlagIsPacked (kAudioFormatFlagIsPacked)
|
||||
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// embedded AudioToolbox declarations
|
||||
typedef uint32_t _saudio_AudioFormatID;
|
||||
@@ -745,6 +839,11 @@ extern _saudio_OSStatus AudioQueueAllocateBuffer(_saudio_AudioQueueRef inAQ, uin
|
||||
extern _saudio_OSStatus AudioQueueEnqueueBuffer(_saudio_AudioQueueRef inAQ, _saudio_AudioQueueBufferRef inBuffer, uint32_t inNumPacketDescs, const _saudio_AudioStreamPacketDescription* inPacketDescs);
|
||||
extern _saudio_OSStatus AudioQueueStart(_saudio_AudioQueueRef inAQ, const _saudio_AudioTimeStamp * inStartTime);
|
||||
extern _saudio_OSStatus AudioQueueStop(_saudio_AudioQueueRef inAQ, bool inImmediate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SAUDIO_OSX_USE_SYSTEM_HEADERS
|
||||
|
||||
typedef struct {
|
||||
@@ -893,6 +992,51 @@ _SOKOL_PRIVATE void _saudio_stream_callback(float* buffer, int num_frames, int n
|
||||
}
|
||||
}
|
||||
|
||||
/*=== MEMORY HELPERS ========================================================*/
|
||||
_SOKOL_PRIVATE void _saudio_clear(void* ptr, size_t size) {
|
||||
SOKOL_ASSERT(ptr && (size > 0));
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void* _saudio_malloc(size_t size) {
|
||||
SOKOL_ASSERT(size > 0);
|
||||
void* ptr;
|
||||
if (_saudio.desc.allocator.alloc) {
|
||||
ptr = _saudio.desc.allocator.alloc(size, _saudio.desc.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
ptr = malloc(size);
|
||||
}
|
||||
SOKOL_ASSERT(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void* _saudio_malloc_clear(size_t size) {
|
||||
void* ptr = _saudio_malloc(size);
|
||||
_saudio_clear(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void _saudio_free(void* ptr) {
|
||||
if (_saudio.desc.allocator.free) {
|
||||
_saudio.desc.allocator.free(ptr, _saudio.desc.allocator.user_data);
|
||||
}
|
||||
else {
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SOKOL_DEBUG)
|
||||
_SOKOL_PRIVATE void _saudio_log(const char* msg) {
|
||||
SOKOL_ASSERT(msg);
|
||||
if (_saudio.desc.logger.log_cb) {
|
||||
_saudio.desc.logger.log_cb(msg, _saudio.desc.logger.user_data);
|
||||
} else {
|
||||
SOKOL_LOG(msg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*=== MUTEX IMPLEMENTATION ===================================================*/
|
||||
#if defined(_SAUDIO_NOTHREADS)
|
||||
|
||||
@@ -1003,8 +1147,7 @@ _SOKOL_PRIVATE void _saudio_fifo_init(_saudio_fifo_t* fifo, int packet_size, int
|
||||
SOKOL_ASSERT((packet_size > 0) && (num_packets > 0));
|
||||
fifo->packet_size = packet_size;
|
||||
fifo->num_packets = num_packets;
|
||||
fifo->base_ptr = (uint8_t*) SOKOL_MALLOC((size_t)(packet_size * num_packets));
|
||||
SOKOL_ASSERT(fifo->base_ptr);
|
||||
fifo->base_ptr = (uint8_t*) _saudio_malloc((size_t)(packet_size * num_packets));
|
||||
fifo->cur_packet = -1;
|
||||
fifo->cur_offset = 0;
|
||||
_saudio_ring_init(&fifo->read_queue, num_packets);
|
||||
@@ -1022,7 +1165,7 @@ _SOKOL_PRIVATE void _saudio_fifo_init(_saudio_fifo_t* fifo, int packet_size, int
|
||||
|
||||
_SOKOL_PRIVATE void _saudio_fifo_shutdown(_saudio_fifo_t* fifo) {
|
||||
SOKOL_ASSERT(fifo->base_ptr);
|
||||
SOKOL_FREE(fifo->base_ptr);
|
||||
_saudio_free(fifo->base_ptr);
|
||||
fifo->base_ptr = 0;
|
||||
fifo->valid = false;
|
||||
_saudio_mutex_destroy(&fifo->mutex);
|
||||
@@ -1191,7 +1334,7 @@ _SOKOL_PRIVATE void _saudio_coreaudio_callback(void* user_data, _saudio_AudioQue
|
||||
int num_bytes = (int) buffer->mAudioDataByteSize;
|
||||
if (0 == _saudio_fifo_read(&_saudio.fifo, ptr, num_bytes)) {
|
||||
/* not enough read data available, fill the entire buffer with silence */
|
||||
memset(ptr, 0, (size_t)num_bytes);
|
||||
_saudio_clear(ptr, (size_t)num_bytes);
|
||||
}
|
||||
}
|
||||
AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);
|
||||
@@ -1213,7 +1356,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
|
||||
/* create an audio queue with fp32 samples */
|
||||
_saudio_AudioStreamBasicDescription fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
_saudio_clear(&fmt, sizeof(fmt));
|
||||
fmt.mSampleRate = (double) _saudio.sample_rate;
|
||||
fmt.mFormatID = _saudio_kAudioFormatLinearPCM;
|
||||
fmt.mFormatFlags = _saudio_kLinearPCMFormatFlagIsFloat | _saudio_kAudioFormatFlagIsPacked;
|
||||
@@ -1223,16 +1366,16 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
fmt.mBytesPerPacket = fmt.mBytesPerFrame;
|
||||
fmt.mBitsPerChannel = 32;
|
||||
_saudio_OSStatus res = AudioQueueNewOutput(&fmt, _saudio_coreaudio_callback, 0, NULL, NULL, 0, &_saudio.backend.ca_audio_queue);
|
||||
SOKOL_ASSERT((res == 0) && _saudio.backend.ca_audio_queue);
|
||||
SOKOL_ASSERT((res == 0) && _saudio.backend.ca_audio_queue); (void)res;
|
||||
|
||||
/* create 2 audio buffers */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
_saudio_AudioQueueBufferRef buf = NULL;
|
||||
const uint32_t buf_byte_size = (uint32_t)_saudio.buffer_frames * fmt.mBytesPerFrame;
|
||||
res = AudioQueueAllocateBuffer(_saudio.backend.ca_audio_queue, buf_byte_size, &buf);
|
||||
SOKOL_ASSERT((res == 0) && buf);
|
||||
SOKOL_ASSERT((res == 0) && buf); (void)res;
|
||||
buf->mAudioDataByteSize = buf_byte_size;
|
||||
memset(buf->mAudioData, 0, buf->mAudioDataByteSize);
|
||||
_saudio_clear(buf->mAudioData, buf->mAudioDataByteSize);
|
||||
AudioQueueEnqueueBuffer(_saudio.backend.ca_audio_queue, buf, 0, NULL);
|
||||
}
|
||||
|
||||
@@ -1241,7 +1384,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
|
||||
/* ...and start playback */
|
||||
res = AudioQueueStart(_saudio.backend.ca_audio_queue, NULL);
|
||||
SOKOL_ASSERT(0 == res);
|
||||
SOKOL_ASSERT(0 == res); (void)res;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1284,7 +1427,7 @@ _SOKOL_PRIVATE void* _saudio_alsa_cb(void* param) {
|
||||
else {
|
||||
if (0 == _saudio_fifo_read(&_saudio.fifo, (uint8_t*)_saudio.backend.buffer, _saudio.backend.buffer_byte_size)) {
|
||||
/* not enough read data available, fill the entire buffer with silence */
|
||||
memset(_saudio.backend.buffer, 0, (size_t)_saudio.backend.buffer_byte_size);
|
||||
_saudio_clear(_saudio.backend.buffer, (size_t)_saudio.backend.buffer_byte_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1296,7 +1439,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
int dir; uint32_t rate;
|
||||
int rc = snd_pcm_open(&_saudio.backend.device, "default", SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (rc < 0) {
|
||||
SOKOL_LOG("sokol_audio.h: snd_pcm_open() failed");
|
||||
SAUDIO_LOG("sokol_audio.h: snd_pcm_open() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1309,26 +1452,26 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
snd_pcm_hw_params_any(_saudio.backend.device, params);
|
||||
snd_pcm_hw_params_set_access(_saudio.backend.device, params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (0 > snd_pcm_hw_params_set_format(_saudio.backend.device, params, SND_PCM_FORMAT_FLOAT_LE)) {
|
||||
SOKOL_LOG("sokol_audio.h: float samples not supported");
|
||||
SAUDIO_LOG("sokol_audio.h: float samples not supported");
|
||||
goto error;
|
||||
}
|
||||
if (0 > snd_pcm_hw_params_set_buffer_size(_saudio.backend.device, params, (snd_pcm_uframes_t)_saudio.buffer_frames)) {
|
||||
SOKOL_LOG("sokol_audio.h: requested buffer size not supported");
|
||||
SAUDIO_LOG("sokol_audio.h: requested buffer size not supported");
|
||||
goto error;
|
||||
}
|
||||
if (0 > snd_pcm_hw_params_set_channels(_saudio.backend.device, params, (uint32_t)_saudio.num_channels)) {
|
||||
SOKOL_LOG("sokol_audio.h: requested channel count not supported");
|
||||
SAUDIO_LOG("sokol_audio.h: requested channel count not supported");
|
||||
goto error;
|
||||
}
|
||||
/* let ALSA pick a nearby sampling rate */
|
||||
rate = (uint32_t) _saudio.sample_rate;
|
||||
dir = 0;
|
||||
if (0 > snd_pcm_hw_params_set_rate_near(_saudio.backend.device, params, &rate, &dir)) {
|
||||
SOKOL_LOG("sokol_audio.h: snd_pcm_hw_params_set_rate_near() failed");
|
||||
SAUDIO_LOG("sokol_audio.h: snd_pcm_hw_params_set_rate_near() failed");
|
||||
goto error;
|
||||
}
|
||||
if (0 > snd_pcm_hw_params(_saudio.backend.device, params)) {
|
||||
SOKOL_LOG("sokol_audio.h: snd_pcm_hw_params() failed");
|
||||
SAUDIO_LOG("sokol_audio.h: snd_pcm_hw_params() failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1339,12 +1482,11 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
/* allocate the streaming buffer */
|
||||
_saudio.backend.buffer_byte_size = _saudio.buffer_frames * _saudio.bytes_per_frame;
|
||||
_saudio.backend.buffer_frames = _saudio.buffer_frames;
|
||||
_saudio.backend.buffer = (float*) SOKOL_MALLOC((size_t)_saudio.backend.buffer_byte_size);
|
||||
memset(_saudio.backend.buffer, 0, (size_t)_saudio.backend.buffer_byte_size);
|
||||
_saudio.backend.buffer = (float*) _saudio_malloc_clear((size_t)_saudio.backend.buffer_byte_size);
|
||||
|
||||
/* create the buffer-streaming start thread */
|
||||
if (0 != pthread_create(&_saudio.backend.thread, 0, _saudio_alsa_cb, 0)) {
|
||||
SOKOL_LOG("sokol_audio.h: pthread_create() failed");
|
||||
SAUDIO_LOG("sokol_audio.h: pthread_create() failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1363,7 +1505,7 @@ _SOKOL_PRIVATE void _saudio_backend_shutdown(void) {
|
||||
pthread_join(_saudio.backend.thread, 0);
|
||||
snd_pcm_drain(_saudio.backend.device);
|
||||
snd_pcm_close(_saudio.backend.device);
|
||||
SOKOL_FREE(_saudio.backend.buffer);
|
||||
_saudio_free(_saudio.backend.buffer);
|
||||
};
|
||||
|
||||
/*=== WASAPI BACKEND IMPLEMENTATION ==========================================*/
|
||||
@@ -1419,7 +1561,7 @@ _SOKOL_PRIVATE void _saudio_wasapi_fill_buffer(void) {
|
||||
else {
|
||||
if (0 == _saudio_fifo_read(&_saudio.fifo, (uint8_t*)_saudio.backend.thread.src_buffer, _saudio.backend.thread.src_buffer_byte_size)) {
|
||||
/* not enough read data available, fill the entire buffer with silence */
|
||||
memset(_saudio.backend.thread.src_buffer, 0, (size_t)_saudio.backend.thread.src_buffer_byte_size);
|
||||
_saudio_clear(_saudio.backend.thread.src_buffer, (size_t)_saudio.backend.thread.src_buffer_byte_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1487,7 +1629,7 @@ _SOKOL_PRIVATE DWORD WINAPI _saudio_wasapi_thread_fn(LPVOID param) {
|
||||
|
||||
_SOKOL_PRIVATE void _saudio_wasapi_release(void) {
|
||||
if (_saudio.backend.thread.src_buffer) {
|
||||
SOKOL_FREE(_saudio.backend.thread.src_buffer);
|
||||
_saudio_free(_saudio.backend.thread.src_buffer);
|
||||
_saudio.backend.thread.src_buffer = 0;
|
||||
}
|
||||
if (_saudio.backend.render_client) {
|
||||
@@ -1537,17 +1679,17 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
#endif
|
||||
_saudio.backend.thread.buffer_end_event = CreateEvent(0, FALSE, FALSE, 0);
|
||||
if (0 == _saudio.backend.thread.buffer_end_event) {
|
||||
SOKOL_LOG("sokol_audio wasapi: failed to create buffer_end_event");
|
||||
SAUDIO_LOG("sokol_audio wasapi: failed to create buffer_end_event");
|
||||
goto error;
|
||||
}
|
||||
#if defined(_SAUDIO_UWP)
|
||||
_saudio.backend.interface_activation_mutex = CreateMutexA(NULL, FALSE, "interface_activation_mutex");
|
||||
if (_saudio.backend.interface_activation_mutex == NULL) {
|
||||
SOKOL_LOG("sokol_audio wasapi: failed to create interface activation mutex");
|
||||
SAUDIO_LOG("sokol_audio wasapi: failed to create interface activation mutex");
|
||||
goto error;
|
||||
}
|
||||
if (FAILED(StringFromIID(_SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_Devinterface_Audio_Render), &_saudio.backend.interface_activation_audio_interface_uid_string))) {
|
||||
SOKOL_LOG("sokol_audio wasapi: failed to get default audio device ID string");
|
||||
SAUDIO_LOG("sokol_audio wasapi: failed to get default audio device ID string");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1561,7 +1703,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
static IActivateAudioInterfaceCompletionHandler completion_handler_interface = { &completion_handler_interface_vtable };
|
||||
|
||||
if (FAILED(ActivateAudioInterfaceAsync(_saudio.backend.interface_activation_audio_interface_uid_string, _SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IAudioClient), NULL, &completion_handler_interface, &_saudio.backend.interface_activation_operation))) {
|
||||
SOKOL_LOG("sokol_audio wasapi: failed to get default audio device ID string");
|
||||
SAUDIO_LOG("sokol_audio wasapi: failed to get default audio device ID string");
|
||||
goto error;
|
||||
}
|
||||
while (!(_saudio.backend.audio_client)) {
|
||||
@@ -1571,7 +1713,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
}
|
||||
|
||||
if (!(_saudio.backend.interface_activation_success)) {
|
||||
SOKOL_LOG("sokol_audio wasapi: interface activation failed. Unable to get audio client");
|
||||
SAUDIO_LOG("sokol_audio wasapi: interface activation failed. Unable to get audio client");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1581,14 +1723,14 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
_SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IMMDeviceEnumerator),
|
||||
(void**)&_saudio.backend.device_enumerator)))
|
||||
{
|
||||
SOKOL_LOG("sokol_audio wasapi: failed to create device enumerator");
|
||||
SAUDIO_LOG("sokol_audio wasapi: failed to create device enumerator");
|
||||
goto error;
|
||||
}
|
||||
if (FAILED(IMMDeviceEnumerator_GetDefaultAudioEndpoint(_saudio.backend.device_enumerator,
|
||||
eRender, eConsole,
|
||||
&_saudio.backend.device)))
|
||||
{
|
||||
SOKOL_LOG("sokol_audio wasapi: GetDefaultAudioEndPoint failed");
|
||||
SAUDIO_LOG("sokol_audio wasapi: GetDefaultAudioEndPoint failed");
|
||||
goto error;
|
||||
}
|
||||
if (FAILED(IMMDevice_Activate(_saudio.backend.device,
|
||||
@@ -1596,13 +1738,13 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
CLSCTX_ALL, 0,
|
||||
(void**)&_saudio.backend.audio_client)))
|
||||
{
|
||||
SOKOL_LOG("sokol_audio wasapi: device activate failed");
|
||||
SAUDIO_LOG("sokol_audio wasapi: device activate failed");
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
WAVEFORMATEXTENSIBLE fmtex;
|
||||
memset(&fmtex, 0, sizeof(fmtex));
|
||||
_saudio_clear(&fmtex, sizeof(fmtex));
|
||||
fmtex.Format.nChannels = (WORD)_saudio.num_channels;
|
||||
fmtex.Format.nSamplesPerSec = (DWORD)_saudio.sample_rate;
|
||||
fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
@@ -1625,22 +1767,22 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK|AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM|AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY,
|
||||
dur, 0, (WAVEFORMATEX*)&fmtex, 0)))
|
||||
{
|
||||
SOKOL_LOG("sokol_audio wasapi: audio client initialize failed");
|
||||
SAUDIO_LOG("sokol_audio wasapi: audio client initialize failed");
|
||||
goto error;
|
||||
}
|
||||
if (FAILED(IAudioClient_GetBufferSize(_saudio.backend.audio_client, &_saudio.backend.thread.dst_buffer_frames))) {
|
||||
SOKOL_LOG("sokol_audio wasapi: audio client get buffer size failed");
|
||||
SAUDIO_LOG("sokol_audio wasapi: audio client get buffer size failed");
|
||||
goto error;
|
||||
}
|
||||
if (FAILED(IAudioClient_GetService(_saudio.backend.audio_client,
|
||||
_SOKOL_AUDIO_WIN32COM_ID(_saudio_IID_IAudioRenderClient),
|
||||
(void**)&_saudio.backend.render_client)))
|
||||
{
|
||||
SOKOL_LOG("sokol_audio wasapi: audio client GetService failed");
|
||||
SAUDIO_LOG("sokol_audio wasapi: audio client GetService failed");
|
||||
goto error;
|
||||
}
|
||||
if (FAILED(IAudioClient_SetEventHandle(_saudio.backend.audio_client, _saudio.backend.thread.buffer_end_event))) {
|
||||
SOKOL_LOG("sokol_audio wasapi: audio client SetEventHandle failed");
|
||||
SAUDIO_LOG("sokol_audio wasapi: audio client SetEventHandle failed");
|
||||
goto error;
|
||||
}
|
||||
_saudio.bytes_per_frame = _saudio.num_channels * (int)sizeof(float);
|
||||
@@ -1648,13 +1790,12 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
_saudio.backend.thread.src_buffer_byte_size = _saudio.backend.thread.src_buffer_frames * _saudio.bytes_per_frame;
|
||||
|
||||
/* allocate an intermediate buffer for sample format conversion */
|
||||
_saudio.backend.thread.src_buffer = (float*) SOKOL_MALLOC((size_t)_saudio.backend.thread.src_buffer_byte_size);
|
||||
SOKOL_ASSERT(_saudio.backend.thread.src_buffer);
|
||||
_saudio.backend.thread.src_buffer = (float*) _saudio_malloc((size_t)_saudio.backend.thread.src_buffer_byte_size);
|
||||
|
||||
/* create streaming thread */
|
||||
_saudio.backend.thread.thread_handle = CreateThread(NULL, 0, _saudio_wasapi_thread_fn, 0, 0, 0);
|
||||
if (0 == _saudio.backend.thread.thread_handle) {
|
||||
SOKOL_LOG("sokol_audio wasapi: CreateThread failed");
|
||||
SAUDIO_LOG("sokol_audio wasapi: CreateThread failed");
|
||||
goto error;
|
||||
}
|
||||
return true;
|
||||
@@ -1698,7 +1839,7 @@ EMSCRIPTEN_KEEPALIVE int _saudio_emsc_pull(int num_frames) {
|
||||
const int num_bytes = num_frames * _saudio.bytes_per_frame;
|
||||
if (0 == _saudio_fifo_read(&_saudio.fifo, _saudio.backend.buffer, num_bytes)) {
|
||||
/* not enough read data available, fill the entire buffer with silence */
|
||||
memset(_saudio.backend.buffer, 0, (size_t)num_bytes);
|
||||
_saudio_clear(_saudio.backend.buffer, (size_t)num_bytes);
|
||||
}
|
||||
}
|
||||
int res = (int) _saudio.backend.buffer;
|
||||
@@ -1723,12 +1864,6 @@ EM_JS(int, saudio_js_init, (int sample_rate, int num_channels, int buffer_size),
|
||||
latencyHint: 'interactive',
|
||||
});
|
||||
}
|
||||
else if (typeof webkitAudioContext !== 'undefined') {
|
||||
Module._saudio_context = new webkitAudioContext({
|
||||
sampleRate: sample_rate,
|
||||
latencyHint: 'interactive',
|
||||
});
|
||||
}
|
||||
else {
|
||||
Module._saudio_context = null;
|
||||
console.log('sokol_audio.h: no WebAudio support');
|
||||
@@ -1736,14 +1871,14 @@ EM_JS(int, saudio_js_init, (int sample_rate, int num_channels, int buffer_size),
|
||||
if (Module._saudio_context) {
|
||||
console.log('sokol_audio.h: sample rate ', Module._saudio_context.sampleRate);
|
||||
Module._saudio_node = Module._saudio_context.createScriptProcessor(buffer_size, 0, num_channels);
|
||||
Module._saudio_node.onaudioprocess = function pump_audio(event) {
|
||||
var num_frames = event.outputBuffer.length;
|
||||
var ptr = __saudio_emsc_pull(num_frames);
|
||||
Module._saudio_node.onaudioprocess = (event) => {
|
||||
const num_frames = event.outputBuffer.length;
|
||||
const ptr = __saudio_emsc_pull(num_frames);
|
||||
if (ptr) {
|
||||
var num_channels = event.outputBuffer.numberOfChannels;
|
||||
for (var chn = 0; chn < num_channels; chn++) {
|
||||
var chan = event.outputBuffer.getChannelData(chn);
|
||||
for (var i = 0; i < num_frames; i++) {
|
||||
const num_channels = event.outputBuffer.numberOfChannels;
|
||||
for (let chn = 0; chn < num_channels; chn++) {
|
||||
const chan = event.outputBuffer.getChannelData(chn);
|
||||
for (let i = 0; i < num_frames; i++) {
|
||||
chan[i] = HEAPF32[(ptr>>2) + ((num_channels*i)+chn)]
|
||||
}
|
||||
}
|
||||
@@ -1752,7 +1887,7 @@ EM_JS(int, saudio_js_init, (int sample_rate, int num_channels, int buffer_size),
|
||||
Module._saudio_node.connect(Module._saudio_context.destination);
|
||||
|
||||
// in some browsers, WebAudio needs to be activated on a user action
|
||||
var resume_webaudio = function() {
|
||||
const resume_webaudio = () => {
|
||||
if (Module._saudio_context) {
|
||||
if (Module._saudio_context.state === 'suspended') {
|
||||
Module._saudio_context.resume();
|
||||
@@ -1771,11 +1906,13 @@ EM_JS(int, saudio_js_init, (int sample_rate, int num_channels, int buffer_size),
|
||||
|
||||
/* shutdown the WebAudioContext and ScriptProcessorNode */
|
||||
EM_JS(void, saudio_js_shutdown, (void), {
|
||||
if (Module._saudio_context !== null) {
|
||||
\x2F\x2A\x2A @suppress {missingProperties} \x2A\x2F
|
||||
const ctx = Module._saudio_context;
|
||||
if (ctx !== null) {
|
||||
if (Module._saudio_node) {
|
||||
Module._saudio_node.disconnect();
|
||||
}
|
||||
Module._saudio_context.close();
|
||||
ctx.close();
|
||||
Module._saudio_context = null;
|
||||
Module._saudio_node = null;
|
||||
}
|
||||
@@ -1819,7 +1956,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
_saudio.sample_rate = saudio_js_sample_rate();
|
||||
_saudio.buffer_frames = saudio_js_buffer_frames();
|
||||
const size_t buf_size = (size_t) (_saudio.buffer_frames * _saudio.bytes_per_frame);
|
||||
_saudio.backend.buffer = (uint8_t*) SOKOL_MALLOC(buf_size);
|
||||
_saudio.backend.buffer = (uint8_t*) _saudio_malloc(buf_size);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -1830,7 +1967,7 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
_SOKOL_PRIVATE void _saudio_backend_shutdown(void) {
|
||||
saudio_js_shutdown();
|
||||
if (_saudio.backend.buffer) {
|
||||
SOKOL_FREE(_saudio.backend.buffer);
|
||||
_saudio_free(_saudio.backend.buffer);
|
||||
_saudio.backend.buffer = 0;
|
||||
}
|
||||
}
|
||||
@@ -1904,7 +2041,7 @@ _SOKOL_PRIVATE void _saudio_opensles_fill_buffer(void) {
|
||||
const int src_buffer_byte_size = src_buffer_frames * _saudio.num_channels * (int)sizeof(float);
|
||||
if (0 == _saudio_fifo_read(&_saudio.fifo, (uint8_t*)_saudio.backend.src_buffer, src_buffer_byte_size)) {
|
||||
/* not enough read data available, fill the entire buffer with silence */
|
||||
memset(_saudio.backend.src_buffer, 0x0, (size_t)src_buffer_byte_size);
|
||||
_saudio_clear(_saudio.backend.src_buffer, (size_t)src_buffer_byte_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1919,6 +2056,7 @@ _SOKOL_PRIVATE void SLAPIENTRY _saudio_opensles_play_cb(SLPlayItf player, void *
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE void* _saudio_opensles_thread_fn(void* param) {
|
||||
_SOKOL_UNUSED(param);
|
||||
while (!_saudio.backend.thread_stop) {
|
||||
/* get next output buffer, advance, next buffer. */
|
||||
int16_t* out_buffer = _saudio.backend.output_buffers[_saudio.backend.active_buffer];
|
||||
@@ -1959,9 +2097,9 @@ _SOKOL_PRIVATE void _saudio_backend_shutdown(void) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < SAUDIO_NUM_BUFFERS; i++) {
|
||||
SOKOL_FREE(_saudio.backend.output_buffers[i]);
|
||||
_saudio_free(_saudio.backend.output_buffers[i]);
|
||||
}
|
||||
SOKOL_FREE(_saudio.backend.src_buffer);
|
||||
_saudio_free(_saudio.backend.src_buffer);
|
||||
}
|
||||
|
||||
_SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
@@ -1969,29 +2107,25 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
|
||||
for (int i = 0; i < SAUDIO_NUM_BUFFERS; ++i) {
|
||||
const int buffer_size_bytes = (int)sizeof(int16_t) * _saudio.num_channels * _saudio.buffer_frames;
|
||||
_saudio.backend.output_buffers[i] = (int16_t*) SOKOL_MALLOC((size_t)buffer_size_bytes);
|
||||
SOKOL_ASSERT(_saudio.backend.output_buffers[i]);
|
||||
memset(_saudio.backend.output_buffers[i], 0x0, (size_t)buffer_size_bytes);
|
||||
_saudio.backend.output_buffers[i] = (int16_t*) _saudio_malloc_clear((size_t)buffer_size_bytes);
|
||||
}
|
||||
|
||||
{
|
||||
const int buffer_size_bytes = _saudio.bytes_per_frame * _saudio.buffer_frames;
|
||||
_saudio.backend.src_buffer = (float*) SOKOL_MALLOC((size_t)buffer_size_bytes);
|
||||
SOKOL_ASSERT(_saudio.backend.src_buffer);
|
||||
memset(_saudio.backend.src_buffer, 0x0, (size_t)buffer_size_bytes);
|
||||
_saudio.backend.src_buffer = (float*) _saudio_malloc_clear((size_t)buffer_size_bytes);
|
||||
}
|
||||
|
||||
/* Create engine */
|
||||
const SLEngineOption opts[] = { SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE };
|
||||
const SLEngineOption opts[] = { { SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE } };
|
||||
if (slCreateEngine(&_saudio.backend.engine_obj, 1, opts, 0, NULL, NULL ) != SL_RESULT_SUCCESS) {
|
||||
SOKOL_LOG("sokol_audio opensles: slCreateEngine failed");
|
||||
SAUDIO_LOG("sokol_audio opensles: slCreateEngine failed");
|
||||
_saudio_backend_shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
(*_saudio.backend.engine_obj)->Realize(_saudio.backend.engine_obj, SL_BOOLEAN_FALSE);
|
||||
if ((*_saudio.backend.engine_obj)->GetInterface(_saudio.backend.engine_obj, SL_IID_ENGINE, &_saudio.backend.engine) != SL_RESULT_SUCCESS) {
|
||||
SOKOL_LOG("sokol_audio opensles: GetInterface->Engine failed");
|
||||
SAUDIO_LOG("sokol_audio opensles: GetInterface->Engine failed");
|
||||
_saudio_backend_shutdown();
|
||||
return false;
|
||||
}
|
||||
@@ -2003,14 +2137,14 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
|
||||
if( (*_saudio.backend.engine)->CreateOutputMix(_saudio.backend.engine, &_saudio.backend.output_mix_obj, 1, ids, req) != SL_RESULT_SUCCESS)
|
||||
{
|
||||
SOKOL_LOG("sokol_audio opensles: CreateOutputMix failed");
|
||||
SAUDIO_LOG("sokol_audio opensles: CreateOutputMix failed");
|
||||
_saudio_backend_shutdown();
|
||||
return false;
|
||||
}
|
||||
(*_saudio.backend.output_mix_obj)->Realize(_saudio.backend.output_mix_obj, SL_BOOLEAN_FALSE);
|
||||
|
||||
if((*_saudio.backend.output_mix_obj)->GetInterface(_saudio.backend.output_mix_obj, SL_IID_VOLUME, &_saudio.backend.output_mix_vol) != SL_RESULT_SUCCESS) {
|
||||
SOKOL_LOG("sokol_audio opensles: GetInterface->OutputMixVol failed");
|
||||
SAUDIO_LOG("sokol_audio opensles: GetInterface->OutputMixVol failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2091,7 +2225,8 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||
SOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) {
|
||||
SOKOL_ASSERT(!_saudio.valid);
|
||||
SOKOL_ASSERT(desc);
|
||||
memset(&_saudio, 0, sizeof(_saudio));
|
||||
SOKOL_ASSERT((desc->allocator.alloc && desc->allocator.free) || (!desc->allocator.alloc && !desc->allocator.free));
|
||||
_saudio_clear(&_saudio, sizeof(_saudio));
|
||||
_saudio.desc = *desc;
|
||||
_saudio.stream_cb = desc->stream_cb;
|
||||
_saudio.stream_userdata_cb = desc->stream_userdata_cb;
|
||||
@@ -2108,7 +2243,7 @@ SOKOL_API_IMPL void saudio_setup(const saudio_desc* desc) {
|
||||
the requested packet size
|
||||
*/
|
||||
if (0 != (_saudio.buffer_frames % _saudio.packet_frames)) {
|
||||
SOKOL_LOG("sokol_audio.h: actual backend buffer size isn't multiple of requested packet size");
|
||||
SAUDIO_LOG("sokol_audio.h: actual backend buffer size isn't multiple of requested packet size");
|
||||
_saudio_backend_shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user