From 9832a760b8425ad0dbaaf6f38ab5d4e6da993c1a Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sat, 7 Mar 2015 04:47:12 -0800 Subject: [PATCH] (API Change) Always use planar float audio output Core API functions changed: ----------------------------- EXPORT bool obs_reset_audio(struct audio_output_info *aoi); EXPORT bool obs_get_audio_info(struct audio_output_info *aoi); To: ----------------------------- EXPORT bool obs_reset_audio(const struct obs_audio_info *oai); EXPORT bool obs_get_audio_info(struct obs_audio_info *oai); Core structure added: ----------------------------- struct obs_audio_info { uint32_t samples_per_sec; enum speaker_layout speakers; uint64_t buffer_ms; }; Non-interleaved (planar) floating point output is standard with audio filtering, so to prevent audio filters from having to worry about different audio format implementations and for the sake consistency between user interfaces, make it so that audio is always set to non-interleaved floating point output. --- libobs/obs-audio-controls.c | 32 ++++++++++++++++------- libobs/obs-source.c | 36 ++++---------------------- libobs/obs.c | 28 +++++++++++++------- libobs/obs.h | 13 ++++++++-- obs/window-basic-main.cpp | 5 +--- plugins/obs-ffmpeg/obs-ffmpeg-output.c | 2 +- 6 files changed, 59 insertions(+), 57 deletions(-) diff --git a/libobs/obs-audio-controls.c b/libobs/obs-audio-controls.c index 7eaae1bff..dd96cb348 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 b86ea5def..a114409b9 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 2e441cc4d..fca52a933 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 e6208a492..df4424305 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 69870e3c3..8b6e519d6 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 bec95fb6c..884c4e311 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");