mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-19 07:31:15 +00:00
Attempt audio output.
This commit is contained in:
parent
779794632e
commit
6ac6e48b95
@ -321,6 +321,7 @@ struct HackyDebugger {
|
|||||||
|
|
||||||
class ConcreteMachine:
|
class ConcreteMachine:
|
||||||
public Machine,
|
public Machine,
|
||||||
|
public MachineTypes::AudioProducer,
|
||||||
public MachineTypes::MappedKeyboardMachine,
|
public MachineTypes::MappedKeyboardMachine,
|
||||||
public MachineTypes::MediaTarget,
|
public MachineTypes::MediaTarget,
|
||||||
public MachineTypes::MouseMachine,
|
public MachineTypes::MouseMachine,
|
||||||
@ -480,6 +481,11 @@ class ConcreteMachine:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - AudioProducer
|
||||||
|
Outputs::Speaker::Speaker *get_speaker() override {
|
||||||
|
return executor_.bus.speaker();
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Activity::Source.
|
// MARK: - Activity::Source.
|
||||||
void set_activity_observer(Activity::Observer *observer) final {
|
void set_activity_observer(Activity::Observer *observer) final {
|
||||||
executor_.bus.set_activity_observer(observer);
|
executor_.bus.set_activity_observer(observer);
|
||||||
|
@ -96,6 +96,7 @@ struct MemoryController {
|
|||||||
case 0b111:
|
case 0b111:
|
||||||
os_mode_ = address & (1 << 12);
|
os_mode_ = address & (1 << 12);
|
||||||
sound_dma_enable_ = address & (1 << 11);
|
sound_dma_enable_ = address & (1 << 11);
|
||||||
|
ioc_.sound().set_dma_enabled(sound_dma_enable_);
|
||||||
video_dma_enable_ = address & (1 << 10);
|
video_dma_enable_ = address & (1 << 10);
|
||||||
switch((address >> 8) & 3) {
|
switch((address >> 8) & 3) {
|
||||||
default:
|
default:
|
||||||
@ -203,6 +204,10 @@ struct MemoryController {
|
|||||||
ioc_.set_disk(disk, drive);
|
ioc_.set_disk(disk, drive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Outputs::Speaker::Speaker *speaker() {
|
||||||
|
return ioc_.sound().speaker();
|
||||||
|
}
|
||||||
|
|
||||||
auto &sound() { return ioc_.sound(); }
|
auto &sound() { return ioc_.sound(); }
|
||||||
const auto &sound() const { return ioc_.sound(); }
|
const auto &sound() const { return ioc_.sound(); }
|
||||||
auto &video() { return ioc_.video(); }
|
auto &video() { return ioc_.video(); }
|
||||||
|
@ -61,6 +61,9 @@ struct Sound: private SoundLevels {
|
|||||||
void set_next_start(uint32_t value) {
|
void set_next_start(uint32_t value) {
|
||||||
next_.start = value;
|
next_.start = value;
|
||||||
set_buffer_valid(true); // My guess: this is triggered on next buffer start write.
|
set_buffer_valid(true); // My guess: this is triggered on next buffer start write.
|
||||||
|
|
||||||
|
// Definitely wrong; testing.
|
||||||
|
// set_halted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool interrupt() const {
|
bool interrupt() const {
|
||||||
@ -89,9 +92,20 @@ struct Sound: private SoundLevels {
|
|||||||
positions_[channel].left = 6 - positions_[channel].right;
|
positions_[channel].left = 6 - positions_[channel].right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_dma_enabled(bool enabled) {
|
||||||
|
dma_enabled_ = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
void tick() {
|
void tick() {
|
||||||
// Do nothing if not currently outputting.
|
// Write silence if not currently outputting.
|
||||||
if(halted_) {
|
if(halted_ || !dma_enabled_) {
|
||||||
|
samples_[byte_].left = samples_[byte_].right = 0;
|
||||||
|
++byte_;
|
||||||
|
if(byte_ == 16) {
|
||||||
|
speaker_.push(reinterpret_cast<int16_t *>(samples_.data()), 16);
|
||||||
|
byte_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,11 +115,15 @@ struct Sound: private SoundLevels {
|
|||||||
divider_ = reload_;
|
divider_ = reload_;
|
||||||
|
|
||||||
// Grab a single byte from the FIFO.
|
// Grab a single byte from the FIFO.
|
||||||
// TODO: and convert to a linear value, apply stereo image, output.
|
const uint8_t raw = ram_[current_.start + byte_];
|
||||||
|
// TODO: volume, pan.
|
||||||
|
samples_[byte_].left = levels[raw];
|
||||||
|
samples_[byte_].right = 0;
|
||||||
++byte_;
|
++byte_;
|
||||||
|
|
||||||
// If the FIFO is exhausted, consider triggering a DMA request.
|
// If the FIFO is exhausted, consider triggering a DMA request.
|
||||||
if(byte_ == 16) {
|
if(byte_ == 16) {
|
||||||
|
speaker_.push(reinterpret_cast<int16_t *>(samples_.data()), 16);
|
||||||
byte_ = 0;
|
byte_ = 0;
|
||||||
|
|
||||||
current_.start += 16;
|
current_.start += 16;
|
||||||
@ -119,6 +137,10 @@ struct Sound: private SoundLevels {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Outputs::Speaker::Speaker *speaker() {
|
||||||
|
return &speaker_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint8_t *ram_ = nullptr;
|
const uint8_t *ram_ = nullptr;
|
||||||
|
|
||||||
@ -132,6 +154,7 @@ private:
|
|||||||
|
|
||||||
void set_halted(bool halted) {
|
void set_halted(bool halted) {
|
||||||
if(halted_ != halted && !halted) {
|
if(halted_ != halted && !halted) {
|
||||||
|
speaker_.push(reinterpret_cast<int16_t *>(samples_.data()), byte_);
|
||||||
byte_ = 0;
|
byte_ = 0;
|
||||||
divider_ = reload_;
|
divider_ = reload_;
|
||||||
}
|
}
|
||||||
@ -140,6 +163,7 @@ private:
|
|||||||
|
|
||||||
bool next_buffer_valid_ = false;
|
bool next_buffer_valid_ = false;
|
||||||
bool halted_ = true; // This is a bit of a guess.
|
bool halted_ = true; // This is a bit of a guess.
|
||||||
|
bool dma_enabled_ = false;
|
||||||
|
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
uint32_t start = 0, end = 0;
|
uint32_t start = 0, end = 0;
|
||||||
@ -154,6 +178,7 @@ private:
|
|||||||
InterruptObserverT &observer_;
|
InterruptObserverT &observer_;
|
||||||
Outputs::Speaker::PushLowpass<true> speaker_;
|
Outputs::Speaker::PushLowpass<true> speaker_;
|
||||||
Concurrency::AsyncTaskQueue<true> queue_;
|
Concurrency::AsyncTaskQueue<true> queue_;
|
||||||
|
std::array<Outputs::Speaker::StereoSample, 16> samples_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
</Testables>
|
</Testables>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Release"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
enableASanStackUseAfterReturn = "YES"
|
enableASanStackUseAfterReturn = "YES"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user