diff --git a/libobs/obs-audio-controls.c b/libobs/obs-audio-controls.c index 7eaae1bfff80299a15c7191db6b98a8cc577a92e..dd96cb348cb8bcbcf03690ea2c93567fc03b2428 100644 --- a/libobs/obs-audio-controls.c +++ b/libobs/obs-audio-controls.c @@ -283,16 +283,22 @@ static void volmeter_source_destroyed(void *vptr, calldata_t *calldata) obs_volmeter_detach_source(volmeter); } -static void volmeter_sum_and_max(float *data, size_t frames, +/* TODO: Separate for individual channels */ +static void volmeter_sum_and_max(float *data[MAX_AV_PLANES], size_t frames, float *sum, float *max) { float s = *sum; float m = *max; - for (float *c = data; c < data + frames; ++c) { - const float pow = *c * *c; - s += pow; - m = (m > pow) ? m : pow; + for (size_t plane = 0; plane < MAX_AV_PLANES; plane++) { + if (!data[plane]) + break; + + for (float *c = data[plane]; c < data[plane] + frames; ++c) { + const float pow = *c * *c; + s += pow; + m = (m > pow) ? m : pow; + } } *sum = s; @@ -340,23 +346,29 @@ static bool volmeter_process_audio_data(obs_volmeter_t *volmeter, { bool updated = false; size_t frames = 0; - size_t samples = 0; size_t left = data->frames; - float *adata = (float *) data->data[0]; + float *adata[MAX_AV_PLANES]; + + for (size_t i = 0; i < MAX_AV_PLANES; i++) + adata[i] = (float*)data->data[i]; while (left) { frames = (volmeter->ival_frames + left > volmeter->update_frames) ? volmeter->update_frames - volmeter->ival_frames : left; - samples = frames * volmeter->channels; - volmeter_sum_and_max(adata, samples, &volmeter->ival_sum, + volmeter_sum_and_max(adata, frames, &volmeter->ival_sum, &volmeter->ival_max); volmeter->ival_frames += (unsigned int)frames; left -= frames; - adata += samples; + + for (size_t i = 0; i < MAX_AV_PLANES; i++) { + if (!adata[i]) + break; + adata[i] += frames; + } /* break if we did not reach the end of the interval */ if (volmeter->ival_frames != volmeter->update_frames) diff --git a/libobs/obs-source.c b/libobs/obs-source.c index b86ea5def95b9197b2c937b8df417c0e42682501..a114409b98b47659c12ae1d308779eef6782a123 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -1637,36 +1637,12 @@ static void downmix_to_mono_planar(struct obs_source *source, uint32_t frames) } } -static void downmix_to_mono_interleaved(struct obs_source *source, - uint32_t frames) -{ - size_t channels = audio_output_get_channels(obs->audio.audio); - const float channels_i = 1.0f / (float)channels; - float *data = (float*)source->audio_data.data[0]; - - for (uint32_t frame = 0; frame < frames; frame++) { - size_t pos = frame * channels; - - for (size_t channel = 1; channel < channels; channel++) - data[pos] += data[pos + channel]; - } - - for (uint32_t frame = 0; frame < frames; frame++) - data[frame * channels] *= channels_i; - - for (uint32_t frame = 0; frame < frames; frame++) { - size_t pos = frame * channels; - - for (size_t channel = 1; channel < channels; channel++) - data[pos + channel] = data[pos]; - } -} - /* resamples/remixes new audio to the designated main audio output format */ static void process_audio(obs_source_t *source, const struct obs_source_audio *audio) { uint32_t frames = audio->frames; + bool mono_output; if (source->sample_info.samples_per_sec != audio->samples_per_sec || source->sample_info.format != audio->format || @@ -1693,12 +1669,10 @@ static void process_audio(obs_source_t *source, audio->timestamp); } - if ((source->flags & OBS_SOURCE_FLAG_FORCE_MONO) != 0) { - if (is_audio_planar(source->sample_info.format)) - downmix_to_mono_planar(source, frames); - else - downmix_to_mono_interleaved(source, frames); - } + mono_output = audio_output_get_channels(obs->audio.audio) == 1; + + if (!mono_output && (source->flags & OBS_SOURCE_FLAG_FORCE_MONO) != 0) + downmix_to_mono_planar(source, frames); } void obs_source_output_audio(obs_source_t *source, diff --git a/libobs/obs.c b/libobs/obs.c index 2e441cc4d2245ebf30dc08e557366f841b450e5f..fca52a933a8899fb545baeb5e6e52b3b747b2960 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -752,8 +752,10 @@ int obs_reset_video(struct obs_video_info *ovi) return obs_init_video(ovi); } -bool obs_reset_audio(struct audio_output_info *ai) +bool obs_reset_audio(const struct obs_audio_info *oai) { + struct audio_output_info ai; + if (!obs) return false; /* don't allow changing of audio settings if active. */ @@ -761,18 +763,24 @@ bool obs_reset_audio(struct audio_output_info *ai) return false; obs_free_audio(); - if(!ai) + if (!oai) return true; + ai.name = "Audio"; + ai.samples_per_sec = oai->samples_per_sec; + ai.format = AUDIO_FORMAT_FLOAT_PLANAR; + ai.speakers = oai->speakers; + ai.buffer_ms = oai->buffer_ms; + blog(LOG_INFO, "audio settings reset:\n" "\tsamples per sec: %d\n" "\tspeakers: %d\n" "\tbuffering (ms): %d\n", - (int)ai->samples_per_sec, - (int)ai->speakers, - (int)ai->buffer_ms); + (int)ai.samples_per_sec, + (int)ai.speakers, + (int)ai.buffer_ms); - return obs_init_audio(ai); + return obs_init_audio(&ai); } bool obs_get_video_info(struct obs_video_info *ovi) @@ -803,17 +811,19 @@ bool obs_get_video_info(struct obs_video_info *ovi) return true; } -bool obs_get_audio_info(struct audio_output_info *aoi) +bool obs_get_audio_info(struct obs_audio_info *oai) { struct obs_core_audio *audio = &obs->audio; const struct audio_output_info *info; - if (!obs || !audio->audio) + if (!obs || !oai || !audio->audio) return false; info = audio_output_get_info(audio->audio); - memcpy(aoi, info, sizeof(struct audio_output_info)); + oai->samples_per_sec = info->samples_per_sec; + oai->speakers = info->speakers; + oai->buffer_ms = info->buffer_ms; return true; } diff --git a/libobs/obs.h b/libobs/obs.h index e6208a492fa5dac49c3fe01f92880cb5517515fb..df4424305c8ee439eef27328b1b44b4bf3eaddbd 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -172,6 +172,15 @@ struct obs_video_info { enum obs_scale_type scale_type; /**< How to scale if scaling */ }; +/** + * Audio initialization structure + */ +struct obs_audio_info { + uint32_t samples_per_sec; + enum speaker_layout speakers; + uint64_t buffer_ms; +}; + /** * Sent to source filters via the filter_audio callback to allow filtering of * audio data @@ -274,13 +283,13 @@ EXPORT int obs_reset_video(struct obs_video_info *ovi); * * @note Cannot reset base audio if an output is currently active. */ -EXPORT bool obs_reset_audio(struct audio_output_info *ai); +EXPORT bool obs_reset_audio(const struct obs_audio_info *oai); /** Gets the current video settings, returns false if no video */ EXPORT bool obs_get_video_info(struct obs_video_info *ovi); /** Gets the current audio settings, returns false if no audio */ -EXPORT bool obs_get_audio_info(struct audio_output_info *ai); +EXPORT bool obs_get_audio_info(struct obs_audio_info *oai); /** * Opens a plugin module directly from a specific path. diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index 69870e3c306b4c3e1eab99b56b5dbc3a83fee65a..8b6e519d6f58a43f73fd60c57c094baa31f2f49a 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -1539,10 +1539,7 @@ int OBSBasic::ResetVideo() bool OBSBasic::ResetAudio() { - struct audio_output_info ai; - ai.name = "Main Audio Track"; - ai.format = AUDIO_FORMAT_FLOAT; - + struct obs_audio_info ai; ai.samples_per_sec = config_get_uint(basicConfig, "Audio", "SampleRate"); diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c index bec95fb6c3820816396e1c8b7d7e66aaa8ce27e3..884c4e311faea8815e983a775ddb95e938399e06 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c @@ -287,7 +287,7 @@ static bool open_audio_codec(struct ffmpeg_data *data) static bool create_audio_stream(struct ffmpeg_data *data) { AVCodecContext *context; - struct audio_output_info aoi; + struct obs_audio_info aoi; if (!obs_get_audio_info(&aoi)) { blog(LOG_WARNING, "No active audio");