mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Makes an attempt to transfer audio outputs during dynamic analysis.
This commit is contained in:
parent
7b420d56e3
commit
c8a4432c63
@ -14,7 +14,9 @@
|
||||
using namespace Analyser::Dynamic;
|
||||
|
||||
MultiCRTMachine::MultiCRTMachine(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines, std::mutex &machines_mutex) :
|
||||
machines_(machines), machines_mutex_(machines_mutex), queues_(machines.size()) {}
|
||||
machines_(machines), machines_mutex_(machines_mutex), queues_(machines.size()) {
|
||||
speaker_ = MultiSpeaker::create(machines);
|
||||
}
|
||||
|
||||
void MultiCRTMachine::perform_parallel(const std::function<void(::CRTMachine::Machine *)> &function) {
|
||||
// Apply a blunt force parallelisation of the machines; each run_for is dispatched
|
||||
@ -72,9 +74,7 @@ Outputs::CRT::CRT *MultiCRTMachine::get_crt() {
|
||||
}
|
||||
|
||||
Outputs::Speaker::Speaker *MultiCRTMachine::get_speaker() {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
CRTMachine::Machine *crt_machine = machines_.front()->crt_machine();
|
||||
return crt_machine ? crt_machine->get_speaker() : nullptr;
|
||||
return speaker_;
|
||||
}
|
||||
|
||||
void MultiCRTMachine::run_for(const Cycles cycles) {
|
||||
@ -99,7 +99,10 @@ bool MultiCRTMachine::get_clock_is_unlimited() {
|
||||
}
|
||||
|
||||
void MultiCRTMachine::did_change_machine_order() {
|
||||
// TODO: shuffle delegates and announce potential output rate changes.
|
||||
if(speaker_) {
|
||||
std::lock_guard<std::mutex> machines_lock(machines_mutex_);
|
||||
speaker_->set_new_front_machine(machines_.front().get());
|
||||
}
|
||||
}
|
||||
|
||||
void MultiCRTMachine::set_delegate(::CRTMachine::Machine::Delegate *delegate) {
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "../../../../Machines/CRTMachine.hpp"
|
||||
#include "../../../../Machines/DynamicMachine.hpp"
|
||||
|
||||
#include "MultiSpeaker.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
@ -49,6 +51,7 @@ class MultiCRTMachine: public ::CRTMachine::Machine, public ::CRTMachine::Machin
|
||||
const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines_;
|
||||
std::mutex &machines_mutex_;
|
||||
std::vector<Concurrency::AsyncTaskQueue> queues_;
|
||||
MultiSpeaker *speaker_ = nullptr;
|
||||
Delegate *delegate_ = nullptr;
|
||||
|
||||
/*!
|
||||
|
@ -0,0 +1,58 @@
|
||||
//
|
||||
// MultiSpeaker.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 18/02/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "MultiSpeaker.hpp"
|
||||
|
||||
using namespace Analyser::Dynamic;
|
||||
|
||||
MultiSpeaker *MultiSpeaker::create(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines) {
|
||||
std::vector<Outputs::Speaker::Speaker *> speakers;
|
||||
for(const auto &machine: machines) {
|
||||
Outputs::Speaker::Speaker *speaker = machine->crt_machine()->get_speaker();
|
||||
if(speaker) speakers.push_back(speaker);
|
||||
}
|
||||
if(speakers.empty()) return nullptr;
|
||||
|
||||
return new MultiSpeaker(speakers);
|
||||
}
|
||||
|
||||
MultiSpeaker::MultiSpeaker(const std::vector<Outputs::Speaker::Speaker *> &speakers) :
|
||||
speakers_(speakers), front_speaker_(speakers.front()) {
|
||||
for(const auto &speaker: speakers_) {
|
||||
speaker->set_delegate(this);
|
||||
}
|
||||
}
|
||||
|
||||
float MultiSpeaker::get_ideal_clock_rate_in_range(float minimum, float maximum) {
|
||||
float ideal = 0.0f;
|
||||
for(const auto &speaker: speakers_) {
|
||||
ideal += speaker->get_ideal_clock_rate_in_range(minimum, maximum);
|
||||
}
|
||||
|
||||
return ideal / static_cast<float>(speakers_.size());
|
||||
}
|
||||
|
||||
void MultiSpeaker::set_output_rate(float cycles_per_second, int buffer_size) {
|
||||
for(const auto &speaker: speakers_) {
|
||||
speaker->set_output_rate(cycles_per_second, buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiSpeaker::set_delegate(Outputs::Speaker::Speaker::Delegate *delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
void MultiSpeaker::speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) {
|
||||
if(delegate_ && speaker == front_speaker_) {
|
||||
delegate_->speaker_did_complete_samples(this, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiSpeaker::set_new_front_machine(::Machine::DynamicMachine *machine) {
|
||||
front_speaker_ = machine->crt_machine()->get_speaker();
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
//
|
||||
// MultiSpeaker.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 18/02/2018.
|
||||
// Copyright © 2018 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef MultiSpeaker_hpp
|
||||
#define MultiSpeaker_hpp
|
||||
|
||||
#include "../../../../Machines/DynamicMachine.hpp"
|
||||
#include "../../../../Outputs/Speaker/Speaker.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Analyser {
|
||||
namespace Dynamic {
|
||||
|
||||
class MultiSpeaker: public Outputs::Speaker::Speaker, Outputs::Speaker::Speaker::Delegate {
|
||||
public:
|
||||
static MultiSpeaker *create(const std::vector<std::unique_ptr<::Machine::DynamicMachine>> &machines);
|
||||
MultiSpeaker(const std::vector<Outputs::Speaker::Speaker *> &speakers);
|
||||
|
||||
void set_new_front_machine(::Machine::DynamicMachine *machine);
|
||||
|
||||
float get_ideal_clock_rate_in_range(float minimum, float maximum);
|
||||
void set_output_rate(float cycles_per_second, int buffer_size);
|
||||
void set_delegate(Outputs::Speaker::Speaker::Delegate *delegate);
|
||||
void speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer);
|
||||
|
||||
private:
|
||||
std::vector<Outputs::Speaker::Speaker *> speakers_;
|
||||
Outputs::Speaker::Speaker *front_speaker_ = nullptr;
|
||||
Outputs::Speaker::Speaker::Delegate *delegate_ = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MultiSpeaker_hpp */
|
@ -288,6 +288,8 @@
|
||||
4B98A05F1FFAD62400ADF63B /* CSROMFetcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */; };
|
||||
4B98A0611FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */; };
|
||||
4B98A1CE1FFADEC500ADF63B /* MSX ROMs in Resources */ = {isa = PBXBuildFile; fileRef = 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */; };
|
||||
4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
|
||||
4B9BE401203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
|
||||
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */; };
|
||||
4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */; };
|
||||
4BAD13441FF709C700FD114A /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E61051FF34737002A9DBD /* MSX.cpp */; };
|
||||
@ -963,6 +965,8 @@
|
||||
4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CSROMFetcher.mm; sourceTree = "<group>"; };
|
||||
4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MSXStaticAnalyserTests.mm; sourceTree = "<group>"; };
|
||||
4B98A1CD1FFADEC400ADF63B /* MSX ROMs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "MSX ROMs"; sourceTree = "<group>"; };
|
||||
4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiSpeaker.cpp; sourceTree = "<group>"; };
|
||||
4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiSpeaker.hpp; sourceTree = "<group>"; };
|
||||
4B9CCDA01DA279CA0098B625 /* Vic20OptionsPanel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vic20OptionsPanel.swift; sourceTree = "<group>"; };
|
||||
4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZX8081.cpp; path = Data/ZX8081.cpp; sourceTree = "<group>"; };
|
||||
4BA0F68D1EEA0E8400E9489E /* ZX8081.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ZX8081.hpp; path = Data/ZX8081.hpp; sourceTree = "<group>"; };
|
||||
@ -2675,11 +2679,13 @@
|
||||
4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */,
|
||||
4B1B88C6202E469300B67DFF /* MultiJoystickMachine.cpp */,
|
||||
4B1B88B9202E2EC100B67DFF /* MultiKeyboardMachine.cpp */,
|
||||
4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */,
|
||||
4B1B88BF202E3DB200B67DFF /* MultiConfigurable.hpp */,
|
||||
4BBB70A2202011C2002FE009 /* MultiConfigurationTarget.hpp */,
|
||||
4BBB70A7202014E2002FE009 /* MultiCRTMachine.hpp */,
|
||||
4B1B88C7202E469300B67DFF /* MultiJoystickMachine.hpp */,
|
||||
4B1B88BA202E2EC100B67DFF /* MultiKeyboardMachine.hpp */,
|
||||
4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */,
|
||||
);
|
||||
path = Implementation;
|
||||
sourceTree = "<group>";
|
||||
@ -3440,6 +3446,7 @@
|
||||
4B055A9C1FAE85DA0060FFFF /* CPCDSK.cpp in Sources */,
|
||||
4B055AE41FAE9B6F0060FFFF /* TextureTarget.cpp in Sources */,
|
||||
4B055ABA1FAE86170060FFFF /* Commodore.cpp in Sources */,
|
||||
4B9BE401203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */,
|
||||
4B055AA61FAE85EF0060FFFF /* Parser.cpp in Sources */,
|
||||
4B055AE91FAE9B990060FFFF /* 6502Base.cpp in Sources */,
|
||||
4B055AEF1FAE9BF00060FFFF /* Typer.cpp in Sources */,
|
||||
@ -3534,6 +3541,7 @@
|
||||
4B4518A11F75FD1C00926311 /* D64.cpp in Sources */,
|
||||
4B1558C01F844ECD006E9A97 /* BitReverse.cpp in Sources */,
|
||||
4BCF1FA41DADC3DD0039D2E7 /* Oric.cpp in Sources */,
|
||||
4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */,
|
||||
4B894538201967B4007DE474 /* Tape.cpp in Sources */,
|
||||
4B54C0CB1F8D92590050900F /* Keyboard.cpp in Sources */,
|
||||
4BEA525E1DF33323007E74F2 /* Tape.cpp in Sources */,
|
||||
|
@ -29,7 +29,7 @@ class Speaker {
|
||||
struct Delegate {
|
||||
virtual void speaker_did_complete_samples(Speaker *speaker, const std::vector<int16_t> &buffer) = 0;
|
||||
};
|
||||
void set_delegate(Delegate *delegate) {
|
||||
virtual void set_delegate(Delegate *delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user