1
0
Fork 0
mirror of https://github.com/bjornbytes/lovr.git synced 2024-07-02 12:33:52 +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:
bjorn 2021-02-16 21:14:40 -07:00 committed by Bjorn
parent 4580107023
commit 75fda2336f
3 changed files with 25 additions and 13 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;