#include <core/mixer/write_frame.h>\r
#include <core/producer/frame/frame_transform.h>\r
#include <common/diagnostics/graph.h>\r
+#include "audio_util.h"\r
\r
#include <tbb/cache_aligned_allocator.h>\r
\r
\r
struct audio_stream\r
{\r
- frame_transform prev_transform;\r
- audio_buffer_ps audio_data;\r
+ frame_transform prev_transform;\r
+ audio_buffer_ps audio_data;\r
};\r
\r
struct audio_mixer::implementation\r
std::vector<audio_item> items_;\r
std::vector<size_t> audio_cadence_;\r
video_format_desc format_desc_;\r
+ channel_layout channel_layout_;\r
float master_volume_;\r
float previous_master_volume_;\r
\r
audio_item item;\r
item.tag = frame.tag();\r
item.transform = transform_stack_.top();\r
- item.audio_data = std::move(frame.audio_data()); // Note: We don't need to care about upper/lower since audio_data is removed/moved from the last field.\r
+\r
+ if (needs_rearranging(frame.get_channel_layout(), channel_layout_))\r
+ {\r
+ auto src_view = frame.get_multichannel_view();\r
+ \r
+ audio_buffer rearranged_buffer;\r
+ rearranged_buffer.resize(\r
+ src_view.num_samples() * channel_layout_.num_channels);\r
+\r
+ auto dst_view = make_multichannel_view<int32_t>(\r
+ rearranged_buffer.begin(),\r
+ rearranged_buffer.end(),\r
+ channel_layout_);\r
+\r
+ bool rearrange_success = rearrange_or_rearrange_and_mix(\r
+ src_view, dst_view, default_mix_config_repository());\r
+\r
+ if (!rearrange_success)\r
+ {\r
+ failed_rearrange(item.tag, src_view.channel_layout());\r
+ }\r
+\r
+ item.audio_data = std::move(rearranged_buffer);\r
+ }\r
+ else\r
+ {\r
+ item.audio_data = std::move(frame.audio_data()); // Note: We don't need to care about upper/lower since audio_data is removed/moved from the last field.\r
+ }\r
\r
items_.push_back(std::move(item)); \r
}\r
master_volume_ = volume;\r
}\r
\r
- audio_buffer mix(const video_format_desc& format_desc)\r
+ audio_buffer mix(const video_format_desc& format_desc, const channel_layout& layout)\r
{ \r
if(format_desc_ != format_desc)\r
{\r
audio_streams_.clear();\r
audio_cadence_ = format_desc.audio_cadence;\r
format_desc_ = format_desc;\r
- } \r
+ channel_layout_ = layout;\r
+ }\r
\r
std::map<const void*, audio_stream> next_audio_streams;\r
\r
const float prev_volume = static_cast<float>(prev_transform.volume) * previous_master_volume_;\r
const float next_volume = static_cast<float>(next_transform.volume) * master_volume_;\r
\r
- auto alpha = (next_volume-prev_volume)/static_cast<float>(item.audio_data.size()/format_desc.audio_channels);\r
+ auto alpha = (next_volume-prev_volume)/static_cast<float>(item.audio_data.size()/channel_layout_.num_channels);\r
\r
for(size_t n = 0; n < item.audio_data.size(); ++n)\r
{\r
- auto sample_multiplier = (prev_volume + (n/format_desc_.audio_channels) * alpha);\r
+ auto sample_multiplier = (prev_volume + (n/channel_layout_.num_channels) * alpha);\r
next_audio.push_back(item.audio_data[n] * sample_multiplier);\r
}\r
\r
\r
size_t audio_size(size_t num_samples) const\r
{\r
- return num_samples * format_desc_.audio_channels;\r
+ return num_samples * channel_layout_.num_channels;\r
+ }\r
+\r
+ void failed_rearrange(const void* tag, const channel_layout& layout)\r
+ {\r
+ if (audio_streams_.find(tag) != audio_streams_.end())\r
+ return; // We don't want to flood the logs.\r
+\r
+ CASPAR_LOG(warning)\r
+ << L"[audio_mixer] Could not satisfactory down/upmix from " \r
+ << layout.name << L" to " << channel_layout_.name \r
+ << L" because no mix config was found for " \r
+ << layout.layout_type << L" => " << channel_layout_.layout_type \r
+ << L". This might cause audio to be lost.";\r
}\r
};\r
\r
void audio_mixer::visit(core::write_frame& frame){impl_->visit(frame);}\r
void audio_mixer::end(){impl_->end();}\r
void audio_mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }\r
-audio_buffer audio_mixer::operator()(const video_format_desc& format_desc){return impl_->mix(format_desc);}\r
+audio_buffer audio_mixer::operator()(const video_format_desc& format_desc, const channel_layout& layout){return impl_->mix(format_desc, layout);}\r
\r
}}
\ No newline at end of file