mirror of
https://github.com/bjornbytes/lovr.git
synced 2024-07-04 21:43:34 +00:00
Enforce strict limit of 64 active sources;
If 64 sources are playing and a new one is started, Source:play will return false. Instead of a linked list, a static list of 64 Sources is used. Bit scanning intrinsics are used to efficiently iterate the list, using a mask (still deciding on this).
This commit is contained in:
parent
4580107023
commit
75fda2336f
|
@ -14,11 +14,13 @@
|
||||||
#define LOVR_THREAD_LOCAL __declspec(thread)
|
#define LOVR_THREAD_LOCAL __declspec(thread)
|
||||||
#define LOVR_ALIGN(n) __declspec(align(n))
|
#define LOVR_ALIGN(n) __declspec(align(n))
|
||||||
#define LOVR_RESTRICT __restrict
|
#define LOVR_RESTRICT __restrict
|
||||||
|
#define LOVR_CTZLL _tzcnt_u64
|
||||||
#else
|
#else
|
||||||
#define LOVR_NORETURN __attribute__((noreturn))
|
#define LOVR_NORETURN __attribute__((noreturn))
|
||||||
#define LOVR_THREAD_LOCAL __thread
|
#define LOVR_THREAD_LOCAL __thread
|
||||||
#define LOVR_ALIGN(n) __attribute__((aligned(n)))
|
#define LOVR_ALIGN(n) __attribute__((aligned(n)))
|
||||||
#define LOVR_RESTRICT restrict
|
#define LOVR_RESTRICT restrict
|
||||||
|
#define LOVR_CTZLL __builtin_ctzll
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
|
|
|
@ -15,12 +15,11 @@ static const ma_format miniaudioFormats[] = {
|
||||||
#define OUTPUT_FORMAT SAMPLE_F32
|
#define OUTPUT_FORMAT SAMPLE_F32
|
||||||
#define OUTPUT_CHANNELS 2
|
#define OUTPUT_CHANNELS 2
|
||||||
#define CAPTURE_CHANNELS 1
|
#define CAPTURE_CHANNELS 1
|
||||||
#define MAX_SOURCES 64
|
|
||||||
#define BUFFER_SIZE 256
|
#define BUFFER_SIZE 256
|
||||||
|
|
||||||
struct Source {
|
struct Source {
|
||||||
uint32_t ref;
|
uint32_t ref;
|
||||||
Source* next;
|
uint32_t index;
|
||||||
Sound* sound;
|
Sound* sound;
|
||||||
ma_data_converter* converter;
|
ma_data_converter* converter;
|
||||||
intptr_t spatializerMemo;
|
intptr_t spatializerMemo;
|
||||||
|
@ -28,7 +27,6 @@ struct Source {
|
||||||
float volume;
|
float volume;
|
||||||
float position[4];
|
float position[4];
|
||||||
float orientation[4];
|
float orientation[4];
|
||||||
bool tracked;
|
|
||||||
bool playing;
|
bool playing;
|
||||||
bool looping;
|
bool looping;
|
||||||
bool spatial;
|
bool spatial;
|
||||||
|
@ -39,7 +37,8 @@ static struct {
|
||||||
ma_context context;
|
ma_context context;
|
||||||
ma_device devices[2];
|
ma_device devices[2];
|
||||||
ma_mutex lock;
|
ma_mutex lock;
|
||||||
Source* sources;
|
Source* sources[MAX_SOURCES];
|
||||||
|
uint64_t sourceMask;
|
||||||
Sound* captureStream;
|
Sound* captureStream;
|
||||||
arr_t(ma_data_converter*) converters;
|
arr_t(ma_data_converter*) converters;
|
||||||
float position[4];
|
float position[4];
|
||||||
|
@ -82,10 +81,15 @@ static void onPlayback(ma_device* device, void* out, const void* in, uint32_t co
|
||||||
memset(dst, 0, sizeof(state.leftovers));
|
memset(dst, 0, sizeof(state.leftovers));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Source** list = &state.sources, *source = *list; source != NULL; source = *list) {
|
// Biterate the source mask to iterate over all active Sources
|
||||||
|
for (uint64_t mask = state.sourceMask, lobit = mask & -mask; mask != 0; mask ^= lobit, lobit = mask & -mask) {
|
||||||
|
uint32_t index = LOVR_CTZLL(mask);
|
||||||
|
Source* source = state.sources[index];
|
||||||
|
|
||||||
if (!source->playing) {
|
if (!source->playing) {
|
||||||
*list = source->next;
|
source->index = ~0u;
|
||||||
source->tracked = false;
|
state.sources[index] = NULL;
|
||||||
|
state.sourceMask &= ~(1ull << index);
|
||||||
lovrRelease(source, lovrSourceDestroy);
|
lovrRelease(source, lovrSourceDestroy);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -135,8 +139,6 @@ static void onPlayback(ma_device* device, void* out, const void* in, uint32_t co
|
||||||
for (uint32_t i = 0; i < OUTPUT_CHANNELS * BUFFER_SIZE; i++) {
|
for (uint32_t i = 0; i < OUTPUT_CHANNELS * BUFFER_SIZE; i++) {
|
||||||
dst[i] += src[i] * volume;
|
dst[i] += src[i] * volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
list = &source->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tail
|
// Tail
|
||||||
|
@ -326,6 +328,7 @@ Source* lovrSourceCreate(Sound* sound, bool spatial) {
|
||||||
Source* source = calloc(1, sizeof(Source));
|
Source* source = calloc(1, sizeof(Source));
|
||||||
lovrAssert(source, "Out of memory");
|
lovrAssert(source, "Out of memory");
|
||||||
source->ref = 1;
|
source->ref = 1;
|
||||||
|
source->index = ~0u;
|
||||||
source->sound = sound;
|
source->sound = sound;
|
||||||
lovrRetain(source->sound);
|
lovrRetain(source->sound);
|
||||||
|
|
||||||
|
@ -386,15 +389,21 @@ void lovrSourceDestroy(void* ref) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrSourcePlay(Source* source) {
|
bool lovrSourcePlay(Source* source) {
|
||||||
|
if (state.sourceMask == ~0ull) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ma_mutex_lock(&state.lock);
|
ma_mutex_lock(&state.lock);
|
||||||
|
|
||||||
source->playing = true;
|
source->playing = true;
|
||||||
|
|
||||||
if (!source->tracked) {
|
// If the source isn't tracked, set its index to the right-most zero bit in the mask
|
||||||
|
if (source->index == ~0u) {
|
||||||
|
uint32_t index = state.sourceMask ? LOVR_CTZLL(~state.sourceMask) : 0;
|
||||||
|
state.sourceMask |= (1ull << index);
|
||||||
|
state.sources[index] = source;
|
||||||
|
source->index = index;
|
||||||
lovrRetain(source);
|
lovrRetain(source);
|
||||||
source->tracked = true;
|
|
||||||
source->next = state.sources;
|
|
||||||
state.sources = source;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ma_mutex_unlock(&state.lock);
|
ma_mutex_unlock(&state.lock);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PLAYBACK_SAMPLE_RATE 48000
|
#define PLAYBACK_SAMPLE_RATE 48000
|
||||||
|
#define MAX_SOURCES 64
|
||||||
|
|
||||||
struct Sound;
|
struct Sound;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue