X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fmixer%2Faudio%2Faudio_mixer.cpp;h=29a89c7609c9283c639737e41c77424fdcddc4a3;hb=9ab62c607612a8e930df9302aa52f33c34d125dd;hp=94f099c1e9afd278acf2106bdfc59c1f931f885b;hpb=56ca215d1b171b11f7307dbcd659e3acec1ab7b7;p=casparcg diff --git a/core/mixer/audio/audio_mixer.cpp b/core/mixer/audio/audio_mixer.cpp index 94f099c1e..29a89c760 100644 --- a/core/mixer/audio/audio_mixer.cpp +++ b/core/mixer/audio/audio_mixer.cpp @@ -62,7 +62,7 @@ struct audio_item }; typedef cache_aligned_vector audio_buffer_ps; - + struct audio_stream { audio_transform prev_transform; @@ -92,7 +92,7 @@ public: graph_->set_color("audio-clipping", diagnostics::color(0.3f, 0.6f, 0.3f)); transform_stack_.push(core::audio_transform()); } - + void push(const frame_transform& transform) { transform_stack_.push(transform_stack_.top()*transform.audio_transform); @@ -111,15 +111,10 @@ public: if(item.transform.is_still) item.transform.volume = 0.0; - - items_.push_back(std::move(item)); - } - void begin(const core::audio_transform& transform) - { - transform_stack_.push(transform_stack_.top()*transform); + items_.push_back(std::move(item)); } - + void pop() { transform_stack_.pop(); @@ -136,20 +131,19 @@ public: } audio_buffer mix(const video_format_desc& format_desc, const audio_channel_layout& channel_layout) - { + { if(format_desc_ != format_desc || channel_layout_ != channel_layout) { audio_streams_.clear(); audio_cadence_ = format_desc.audio_cadence; format_desc_ = format_desc; channel_layout_ = channel_layout; - } - + } + std::map next_audio_streams; - std::vector used_tags; for (auto& item : items_) - { + { audio_buffer_ps next_audio; std::unique_ptr channel_remapper; bool remapping_failed = false; @@ -159,20 +153,23 @@ public: auto tag = item.tag; - if(boost::range::find(used_tags, tag) != used_tags.end()) - continue; - - used_tags.push_back(tag); + auto it = next_audio_streams.find(tag); + bool found = it != next_audio_streams.end(); + + if (!found) + { + it = audio_streams_.find(tag); + found = it != audio_streams_.end(); + } - const auto it = audio_streams_.find(tag); - if (it != audio_streams_.end()) + if (found) { prev_transform = it->second.prev_transform; next_audio = std::move(it->second.audio_data); channel_remapper = std::move(it->second.channel_remapper); remapping_failed = it->second.remapping_failed; } - + if (remapping_failed) { CASPAR_LOG(trace) << "[audio_mixer] audio channel remapping already failed for stream."; @@ -181,12 +178,13 @@ public: } // Skip it if there is no existing audio stream and item has no audio-data. - if(it == audio_streams_.end() && item.audio_data.empty()) + if(!found && item.audio_data.empty()) continue; if (item.channel_layout == audio_channel_layout::invalid()) { - CASPAR_LOG(debug) << "[audio_mixer] invalid audio channel layout for item"; + CASPAR_LOG(warning) << "[audio_mixer] invalid audio channel layout for item"; + next_audio_streams[tag].remapping_failed = true; continue; } @@ -212,13 +210,13 @@ public: // TODO: Move volume mixing into code below, in order to support audio sample counts not corresponding to frame audio samples. auto alpha = (next_volume-prev_volume)/static_cast(item.audio_data.size()/channel_layout_.num_channels); - + for(size_t n = 0; n < item.audio_data.size(); ++n) { auto sample_multiplier = (prev_volume + (n / channel_layout_.num_channels) * alpha); next_audio.push_back(item.audio_data.data()[n] * sample_multiplier); - } - + } + next_audio_streams[tag].prev_transform = std::move(next_transform); // Store all active tags, inactive tags will be removed at the end. next_audio_streams[tag].audio_data = std::move(next_audio); next_audio_streams[tag].channel_remapper = std::move(channel_remapper); @@ -230,8 +228,8 @@ public: items_.clear(); audio_streams_ = std::move(next_audio_streams); - - if(audio_streams_.empty()) + + if(audio_streams_.empty()) audio_streams_[nullptr].audio_data = audio_buffer_ps(audio_size(audio_cadence_.front()), 0.0); { // sanity check @@ -244,10 +242,10 @@ public: }) .count(); - if(nb_invalid_streams > 0) - CASPAR_LOG(trace) << "[audio_mixer] Incorrect frame audio cadence detected."; + if(nb_invalid_streams > 0) + CASPAR_LOG(trace) << "[audio_mixer] Incorrect frame audio cadence detected."; } - + audio_buffer_ps result_ps(audio_size(audio_cadence_.front()), 0.0); for (auto& stream : audio_streams_ | boost::adaptors::map_values) { @@ -262,10 +260,10 @@ public: auto out = boost::range::transform(result_ps, stream.audio_data, std::begin(result_ps), std::plus()); stream.audio_data.erase(std::begin(stream.audio_data), std::begin(stream.audio_data) + std::distance(std::begin(result_ps), out)); - } - + } + boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1); - + auto result_owner = spl::make_shared(); auto& result = *result_owner; result.reserve(result_ps.size()); @@ -290,7 +288,7 @@ public: if (clipping) graph_->set_tag(diagnostics::tag_severity::WARNING, "audio-clipping"); - + const int num_channels = channel_layout_.num_channels; monitor_subject_ << monitor::message("/nb_channels") % num_channels;