mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Reintroduce mono to stereo conversion.
This commit is contained in:
parent
25085cb5af
commit
3a208460e2
@ -49,8 +49,10 @@ template <typename... T> class CompoundSource:
|
|||||||
private:
|
private:
|
||||||
template <typename... S> class CompoundSourceHolder {
|
template <typename... S> class CompoundSourceHolder {
|
||||||
public:
|
public:
|
||||||
template <bool output_stereo> void get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
template <bool output_stereo>
|
||||||
std::fill(target, target + number_of_samples, 0);
|
void get_samples(std::size_t number_of_samples, typename SampleT<output_stereo>::type *target) {
|
||||||
|
// Default-construct all samples, to fill with silence.
|
||||||
|
std::fill(target, target + number_of_samples, typename SampleT<output_stereo>::type());
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_scaled_volume_range(int16_t, double *, double) {}
|
void set_scaled_volume_range(int16_t, double *, double) {}
|
||||||
@ -73,9 +75,27 @@ template <typename... T> class CompoundSource:
|
|||||||
|
|
||||||
static constexpr bool is_stereo = S::is_stereo || CompoundSourceHolder<R...>::is_stereo;
|
static constexpr bool is_stereo = S::is_stereo || CompoundSourceHolder<R...>::is_stereo;
|
||||||
|
|
||||||
// TODO: fix below for potential stereo -> mono conversion.
|
|
||||||
template <bool output_stereo>
|
template <bool output_stereo>
|
||||||
void get_samples(std::size_t number_of_samples, typename SampleT<output_stereo>::type *target) {
|
void get_samples(std::size_t number_of_samples, typename ::Outputs::Speaker::SampleT<output_stereo>::type *target) {
|
||||||
|
|
||||||
|
// If this is the step at which a mono-to-stereo adaptation happens, apply it.
|
||||||
|
if constexpr (output_stereo && !S::is_stereo) {
|
||||||
|
// There'll be only one place in the chain that this conversion happens, but it'll
|
||||||
|
// happen there often. So avoid continuously reallocating.
|
||||||
|
if(conversion_source_.size() < number_of_samples) {
|
||||||
|
conversion_source_.resize(number_of_samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the conversion buffer with this source and all below.
|
||||||
|
get_samples<false>(number_of_samples, conversion_source_.data());
|
||||||
|
|
||||||
|
// Map up and return.
|
||||||
|
for(std::size_t c = 0; c < number_of_samples; c++) {
|
||||||
|
target[c].left = target[c].right = conversion_source_[c];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the rest of the output.
|
// Get the rest of the output.
|
||||||
next_source_.template get_samples<output_stereo>(number_of_samples, target);
|
next_source_.template get_samples<output_stereo>(number_of_samples, target);
|
||||||
|
|
||||||
@ -87,24 +107,12 @@ template <typename... T> class CompoundSource:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get this component's output.
|
// Get this component's output.
|
||||||
auto buffer_size = number_of_samples * (output_stereo ? 2 : 1);
|
typename SampleT<output_stereo>::type local_samples[number_of_samples];
|
||||||
typename SampleT<is_stereo>::type local_samples[number_of_samples];
|
|
||||||
source_.get_samples(number_of_samples, local_samples);
|
source_.get_samples(number_of_samples, local_samples);
|
||||||
|
|
||||||
// Merge it in; furthermore if total output is stereo but this source isn't,
|
// Merge it in.
|
||||||
// map it to stereo.
|
while(number_of_samples--) {
|
||||||
if constexpr (output_stereo == S::is_stereo) {
|
target[number_of_samples] += local_samples[number_of_samples];
|
||||||
while(buffer_size--) {
|
|
||||||
target[buffer_size] += local_samples[buffer_size];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This will happen only if mapping from mono to stereo, never in the
|
|
||||||
// other direction, because the compound source outputs stereo if any
|
|
||||||
// subcomponent does. So it outputs mono only if no stereo devices are
|
|
||||||
// in the mixing chain.
|
|
||||||
while(buffer_size--) {
|
|
||||||
target[buffer_size] += local_samples[buffer_size >> 1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: accelerate above?
|
// TODO: accelerate above?
|
||||||
@ -132,9 +140,12 @@ template <typename... T> class CompoundSource:
|
|||||||
private:
|
private:
|
||||||
S &source_;
|
S &source_;
|
||||||
CompoundSourceHolder<R...> next_source_;
|
CompoundSourceHolder<R...> next_source_;
|
||||||
|
std::vector<MonoSample> conversion_source_;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Sample = typename SampleT<::Outputs::Speaker::is_stereo<T...>()>::type;
|
||||||
|
|
||||||
// To ensure at most one mono to stereo conversion, require appropriate source ordering.
|
// To ensure at most one mono to stereo conversion, require appropriate source ordering.
|
||||||
static_assert(are_properly_ordered<T...>(), "Sources should be listed with all stereo sources before all mono sources");
|
static_assert(are_properly_ordered<T...>(), "Sources should be listed with all stereo sources before all mono sources");
|
||||||
|
|
||||||
@ -146,7 +157,7 @@ template <typename... T> class CompoundSource:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_samples(std::size_t number_of_samples, typename SampleT<::Outputs::Speaker::is_stereo<T...>()>::type *target) {
|
void get_samples(std::size_t number_of_samples, Sample *target) {
|
||||||
source_holder_.template get_samples<::Outputs::Speaker::is_stereo<T...>()>(number_of_samples, target);
|
source_holder_.template get_samples<::Outputs::Speaker::is_stereo<T...>()>(number_of_samples, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,9 @@ namespace Outputs::Speaker {
|
|||||||
using MonoSample = int16_t;
|
using MonoSample = int16_t;
|
||||||
struct StereoSample {
|
struct StereoSample {
|
||||||
#if TARGET_RT_BIG_ENDIAN
|
#if TARGET_RT_BIG_ENDIAN
|
||||||
int16_t right, left;
|
int16_t right = 0, left = 0;
|
||||||
#else
|
#else
|
||||||
int16_t left, right;
|
int16_t left = 0, right = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
StereoSample() = default;
|
StereoSample() = default;
|
||||||
|
Loading…
Reference in New Issue
Block a user