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