1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Makes CompoundSource mono/stereo-aware.

This commit is contained in:
Thomas Harte 2020-02-16 18:45:36 -05:00
parent 50d356be2f
commit 545a6177bb
2 changed files with 31 additions and 9 deletions

View File

@ -32,6 +32,7 @@ class SCC: public ::Outputs::Speaker::SampleSource {
/// As per ::SampleSource; provides audio output.
void get_samples(std::size_t number_of_samples, std::int16_t *target);
void set_sample_volume_range(std::int16_t range);
static constexpr bool get_is_stereo() { return false; }
/// Writes to the SCC.
void write(uint16_t address, uint8_t value);

View File

@ -33,7 +33,7 @@ template <typename... T> class CompoundSource:
}
void get_samples(std::size_t number_of_samples, std::int16_t *target) {
source_holder_.get_samples(number_of_samples, target);
source_holder_.template get_samples<get_is_stereo()>(number_of_samples, target);
}
void skip_samples(const std::size_t number_of_samples) {
@ -66,7 +66,7 @@ template <typename... T> class CompoundSource:
template <typename... S> class CompoundSourceHolder: public Outputs::Speaker::SampleSource {
public:
void get_samples(std::size_t number_of_samples, std::int16_t *target) {
template <bool output_stereo> void get_samples(std::size_t number_of_samples, std::int16_t *target) {
std::memset(target, 0, sizeof(std::int16_t) * number_of_samples);
}
@ -85,18 +85,39 @@ template <typename... T> class CompoundSource:
public:
CompoundSourceHolder(S &source, R &...next) : source_(source), next_source_(next...) {}
void get_samples(std::size_t number_of_samples, std::int16_t *target) {
template <bool output_stereo> void get_samples(std::size_t number_of_samples, std::int16_t *target) {
// Get the rest of the output.
next_source_.template get_samples<output_stereo>(number_of_samples, target);
if(source_.is_zero_level()) {
// This component is currently outputting silence; therefore don't add anything to the output
// audio — just pass the call onward.
source_.skip_samples(number_of_samples);
next_source_.get_samples(number_of_samples, target);
return;
}
// Get this component's output.
auto buffer_size = number_of_samples * (output_stereo ? 2 : 1);
int16_t local_samples[buffer_size];
source_.get_samples(number_of_samples, local_samples);
// Merge it in; furthermore if total output is stereo but this source isn't,
// map it to stereo.
if constexpr (output_stereo == S::get_is_stereo()) {
while(buffer_size--) {
target[buffer_size] += local_samples[buffer_size];
}
} else {
int16_t next_samples[number_of_samples];
next_source_.get_samples(number_of_samples, next_samples);
source_.get_samples(number_of_samples, target);
while(number_of_samples--) {
target[number_of_samples] += next_samples[number_of_samples];
// 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?
}
void skip_samples(const std::size_t number_of_samples) {