mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Takes a stab at next_sequence_point.
This commit is contained in:
parent
4870506f6e
commit
7a8920ee38
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
// TODO: is it safe not to check for back-pressure in pending_stores_?
|
// TODO: is it safe not to check for back-pressure in pending_stores_?
|
||||||
|
|
||||||
@ -174,11 +175,28 @@ uint8_t GLU::get_address_high() {
|
|||||||
|
|
||||||
// MARK: - Update logic.
|
// MARK: - Update logic.
|
||||||
|
|
||||||
|
Cycles GLU::get_next_sequence_point() const {
|
||||||
|
uint32_t result = std::numeric_limits<decltype(result)>::max();
|
||||||
|
|
||||||
|
for(int c = 0; c < local_.oscillator_count; c++) {
|
||||||
|
// Don't do anything for halted oscillators, or for oscillators that can't hit stops.
|
||||||
|
if((local_.oscillators[c].control&3) != 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine how many cycles until a stop is hit and update the pending result
|
||||||
|
// if this is the new soonest-to-expire oscillator.
|
||||||
|
const auto first_overflow_value = (local_.oscillators[c].overflow_mask - 1) << 1;
|
||||||
|
const auto time_until_stop = (first_overflow_value - local_.oscillators[c].position + local_.oscillators[c].velocity - 1) / local_.oscillators[c].velocity;
|
||||||
|
result = std::min(result, time_until_stop);
|
||||||
|
}
|
||||||
|
return Cycles(result);
|
||||||
|
}
|
||||||
|
|
||||||
void GLU::skip_audio(EnsoniqState &state, size_t number_of_samples) {
|
void GLU::skip_audio(EnsoniqState &state, size_t number_of_samples) {
|
||||||
// Just advance all oscillator pointers and check for interrupts.
|
// Just advance all oscillator pointers and check for interrupts.
|
||||||
// If a read occurs to the current-output level, generate it then.
|
// If a read occurs to the current-output level, generate it then.
|
||||||
|
for(int c = 0; c < state.oscillator_count; c++) {
|
||||||
for(int c = 0; c < local_.oscillator_count; c++) {
|
|
||||||
// Don't do anything for halted oscillators.
|
// Don't do anything for halted oscillators.
|
||||||
if(state.oscillators[c].control&1) continue;
|
if(state.oscillators[c].control&1) continue;
|
||||||
|
|
||||||
@ -186,7 +204,7 @@ void GLU::skip_audio(EnsoniqState &state, size_t number_of_samples) {
|
|||||||
state.oscillators[c].position += state.oscillators[c].velocity * number_of_samples;
|
state.oscillators[c].position += state.oscillators[c].velocity * number_of_samples;
|
||||||
|
|
||||||
// Check for stops, and any interrupts that therefore flow.
|
// Check for stops, and any interrupts that therefore flow.
|
||||||
if((state.oscillators[c].control & 1) && (state.oscillators[c].position & state.oscillators[c].overflow_mask)) {
|
if((state.oscillators[c].control & 2) && (state.oscillators[c].position & state.oscillators[c].overflow_mask)) {
|
||||||
// Apply halt, set interrupt request flag.
|
// Apply halt, set interrupt request flag.
|
||||||
state.oscillators[c].position = 0;
|
state.oscillators[c].position = 0;
|
||||||
state.oscillators[c].control |= 1;
|
state.oscillators[c].control |= 1;
|
||||||
|
@ -33,6 +33,7 @@ class GLU: public Outputs::Speaker::SampleSource {
|
|||||||
uint8_t get_address_high();
|
uint8_t get_address_high();
|
||||||
|
|
||||||
void run_for(Cycles);
|
void run_for(Cycles);
|
||||||
|
Cycles get_next_sequence_point() const;
|
||||||
|
|
||||||
// SampleSource.
|
// SampleSource.
|
||||||
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||||
|
Loading…
Reference in New Issue
Block a user