mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-24 02:30:54 +00:00
Adds the messaging that would allow a Speaker to output stereo, semantically.
This commit is contained in:
parent
dde672701f
commit
49b8e771b5
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -67,7 +67,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
enableASanStackUseAfterReturn = "YES"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user