mirror of
https://github.com/TomHarte/CLK.git
synced 2024-09-29 16:55:59 +00:00
Adds mixdown/up capability to Speaker.
To deal with occasions when the host machine just always is either mono or stereo, and the emulated machine must cope.
This commit is contained in:
parent
ea1c8a3b81
commit
90856a0e7a
@ -38,6 +38,7 @@ float MultiSpeaker::get_ideal_clock_rate_in_range(float minimum, float maximum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MultiSpeaker::set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) {
|
void MultiSpeaker::set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) {
|
||||||
|
is_stereo_ = stereo;
|
||||||
for(const auto &speaker: speakers_) {
|
for(const auto &speaker: speakers_) {
|
||||||
speaker->set_computed_output_rate(cycles_per_second, buffer_size, stereo);
|
speaker->set_computed_output_rate(cycles_per_second, buffer_size, stereo);
|
||||||
}
|
}
|
||||||
@ -53,7 +54,7 @@ void MultiSpeaker::speaker_did_complete_samples(Speaker *speaker, const std::vec
|
|||||||
std::lock_guard<std::mutex> lock_guard(front_speaker_mutex_);
|
std::lock_guard<std::mutex> lock_guard(front_speaker_mutex_);
|
||||||
if(speaker != front_speaker_) return;
|
if(speaker != front_speaker_) return;
|
||||||
}
|
}
|
||||||
did_complete_samples(this, buffer);
|
did_complete_samples(this, buffer, is_stereo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiSpeaker::speaker_did_change_input_clock(Speaker *speaker) {
|
void MultiSpeaker::speaker_did_change_input_clock(Speaker *speaker) {
|
||||||
|
@ -51,6 +51,8 @@ class MultiSpeaker: public Outputs::Speaker::Speaker, Outputs::Speaker::Speaker:
|
|||||||
Outputs::Speaker::Speaker *front_speaker_ = nullptr;
|
Outputs::Speaker::Speaker *front_speaker_ = nullptr;
|
||||||
Outputs::Speaker::Speaker::Delegate *delegate_ = nullptr;
|
Outputs::Speaker::Speaker::Delegate *delegate_ = nullptr;
|
||||||
std::mutex front_speaker_mutex_;
|
std::mutex front_speaker_mutex_;
|
||||||
|
|
||||||
|
bool is_stereo_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,11 @@
|
|||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = ""/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Master System/R-Type (NTSC).sms""
|
argument = ""/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Master System/R-Type (NTSC).sms""
|
||||||
isEnabled = "NO">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = ""/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Robocop.dsk""
|
argument = ""/Users/thomasharte/Library/Mobile Documents/com~apple~CloudDocs/Desktop/Soft/Amstrad CPC/Robocop.dsk""
|
||||||
isEnabled = "YES">
|
isEnabled = "NO">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = "--speed=5"
|
argument = "--speed=5"
|
||||||
|
@ -151,7 +151,7 @@ template <typename SampleSource, bool is_stereo> class LowpassSpeaker: public Sp
|
|||||||
// Announce to delegate if full.
|
// Announce to delegate if full.
|
||||||
if(output_buffer_pointer_ == output_buffer_.size()) {
|
if(output_buffer_pointer_ == output_buffer_.size()) {
|
||||||
output_buffer_pointer_ = 0;
|
output_buffer_pointer_ = 0;
|
||||||
did_complete_samples(this, output_buffer_);
|
did_complete_samples(this, output_buffer_, is_stereo);
|
||||||
}
|
}
|
||||||
|
|
||||||
cycles_remaining -= cycles_to_read;
|
cycles_remaining -= cycles_to_read;
|
||||||
@ -273,7 +273,7 @@ template <typename SampleSource, bool is_stereo> class LowpassSpeaker: public Sp
|
|||||||
// Announce to delegate if full.
|
// Announce to delegate if full.
|
||||||
if(output_buffer_pointer_ == output_buffer_.size()) {
|
if(output_buffer_pointer_ == output_buffer_.size()) {
|
||||||
output_buffer_pointer_ = 0;
|
output_buffer_pointer_ = 0;
|
||||||
did_complete_samples(this, output_buffer_);
|
did_complete_samples(this, output_buffer_, is_stereo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the next loop around is going to reuse some of the samples just collected, use a memmove to
|
// If the next loop around is going to reuse some of the samples just collected, use a memmove to
|
||||||
|
@ -81,9 +81,32 @@ class Speaker {
|
|||||||
virtual void set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) = 0;
|
virtual void set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) {
|
void did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer, bool is_stereo) {
|
||||||
++completed_sample_sets_;
|
++completed_sample_sets_;
|
||||||
|
|
||||||
|
// Hope for the fast path first: producer and consumer agree about
|
||||||
|
// number of channels.
|
||||||
|
if(is_stereo == stereo_output_) {
|
||||||
delegate_->speaker_did_complete_samples(this, buffer);
|
delegate_->speaker_did_complete_samples(this, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Producer and consumer don't agree, so mix two channels to one, or double out one to two.
|
||||||
|
if(is_stereo) {
|
||||||
|
// Mix down.
|
||||||
|
mix_buffer_.resize(buffer.size() / 2);
|
||||||
|
for(size_t c = 0; c < mix_buffer_.size(); ++c) {
|
||||||
|
mix_buffer_[c] = (buffer[(c << 1) + 0] + buffer[(c << 1) + 1]) >> 1;
|
||||||
|
// TODO: is there an Accelerate framework solution to this?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Double up.
|
||||||
|
mix_buffer_.resize(buffer.size() * 2);
|
||||||
|
for(size_t c = 0; c < buffer.size(); ++c) {
|
||||||
|
mix_buffer_[(c << 1) + 0] = mix_buffer_[(c << 1) + 1] = buffer[c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate_->speaker_did_complete_samples(this, mix_buffer_);
|
||||||
}
|
}
|
||||||
Delegate *delegate_ = nullptr;
|
Delegate *delegate_ = nullptr;
|
||||||
|
|
||||||
@ -99,6 +122,7 @@ class Speaker {
|
|||||||
float output_cycles_per_second_ = 1.0f;
|
float output_cycles_per_second_ = 1.0f;
|
||||||
int output_buffer_size_ = 1;
|
int output_buffer_size_ = 1;
|
||||||
bool stereo_output_ = false;
|
bool stereo_output_ = false;
|
||||||
|
std::vector<int16_t> mix_buffer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user