libobs: Mix audio of each source in a scene only once

This commit is contained in:
derrod
2024-04-14 13:49:43 +02:00
committed by Lain
parent c815d6ad61
commit 8a38e3375b
2 changed files with 76 additions and 10 deletions

View File

@@ -239,6 +239,7 @@ static void scene_destroy(void *data)
pthread_mutex_destroy(&scene->video_mutex);
pthread_mutex_destroy(&scene->audio_mutex);
da_free(scene->mix_sources);
bfree(scene);
}
@@ -1527,9 +1528,11 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
item = scene->first_item;
while (item) {
uint64_t source_ts;
size_t pos, count;
size_t pos;
bool apply_buf;
struct obs_source *source;
struct scene_source_mix *source_mix = NULL;
if (item->visible && transition_active(item->show_transition))
source = item->show_transition;
else if (!item->visible &&
@@ -1560,15 +1563,64 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
continue;
}
count = AUDIO_OUTPUT_FRAMES - pos;
if (!apply_buf && !item->visible &&
!transition_active(item->hide_transition)) {
item = item->next;
continue;
}
obs_source_get_audio_mix(source, &child_audio);
for (size_t i = 0; i < scene->mix_sources.num; i++) {
struct scene_source_mix *mix =
&scene->mix_sources.array[i];
if (mix->source == item->source) {
source_mix = mix;
break;
}
}
if (!source_mix) {
source_mix = da_push_back_new(scene->mix_sources);
source_mix->source = item->source;
source_mix->transition = source != item->source ? source
: NULL;
source_mix->apply_buf = apply_buf;
source_mix->pos = pos;
source_mix->count = AUDIO_OUTPUT_FRAMES - pos;
if (apply_buf) {
memcpy(source_mix->buf, buf,
sizeof(float) * source_mix->count);
}
} else {
/* Only transition audio if there are no
* non-transitioning scene items. */
if (source_mix->transition && source == item->source)
source_mix->transition = NULL;
/* Only apply buf to mix if all scene items for this
* source require it. */
source_mix->apply_buf = source_mix->apply_buf &&
apply_buf;
/* Update buf so that only highest value across all
* items is used. */
if (source_mix->apply_buf &&
memcmp(source_mix->buf, buf,
source_mix->count * sizeof(float)) != 0) {
for (size_t i = 0; i < source_mix->count; i++) {
if (buf[i] > source_mix->buf[i])
source_mix->buf[i] = buf[i];
}
}
}
item = item->next;
}
for (size_t i = 0; i < scene->mix_sources.num; i++) {
struct scene_source_mix *source_mix =
&scene->mix_sources.array[i];
obs_source_get_audio_mix(source_mix->transition
? source_mix->transition
: source_mix->source,
&child_audio);
for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
if ((mixers & (1 << mix)) == 0)
@@ -1578,17 +1630,20 @@ static bool scene_audio_render(void *data, uint64_t *ts_out,
float *out = audio_output->output[mix].data[ch];
float *in = child_audio.output[mix].data[ch];
if (apply_buf)
mix_audio_with_buf(out, in, buf, pos,
count);
if (source_mix->apply_buf)
mix_audio_with_buf(out, in,
source_mix->buf,
source_mix->pos,
source_mix->count);
else
mix_audio(out, in, pos, count);
mix_audio(out, in, source_mix->pos,
source_mix->count);
}
}
item = item->next;
}
da_clear(scene->mix_sources);
*ts_out = timestamp;
audio_unlock(scene);

View File

@@ -93,6 +93,15 @@ struct obs_scene_item {
struct obs_scene_item *next;
};
struct scene_source_mix {
obs_source_t *source;
obs_source_t *transition;
size_t pos;
size_t count;
bool apply_buf;
float buf[AUDIO_OUTPUT_FRAMES];
};
struct obs_scene {
struct obs_source *source;
@@ -106,4 +115,6 @@ struct obs_scene {
pthread_mutex_t video_mutex;
pthread_mutex_t audio_mutex;
struct obs_scene_item *first_item;
DARRAY(struct scene_source_mix) mix_sources;
};