1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-07 08:28:57 +00:00

Starts implementing noise.

This commit is contained in:
Thomas Harte 2021-06-26 23:48:53 -04:00
parent f8bb66d2a0
commit fcd267a3f9
2 changed files with 55 additions and 10 deletions

View File

@ -26,26 +26,36 @@ void Dave::write(uint16_t address, uint8_t value) {
channels_[address >> 1].high_pass = value & 0x40;
channels_[address >> 1].ring_modulate = value & 0x80;
break;
case 6:
noise_.frequency = Noise::Frequency(value&3);
noise_.polynomial = Noise::Polynomial((value >> 2)&3);
noise_.swap_polynomial = value & 0x10;
noise_.low_pass = value & 0x20;
noise_.high_pass = value & 0x40;
noise_.ring_modulate = value & 0x80;
break;
// TODO:
//
// 6: noise selection.
// 7: sync bits, optional D/As, interrupt rate (albeit some of that shouldn't be on this thread, or possibly even _here_).
// 11, 14: noise amplitude.
// 7: sync bits, optional D/As.
//
// (will handle interrupt bits elsewhere)
case 8: case 9: case 10:
channels_[address - 8].amplitude[0] = value & 0x3f;
break;
case 11: case 12: case 13:
channels_[address - 11].amplitude[1] = value & 0x3f;
case 12: case 13: case 14:
channels_[address - 12].amplitude[1] = value & 0x3f;
break;
case 11: noise_.amplitude[0] = value & 0x3f; break;
case 15: noise_.amplitude[1] = value & 0x3f; break;
}
});
}
void Dave::set_sample_volume_range(int16_t range) {
audio_queue_.defer([range, this] {
volume_ = range / (63*3);
volume_ = range / (63*4);
});
}
@ -54,9 +64,11 @@ void Dave::get_samples(std::size_t number_of_samples, int16_t *target) {
poly_state_[int(Channel::Distortion::FourBit)] = poly4_.next();
poly_state_[int(Channel::Distortion::FiveBit)] = poly5_.next();
poly_state_[int(Channel::Distortion::SevenBit)] = poly7_.next();
if(noise_.swap_polynomial) {
poly_state_[int(Channel::Distortion::SevenBit)] = poly_state_[int(Channel::Distortion::None)];
}
// TODO: substitute poly_state_[2] if polynomial substitution is in play.
// Update tone channels.
#define update_channel(x) { \
auto output = channels_[x].output & 1; \
channels_[x].output <<= 1; \
@ -86,19 +98,23 @@ void Dave::get_samples(std::size_t number_of_samples, int16_t *target) {
#undef update_channel
// TODO: update noise channel.
// Dumbest ever first attempt: sum channels.
target[(c << 1) + 0] =
volume_ * (
channels_[0].amplitude[0] * (channels_[0].output & 1) +
channels_[1].amplitude[0] * (channels_[1].output & 1) +
channels_[2].amplitude[0] * (channels_[2].output & 1)
channels_[2].amplitude[0] * (channels_[2].output & 1) +
noise_.amplitude[0] * noise_.output
);
target[(c << 1) + 1] =
volume_ * (
channels_[0].amplitude[1] * (channels_[0].output & 1) +
channels_[1].amplitude[1] * (channels_[1].output & 1) +
channels_[2].amplitude[1] * (channels_[2].output & 1)
channels_[2].amplitude[1] * (channels_[2].output & 1) +
noise_.amplitude[1] * noise_.output
);
}
}

View File

@ -35,6 +35,7 @@ class Dave: public Outputs::Speaker::SampleSource {
private:
Concurrency::DeferringAsyncTaskQueue &audio_queue_;
// Tone channels.
struct Channel {
// User-set values.
uint16_t reload = 0;
@ -52,6 +53,34 @@ class Dave: public Outputs::Speaker::SampleSource {
uint16_t count = 0;
int output = 0;
} channels_[3];
// Noise channel.
struct Noise {
// User-set values.
uint8_t amplitude[2]{};
enum class Frequency {
DivideByFour,
ToneChannel0,
ToneChannel1,
ToneChannel2,
} frequency = Frequency::DivideByFour;
enum class Polynomial {
SeventeenBit,
FifteenBit,
ElevenBit,
NineBit
} polynomial = Polynomial::SeventeenBit;
bool swap_polynomial = false;
bool low_pass = false;
bool high_pass = false;
bool ring_modulate = false;
// Current state.
bool output = false;
uint16_t count = 0;
} noise_;
// Global volume, per SampleSource obligations.
int16_t volume_ = 0;
// Polynomials that are always running.