mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Attempts to obey accumulator size in determining sample end.
This commit is contained in:
parent
b0efc647f1
commit
8edb3fcd5f
@ -78,6 +78,9 @@ void GLU::EnsoniqState::set_register(uint16_t address, uint8_t value) {
|
|||||||
} break;
|
} break;
|
||||||
case 0xc0:
|
case 0xc0:
|
||||||
oscillators[address & 0x1f].table_size = value;
|
oscillators[address & 0x1f].table_size = value;
|
||||||
|
|
||||||
|
// The most-significant bit that should be used is 16 + (value & 7).
|
||||||
|
oscillators[address & 0x1f].overflow_mask = ~(0xffffff >> (7 - (value & 7)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -194,13 +197,13 @@ void GLU::generate_audio(size_t number_of_samples, std::int16_t *target, int16_t
|
|||||||
|
|
||||||
// Test for a new halting event.
|
// Test for a new halting event.
|
||||||
switch(remote_.oscillators[c].control & 6) {
|
switch(remote_.oscillators[c].control & 6) {
|
||||||
case 0: // Free-run mode; just keep the counter to its genuine 24 bits and always update sample.
|
case 0: // Free-run mode; don't truncate the position at all, in case the
|
||||||
remote_.oscillators[c].position &= 0x00ffffff;
|
// accumulator bits in use changes.
|
||||||
output += remote_.oscillators[c].output(remote_.ram_);
|
output += remote_.oscillators[c].output(remote_.ram_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // One-shot mode; check for end of run. Otherwise update sample.
|
case 2: // One-shot mode; check for end of run. Otherwise update sample.
|
||||||
if(remote_.oscillators[c].position & 0xff000000) {
|
if(remote_.oscillators[c].position & remote_.oscillators[c].overflow_mask) {
|
||||||
remote_.oscillators[c].position = 0;
|
remote_.oscillators[c].position = 0;
|
||||||
remote_.oscillators[c].control |= 1;
|
remote_.oscillators[c].control |= 1;
|
||||||
} else {
|
} else {
|
||||||
@ -213,9 +216,10 @@ void GLU::generate_audio(size_t number_of_samples, std::int16_t *target, int16_t
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: // Swap mode; possibly trigger partner, and update sample.
|
case 6: // Swap mode; possibly trigger partner, and update sample.
|
||||||
// TODO: possibly this function argues in favour of summing the output
|
// Per tech note #11: "Whenever a swap occurs from a higher-numbered
|
||||||
// in a separate loop?
|
// oscillator to a lower-numbered one, the output signal from the corresponding
|
||||||
if(remote_.oscillators[c].position & 0xff000000) {
|
// generator temporarily falls to the zero-crossing level (silence)"
|
||||||
|
if(remote_.oscillators[c].position & remote_.oscillators[c].overflow_mask) {
|
||||||
remote_.oscillators[c].control |= 1;
|
remote_.oscillators[c].control |= 1;
|
||||||
remote_.oscillators[c].position = 0;
|
remote_.oscillators[c].position = 0;
|
||||||
remote_.oscillators[c^1].control &= ~1;
|
remote_.oscillators[c^1].control &= ~1;
|
||||||
@ -227,6 +231,7 @@ void GLU::generate_audio(size_t number_of_samples, std::int16_t *target, int16_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Maximum total output was 32 channels times a 16-bit range. Map that down.
|
// Maximum total output was 32 channels times a 16-bit range. Map that down.
|
||||||
|
// TODO: dynamic total volume?
|
||||||
target[sample] = (output * output_range_) >> 20;
|
target[sample] = (output * output_range_) >> 20;
|
||||||
|
|
||||||
// Apply any RAM writes that interleave here.
|
// Apply any RAM writes that interleave here.
|
||||||
@ -266,6 +271,7 @@ int16_t GLU::EnsoniqState::Oscillator::output(uint8_t *ram) {
|
|||||||
const auto level = sample(ram);
|
const auto level = sample(ram);
|
||||||
|
|
||||||
// "An oscillator will halt when a zero is encountered in its waveform table."
|
// "An oscillator will halt when a zero is encountered in its waveform table."
|
||||||
|
// TODO: only if in free-run mode, I think? Or?
|
||||||
if(!level) {
|
if(!level) {
|
||||||
control |= 1;
|
control |= 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -76,6 +76,10 @@ class GLU: public Outputs::Speaker::SampleSource {
|
|||||||
uint8_t control;
|
uint8_t control;
|
||||||
uint8_t table_size;
|
uint8_t table_size;
|
||||||
|
|
||||||
|
// Derived state.
|
||||||
|
uint32_t overflow_mask; // If a non-zero bit gets anywhere into the overflow mask, this channel
|
||||||
|
// has wrapped around. It's a function of table_size.
|
||||||
|
|
||||||
uint8_t sample(uint8_t *ram);
|
uint8_t sample(uint8_t *ram);
|
||||||
int16_t output(uint8_t *ram);
|
int16_t output(uint8_t *ram);
|
||||||
} oscillators[32];
|
} oscillators[32];
|
||||||
|
Loading…
Reference in New Issue
Block a user