mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Attempts an essentially-complete implementation of tone channels.
This commit is contained in:
parent
90782d3c27
commit
f8bb66d2a0
@ -50,15 +50,35 @@ void Dave::set_sample_volume_range(int16_t range) {
|
||||
}
|
||||
|
||||
void Dave::get_samples(std::size_t number_of_samples, int16_t *target) {
|
||||
// Step 1: divide input clock to 125,000 Hz (?)
|
||||
for(size_t c = 0; c < number_of_samples; c++) {
|
||||
#define update_channel(x) \
|
||||
if(!channels_[x].count) { \
|
||||
channels_[x].output ^= true; \
|
||||
channels_[x].count = channels_[x].reload; \
|
||||
} else { \
|
||||
--channels_[x].count; \
|
||||
}
|
||||
poly_state_[int(Channel::Distortion::FourBit)] = poly4_.next();
|
||||
poly_state_[int(Channel::Distortion::FiveBit)] = poly5_.next();
|
||||
poly_state_[int(Channel::Distortion::SevenBit)] = poly7_.next();
|
||||
|
||||
// TODO: substitute poly_state_[2] if polynomial substitution is in play.
|
||||
|
||||
#define update_channel(x) { \
|
||||
auto output = channels_[x].output & 1; \
|
||||
channels_[x].output <<= 1; \
|
||||
if(!channels_[x].count) { \
|
||||
channels_[x].count = channels_[x].reload; \
|
||||
\
|
||||
if(channels_[x].distortion == Channel::Distortion::None) \
|
||||
output ^= 1; \
|
||||
else \
|
||||
output = poly_state_[int(channels_[x].distortion)]; \
|
||||
\
|
||||
if(channels_[x].high_pass && (channels_[(x+1)%3].output&3) == 2) { \
|
||||
output = 0; \
|
||||
} \
|
||||
if(channels_[x].ring_modulate) { \
|
||||
output = ~(output ^ channels_[(x+2)%3].output) & 1; \
|
||||
} \
|
||||
} else { \
|
||||
--channels_[x].count; \
|
||||
} \
|
||||
channels_[x].output |= output; \
|
||||
}
|
||||
|
||||
update_channel(0);
|
||||
update_channel(1);
|
||||
@ -69,16 +89,16 @@ void Dave::get_samples(std::size_t number_of_samples, int16_t *target) {
|
||||
// Dumbest ever first attempt: sum channels.
|
||||
target[(c << 1) + 0] =
|
||||
volume_ * (
|
||||
channels_[0].amplitude[0] * channels_[0].output +
|
||||
channels_[1].amplitude[0] * channels_[1].output +
|
||||
channels_[2].amplitude[0] * channels_[2].output
|
||||
channels_[0].amplitude[0] * (channels_[0].output & 1) +
|
||||
channels_[1].amplitude[0] * (channels_[1].output & 1) +
|
||||
channels_[2].amplitude[0] * (channels_[2].output & 1)
|
||||
);
|
||||
|
||||
target[(c << 1) + 1] =
|
||||
volume_ * (
|
||||
channels_[0].amplitude[1] * channels_[0].output +
|
||||
channels_[1].amplitude[1] * channels_[1].output +
|
||||
channels_[2].amplitude[1] * channels_[2].output
|
||||
channels_[0].amplitude[1] * (channels_[0].output & 1) +
|
||||
channels_[1].amplitude[1] * (channels_[1].output & 1) +
|
||||
channels_[2].amplitude[1] * (channels_[2].output & 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -41,27 +41,32 @@ class Dave: public Outputs::Speaker::SampleSource {
|
||||
bool high_pass = false;
|
||||
bool ring_modulate = false;
|
||||
enum class Distortion {
|
||||
None,
|
||||
FourBit,
|
||||
FiveBit,
|
||||
SevenBit,
|
||||
None = 0,
|
||||
FourBit = 1,
|
||||
FiveBit = 2,
|
||||
SevenBit = 3,
|
||||
} distortion = Distortion::None;
|
||||
uint8_t amplitude[2]{};
|
||||
|
||||
// Current state.
|
||||
uint16_t count = 0;
|
||||
bool output = true;
|
||||
int output = 0;
|
||||
} channels_[3];
|
||||
int16_t volume_ = 0;
|
||||
|
||||
// Various polynomials that contribute to audio generation.
|
||||
// Polynomials that are always running.
|
||||
Numeric::LFSRv<0xc> poly4_;
|
||||
Numeric::LFSRv<0x14> poly5_;
|
||||
Numeric::LFSRv<0x60> poly7_;
|
||||
|
||||
// The selectable, noise-related polynomial.
|
||||
Numeric::LFSRv<0x110> poly9_;
|
||||
Numeric::LFSRv<0x500> poly11_;
|
||||
Numeric::LFSRv<0x6000> poly15_;
|
||||
Numeric::LFSRv<0x12000> poly17_;
|
||||
|
||||
// Current state of the active polynomials.
|
||||
uint8_t poly_state_[4];
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ template <bool has_disk_controller> class ConcreteMachine:
|
||||
page<3>(0x00);
|
||||
|
||||
// Set up audio.
|
||||
speaker_.set_input_rate(125000.0f); // TODO: a bigger number, and respect the programmable divider.
|
||||
speaker_.set_input_rate(250000.0f); // TODO: a bigger number, and respect the programmable divider.
|
||||
|
||||
// Pass on any media.
|
||||
insert_media(target.media);
|
||||
@ -368,7 +368,9 @@ template <bool has_disk_controller> class ConcreteMachine:
|
||||
}
|
||||
|
||||
inline void update_audio() {
|
||||
speaker_.run_for(audio_queue_, time_since_audio_update_.divide_cycles(Cycles(32)));
|
||||
// TODO: divide by only 8, letting Dave divide itself by a further 2 or 3
|
||||
// as per its own register.
|
||||
speaker_.run_for(audio_queue_, time_since_audio_update_.divide_cycles(Cycles(16)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user