diff --git a/Outputs/Speaker/Implementation/CompoundSource.hpp b/Outputs/Speaker/Implementation/CompoundSource.hpp index 6bc77220a..a4a9f2251 100644 --- a/Outputs/Speaker/Implementation/CompoundSource.hpp +++ b/Outputs/Speaker/Implementation/CompoundSource.hpp @@ -26,6 +26,20 @@ template constexpr bool is_stereo() { return is_stereo; } +/// @returns @c true if the variadic template arguments are ordered as all stereo sources followed by +/// all mono; @c false otherwise. +template constexpr bool are_properly_ordered() { + bool is_ordered = true; + bool is_stereo = true; + ([&] { + if(S::is_stereo && !is_stereo) { + is_ordered = false; + } + is_stereo &= S::is_stereo; + }(), ...); + return is_ordered; +} + /*! A CompoundSource adds together the sound generated by multiple individual SampleSources. An owner may optionally assign relative volumes. @@ -59,7 +73,7 @@ template class CompoundSource: static constexpr bool is_stereo = S::is_stereo || CompoundSourceHolder::is_stereo; - // TODO: fix below for mixed mono/stereo sources. + // TODO: fix below for potential stereo -> mono conversion. template void get_samples(std::size_t number_of_samples, typename SampleT::type *target) { // Get the rest of the output. @@ -121,6 +135,9 @@ template class CompoundSource: }; public: + // To ensure at most one mono to stereo conversion, require appropriate source ordering. + static_assert(are_properly_ordered(), "Sources should be listed with all stereo sources before all mono sources"); + CompoundSource(T &... sources) : source_holder_(sources...) { // Default: give all sources equal volume. const auto volume = 1.0 / double(source_holder_.size());