1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Makes an attempt to transfer audio outputs during dynamic analysis.

This commit is contained in:
Thomas Harte 2018-02-18 15:23:15 -05:00
parent 7b420d56e3
commit c8a4432c63
6 changed files with 120 additions and 6 deletions

View File

@ -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) {

View File

@ -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;
/*!

View File

@ -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();
}

View File

@ -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 */

View File

@ -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 */,

View File

@ -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;
}