1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

All proper inputs are now provided to the audio generator.

Hopefully. The next job is to generate audio. If that sounds correct, then the disk motor speed question can be tackled.
This commit is contained in:
Thomas Harte 2019-06-01 15:03:15 -04:00
parent 723137c0d4
commit 6d985866ee
5 changed files with 75 additions and 30 deletions

View File

@ -0,0 +1,34 @@
//
// DeferredAudio.hpp
// Clock Signal
//
// Created by Thomas Harte on 01/06/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef DeferredAudio_h
#define DeferredAudio_h
#include "Audio.hpp"
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
namespace Apple {
namespace Macintosh {
struct DeferredAudio {
Concurrency::DeferringAsyncTaskQueue queue;
Audio audio;
Outputs::Speaker::LowpassSpeaker<Audio> speaker;
HalfCycles time_since_update;
DeferredAudio() : audio(queue), speaker(audio) {}
void flush() {
speaker.run_for(queue, time_since_update.flush_cycles());
}
};
}
}
#endif /* DeferredAudio_h */

View File

@ -10,7 +10,7 @@
#include <array> #include <array>
#include "Audio.hpp" #include "DeferredAudio.hpp"
#include "Keyboard.hpp" #include "Keyboard.hpp"
#include "RealTimeClock.hpp" #include "RealTimeClock.hpp"
#include "Video.hpp" #include "Video.hpp"
@ -21,7 +21,6 @@
#include "../../../Components/6522/6522.hpp" #include "../../../Components/6522/6522.hpp"
#include "../../../Components/DiskII/IWM.hpp" #include "../../../Components/DiskII/IWM.hpp"
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
#include "../../../Processors/68000/68000.hpp" #include "../../../Processors/68000/68000.hpp"
#include "../../Utility/MemoryPacker.hpp" #include "../../Utility/MemoryPacker.hpp"
@ -42,7 +41,7 @@ class ConcreteMachine:
public: public:
ConcreteMachine(const ROMMachine::ROMFetcher &rom_fetcher) : ConcreteMachine(const ROMMachine::ROMFetcher &rom_fetcher) :
mc68000_(*this), mc68000_(*this),
video_(ram_.data()), video_(ram_.data(), audio_),
via_(via_port_handler_), via_(via_port_handler_),
via_port_handler_(*this, clock_, keyboard_, video_, audio_, iwm_), via_port_handler_(*this, clock_, keyboard_, video_, audio_, iwm_),
iwm_(CLOCK_RATE) { iwm_(CLOCK_RATE) {
@ -57,6 +56,7 @@ class ConcreteMachine:
// The Mac runs at 7.8336mHz. // The Mac runs at 7.8336mHz.
set_clock_rate(double(CLOCK_RATE)); set_clock_rate(double(CLOCK_RATE));
audio_.speaker.set_input_rate(float(CLOCK_RATE));
} }
void set_scan_target(Outputs::Display::ScanTarget *scan_target) override { void set_scan_target(Outputs::Display::ScanTarget *scan_target) override {
@ -243,8 +243,8 @@ class ConcreteMachine:
ROM_is_overlay_ = rom_is_overlay; ROM_is_overlay_ = rom_is_overlay;
} }
void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) { void set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer) {
video_.set_use_alternate_screen_buffer(use_alternate_screen_buffer); video_.set_use_alternate_buffers(use_alternate_screen_buffer, use_alternate_audio_buffer);
} }
private: private:
@ -259,22 +259,9 @@ class ConcreteMachine:
} }
}; };
struct Audio {
Concurrency::DeferringAsyncTaskQueue queue;
Apple::Macintosh::Audio audio;
Outputs::Speaker::LowpassSpeaker<Apple::Macintosh::Audio> speaker;
HalfCycles time_since_update;
Audio() : audio(queue), speaker(audio) {}
void flush() {
speaker.run_for(queue, time_since_update.flush_cycles());
}
};
class VIAPortHandler: public MOS::MOS6522::PortHandler { class VIAPortHandler: public MOS::MOS6522::PortHandler {
public: public:
VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, Video &video, Audio &audio, IWM &iwm) : VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock, Keyboard &keyboard, Video &video, DeferredAudio &audio, IWM &iwm) :
machine_(machine), clock_(clock), keyboard_(keyboard), video_(video), audio_(audio), iwm_(iwm) {} machine_(machine), clock_(clock), keyboard_(keyboard), video_(video), audio_(audio), iwm_(iwm) {}
using Port = MOS::MOS6522::Port; using Port = MOS::MOS6522::Port;
@ -299,13 +286,11 @@ class ConcreteMachine:
iwm_.flush(); iwm_.flush();
iwm_.iwm.set_select(!(value & 0x20)); iwm_.iwm.set_select(!(value & 0x20));
machine_.set_use_alternate_screen_buffer(!(value & 0x40)); machine_.set_use_alternate_buffers(!(value & 0x40), !(value&0x08));
machine_.set_rom_is_overlay(!!(value & 0x10)); machine_.set_rom_is_overlay(!!(value & 0x10));
audio_.flush(); audio_.flush();
audio_.audio.set_volume(value & 7); audio_.audio.set_volume(value & 7);
// TODO: alternate sound buffer.
break; break;
case Port::B: case Port::B:
@ -360,7 +345,7 @@ class ConcreteMachine:
RealTimeClock &clock_; RealTimeClock &clock_;
Keyboard &keyboard_; Keyboard &keyboard_;
Video &video_; Video &video_;
Audio &audio_; DeferredAudio &audio_;
IWM &iwm_; IWM &iwm_;
}; };
@ -369,8 +354,8 @@ class ConcreteMachine:
CPU::MC68000::Processor<ConcreteMachine, true> mc68000_; CPU::MC68000::Processor<ConcreteMachine, true> mc68000_;
DeferredAudio audio_;
Video video_; Video video_;
Audio audio_;
RealTimeClock clock_; RealTimeClock clock_;
Keyboard keyboard_; Keyboard keyboard_;

View File

@ -33,7 +33,8 @@ const int sync_end = 38;
// "The visible portion of a full-screen display consists of 342 horizontal scan lines... // "The visible portion of a full-screen display consists of 342 horizontal scan lines...
// During the vertical blanking interval, the turned-off beam ... traces out an additional 28 scan lines," // During the vertical blanking interval, the turned-off beam ... traces out an additional 28 scan lines,"
// //
Video::Video(uint16_t *ram) : Video::Video(uint16_t *ram, DeferredAudio &audio) :
audio_(audio),
crt_(704, 1, 370, Outputs::Display::ColourSpace::YIQ, 1, 1, 6, false, Outputs::Display::InputDataType::Luminance1), crt_(704, 1, 370, Outputs::Display::ColourSpace::YIQ, 1, 1, 6, false, Outputs::Display::InputDataType::Luminance1),
ram_(ram) { ram_(ram) {
@ -131,6 +132,14 @@ void Video::run_for(HalfCycles duration) {
crt_.output_blank((44 - sync_end) * 16); crt_.output_blank((44 - sync_end) * 16);
} }
} }
// Audio and disk fetches occur "just before video data".
if(final_word == 44) {
const uint16_t audio_word = ram_[audio_address_];
++audio_address_;
audio_.audio.post_sample(audio_word >> 8);
// TODO: post disk byte.
}
} }
duration -= cycles_left_in_line; duration -= cycles_left_in_line;
@ -141,6 +150,12 @@ void Video::run_for(HalfCycles duration) {
Video: $1A700 and the alternate buffer starts at $12700; for a 512K Macintosh, add $60000 to these numbers. Video: $1A700 and the alternate buffer starts at $12700; for a 512K Macintosh, add $60000 to these numbers.
*/ */
video_address_ = use_alternate_screen_buffer_ ? (0x12700 >> 1) : (0x1a700 >> 1); video_address_ = use_alternate_screen_buffer_ ? (0x12700 >> 1) : (0x1a700 >> 1);
/*
"The main sound buffer is at $1FD00 in a 128K Macintosh, and the alternate buffer is at $1A100;
for a 512K Macintosh, add $60000 to these values."
*/
audio_address_ = use_alternate_audio_buffer_ ? (0x1fd00 >> 1) : (0x1a100 >> 1);
} }
} }
} }
@ -156,7 +171,7 @@ bool Video::is_outputting() {
return line < 342 && column < 32; return line < 342 && column < 32;
} }
void Video::set_use_alternate_screen_buffer(bool use_alternate_screen_buffer) { void Video::set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer) {
use_alternate_screen_buffer_ = use_alternate_screen_buffer; use_alternate_screen_buffer_ = use_alternate_screen_buffer;
use_alternate_audio_buffer_ = use_alternate_audio_buffer;
} }

View File

@ -11,29 +11,38 @@
#include "../../../Outputs/CRT/CRT.hpp" #include "../../../Outputs/CRT/CRT.hpp"
#include "../../../ClockReceiver/ClockReceiver.hpp" #include "../../../ClockReceiver/ClockReceiver.hpp"
#include "DeferredAudio.hpp"
namespace Apple { namespace Apple {
namespace Macintosh { namespace Macintosh {
class Video { class Video {
public: public:
Video(uint16_t *ram); Video(uint16_t *ram, DeferredAudio &audio);
void set_scan_target(Outputs::Display::ScanTarget *scan_target); void set_scan_target(Outputs::Display::ScanTarget *scan_target);
void run_for(HalfCycles duration); void run_for(HalfCycles duration);
void set_use_alternate_screen_buffer(bool use_alternate_screen_buffer);
void set_use_alternate_buffers(bool use_alternate_screen_buffer, bool use_alternate_audio_buffer);
// TODO: feedback on blanks and syncs. // TODO: feedback on blanks and syncs.
bool vsync(); bool vsync();
bool is_outputting(); bool is_outputting();
private: private:
DeferredAudio &audio_;
uint16_t *ram_ = nullptr;
Outputs::CRT::CRT crt_; Outputs::CRT::CRT crt_;
HalfCycles frame_position_; HalfCycles frame_position_;
size_t video_address_ = 0; size_t video_address_ = 0;
uint16_t *ram_ = nullptr; size_t audio_address_ = 0;
uint8_t *pixel_buffer_ = nullptr; uint8_t *pixel_buffer_ = nullptr;
bool use_alternate_screen_buffer_ = false; bool use_alternate_screen_buffer_ = false;
bool use_alternate_audio_buffer_ = false;
}; };
} }

View File

@ -1328,6 +1328,7 @@
4BB298EC1B587D8400A49093 /* txsn */ = {isa = PBXFileReference; lastKnownFileType = file; path = txsn; sourceTree = "<group>"; }; 4BB298EC1B587D8400A49093 /* txsn */ = {isa = PBXFileReference; lastKnownFileType = file; path = txsn; sourceTree = "<group>"; };
4BB298ED1B587D8400A49093 /* tyan */ = {isa = PBXFileReference; lastKnownFileType = file; path = tyan; sourceTree = "<group>"; }; 4BB298ED1B587D8400A49093 /* tyan */ = {isa = PBXFileReference; lastKnownFileType = file; path = tyan; sourceTree = "<group>"; };
4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CRCTests.mm; sourceTree = "<group>"; }; 4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CRCTests.mm; sourceTree = "<group>"; };
4BB4BFAA22A300710069048D /* DeferredAudio.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeferredAudio.hpp; sourceTree = "<group>"; };
4BB697C61D4B558F00248BDF /* Factors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Factors.hpp; path = ../../NumberTheory/Factors.hpp; sourceTree = "<group>"; }; 4BB697C61D4B558F00248BDF /* Factors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Factors.hpp; path = ../../NumberTheory/Factors.hpp; sourceTree = "<group>"; };
4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; }; 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; }; 4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; };
@ -3072,6 +3073,7 @@
4BCE0058227CFFCA000CA200 /* Macintosh.cpp */, 4BCE0058227CFFCA000CA200 /* Macintosh.cpp */,
4BCE005E227D39AB000CA200 /* Video.cpp */, 4BCE005E227D39AB000CA200 /* Video.cpp */,
4B9378E322A199C600973513 /* Audio.hpp */, 4B9378E322A199C600973513 /* Audio.hpp */,
4BB4BFAA22A300710069048D /* DeferredAudio.hpp */,
4BDB3D8522833321002D3CEE /* Keyboard.hpp */, 4BDB3D8522833321002D3CEE /* Keyboard.hpp */,
4BCE0059227CFFCA000CA200 /* Macintosh.hpp */, 4BCE0059227CFFCA000CA200 /* Macintosh.hpp */,
4BD0692B22828A2D00D2A54F /* RealTimeClock.hpp */, 4BD0692B22828A2D00D2A54F /* RealTimeClock.hpp */,