1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +00:00

Adds the messaging that would allow a Speaker to output stereo, semantically.

This commit is contained in:
Thomas Harte 2020-02-15 13:40:19 -05:00
parent dde672701f
commit 49b8e771b5
7 changed files with 50 additions and 10 deletions

View File

@ -37,9 +37,9 @@ float MultiSpeaker::get_ideal_clock_rate_in_range(float minimum, float maximum)
return ideal / static_cast<float>(speakers_.size());
}
void MultiSpeaker::set_computed_output_rate(float cycles_per_second, int buffer_size) {
void MultiSpeaker::set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) {
for(const auto &speaker: speakers_) {
speaker->set_computed_output_rate(cycles_per_second, buffer_size);
speaker->set_computed_output_rate(cycles_per_second, buffer_size, stereo);
}
}

View File

@ -39,7 +39,7 @@ class MultiSpeaker: public Outputs::Speaker::Speaker, Outputs::Speaker::Speaker:
// Below is the standard Outputs::Speaker::Speaker interface; see there for documentation.
float get_ideal_clock_rate_in_range(float minimum, float maximum) override;
void set_computed_output_rate(float cycles_per_second, int buffer_size) override;
void set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) override;
void set_delegate(Outputs::Speaker::Speaker::Delegate *delegate) override;
private:

View File

@ -67,7 +67,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"

View File

@ -272,7 +272,7 @@ struct ActivityObserver: public Activity::Observer {
@synchronized(self) {
Outputs::Speaker::Speaker *speaker = _machine->crt_machine()->get_speaker();
if(speaker) {
speaker->set_output_rate(sampleRate, (int)bufferSize);
speaker->set_output_rate(sampleRate, (int)bufferSize, false);
speaker->set_delegate(delegate);
return YES;
}

View File

@ -667,7 +667,7 @@ int main(int argc, char *argv[]) {
speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples);
speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, false);
speaker->set_delegate(&speaker_delegate);
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
}

View File

@ -58,7 +58,7 @@ template <typename T> class LowpassSpeaker: public Speaker {
}
// Implemented as per Speaker.
void set_computed_output_rate(float cycles_per_second, int buffer_size) final {
void set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) final {
std::lock_guard<std::mutex> lock_guard(filter_parameters_mutex_);
if(filter_parameters_.output_cycles_per_second == cycles_per_second && size_t(buffer_size) == output_buffer_.size()) {
return;
@ -69,6 +69,11 @@ template <typename T> class LowpassSpeaker: public Speaker {
output_buffer_.resize(std::size_t(buffer_size));
}
// TODO.
bool get_is_stereo() final {
return false;
}
/*!
Sets the clock rate of the input audio.
*/

View File

@ -23,28 +23,62 @@ class Speaker {
public:
virtual ~Speaker() {}
/*!
@returns The best output clock rate for the audio being supplied to this speaker, from the range given.
*/
virtual float get_ideal_clock_rate_in_range(float minimum, float maximum) = 0;
void set_output_rate(float cycles_per_second, int buffer_size) {
/*!
@returns @c true if the device would most ideally output stereo sound; @c false otherwise.
*/
virtual bool get_is_stereo() { return false; };
/*!
Sets the actual output rate; packets provided to the delegate will conform to these
specifications regardless of the input.
*/
void set_output_rate(float cycles_per_second, int buffer_size, bool stereo) {
output_cycles_per_second_ = cycles_per_second;
output_buffer_size_ = buffer_size;
stereo_output_ = stereo;
compute_output_rate();
}
/*!
Speeds a speed multiplier for this machine, e.g. that it is currently being run at 2.0x its normal rate.
This will affect the number of input samples that are combined to produce one output sample.
*/
void set_input_rate_multiplier(float multiplier) {
input_rate_multiplier_ = multiplier;
compute_output_rate();
}
/*!
@returns The number of sample sets so far delivered to the delegate.
*/
int completed_sample_sets() const { return completed_sample_sets_; }
/*!
Defines a receiver for audio packets.
*/
struct Delegate {
/*!
Indicates that a new audio packet is ready. If the output is stereo, samples will be interleaved with the first
being left, the second being right, etc.
*/
virtual void speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) = 0;
/*!
Provides the delegate with a hint that the input clock rate has changed, which provides an opportunity to
renegotiate the ideal clock rate, if desired.
*/
virtual void speaker_did_change_input_clock(Speaker *speaker) {}
};
virtual void set_delegate(Delegate *delegate) {
delegate_ = delegate;
}
virtual void set_computed_output_rate(float cycles_per_second, int buffer_size) = 0;
virtual void set_computed_output_rate(float cycles_per_second, int buffer_size, bool stereo) = 0;
protected:
void did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) {
@ -57,13 +91,14 @@ class Speaker {
void compute_output_rate() {
// The input rate multiplier is actually used as an output rate divider,
// to confirm to the public interface of a generic speaker being output-centric.
set_computed_output_rate(output_cycles_per_second_ / input_rate_multiplier_, output_buffer_size_);
set_computed_output_rate(output_cycles_per_second_ / input_rate_multiplier_, output_buffer_size_, stereo_output_);
}
int completed_sample_sets_ = 0;
float input_rate_multiplier_ = 1.0f;
float output_cycles_per_second_ = 1.0f;
int output_buffer_size_ = 1;
bool stereo_output_ = false;
};
}