mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-07 23:29:06 +00:00
Starts trying to make sense of the various fields at play.
This commit is contained in:
parent
dd6769bfbc
commit
a0d14f4030
@ -185,7 +185,7 @@ void OPLL::write_register(uint8_t address, uint8_t value) {
|
|||||||
if(address >= 0x20 && address <= 0x28) {
|
if(address >= 0x20 && address <= 0x28) {
|
||||||
const auto index = address - 0x20;
|
const auto index = address - 0x20;
|
||||||
channels_[index].frequency = (channels_[index].frequency & 0xff) | (value & 1);
|
channels_[index].frequency = (channels_[index].frequency & 0xff) | (value & 1);
|
||||||
channels_[index].octave = (value >> 1) & 7;
|
channels_[index].octave = (value >> 1) & 0x7;
|
||||||
channels_[index].key_on = value & 0x10;
|
channels_[index].key_on = value & 0x10;
|
||||||
channels_[index].hold_sustain_level = value & 0x20;
|
channels_[index].hold_sustain_level = value & 0x20;
|
||||||
return;
|
return;
|
||||||
@ -198,8 +198,8 @@ void OPLL::setup_fixed_instrument(int number, const uint8_t *data) {
|
|||||||
auto carrier = &operators_[number * 2 + 1];
|
auto carrier = &operators_[number * 2 + 1];
|
||||||
|
|
||||||
// Set waveforms — only sine and halfsine are available.
|
// Set waveforms — only sine and halfsine are available.
|
||||||
carrier->waveform = (data[3] & 0x10) ? 1 : 0;
|
carrier->waveform = Operator::Waveform((data[3] & 0x10) ? 1 : 0);
|
||||||
modulator->waveform = (data[3] & 0x08) ? 1 : 0;
|
modulator->waveform = Operator::Waveform((data[3] & 0x08) ? 1 : 0);
|
||||||
|
|
||||||
// Set modulator amplitude and key-scale level.
|
// Set modulator amplitude and key-scale level.
|
||||||
modulator->scaling_level = data[2] >> 6;
|
modulator->scaling_level = data[2] >> 6;
|
||||||
@ -317,7 +317,7 @@ void OPL2::write_register(uint8_t address, uint8_t value) {
|
|||||||
const auto index = operator_by_address[address - 0xe0];
|
const auto index = operator_by_address[address - 0xe0];
|
||||||
if(index == -1) return;
|
if(index == -1) return;
|
||||||
|
|
||||||
operators_[index].waveform = value & 3;
|
operators_[index].waveform = Operator::Waveform(value & 3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,18 +19,43 @@ namespace Yamaha {
|
|||||||
namespace OPL {
|
namespace OPL {
|
||||||
|
|
||||||
struct Operator {
|
struct Operator {
|
||||||
|
/// If true then an amplitude modulation of "3.7Hz" is applied,
|
||||||
|
/// with a depth "determined by the AM-DEPTH of the BD register"?
|
||||||
bool apply_amplitude_modulation = false;
|
bool apply_amplitude_modulation = false;
|
||||||
|
|
||||||
|
/// If true then a vibrato of '6.4 Hz' is applied, with a depth
|
||||||
|
/// "determined by VOB_DEPTH of the BD register"?
|
||||||
bool apply_vibrato = false;
|
bool apply_vibrato = false;
|
||||||
|
|
||||||
|
/// Selects between an ADSR envelope that holds at the sustain level
|
||||||
|
/// for as long as this key is on, releasing afterwards, and one that
|
||||||
|
/// simply switches straight to the release rate once the sustain
|
||||||
|
/// level is hit, getting back to 0 regardless of an ongoing key-on.
|
||||||
bool hold_sustain_level = false;
|
bool hold_sustain_level = false;
|
||||||
|
|
||||||
|
/// Provides a potential faster step through the ADSR envelope. Cf. p12.
|
||||||
bool keyboard_scaling_rate = false;
|
bool keyboard_scaling_rate = false;
|
||||||
|
|
||||||
|
/// Indexes a lookup table to determine what multiple of the channel's frequency
|
||||||
|
/// this operator is advancing at.
|
||||||
int frequency_multiple = 0;
|
int frequency_multiple = 0;
|
||||||
int scaling_level = 0;
|
|
||||||
|
/// Sets the current output level of this modulator, as an attenuation.
|
||||||
int output_level = 0;
|
int output_level = 0;
|
||||||
|
|
||||||
|
/// Selects attenuation that is applied as a function of interval. Cf. p14.
|
||||||
|
int scaling_level = 0;
|
||||||
|
|
||||||
|
/// Sets the ADSR rates.
|
||||||
int attack_rate = 0;
|
int attack_rate = 0;
|
||||||
int decay_rate = 0;
|
int decay_rate = 0;
|
||||||
int sustain_level = 0;
|
int sustain_level = 0;
|
||||||
int release_rate = 0;
|
int release_rate = 0;
|
||||||
int waveform = 0;
|
|
||||||
|
/// Selects the generated waveform.
|
||||||
|
enum class Waveform {
|
||||||
|
Sine, HalfSine, AbsSine, PulseSine
|
||||||
|
} waveform = Waveform::Sine;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Channel {
|
struct Channel {
|
||||||
@ -39,6 +64,22 @@ struct Channel {
|
|||||||
bool key_on = false;
|
bool key_on = false;
|
||||||
int feedback_strength = 0;
|
int feedback_strength = 0;
|
||||||
bool use_fm_synthesis = true;
|
bool use_fm_synthesis = true;
|
||||||
|
|
||||||
|
// This should be called at a rate of around 49,716 Hz.
|
||||||
|
void update() {
|
||||||
|
// Per the documentation:
|
||||||
|
// F-Num = Music Frequency * 2^(20-Block) / 49716
|
||||||
|
//
|
||||||
|
// Given that a 256-entry table is used to store a quarter of a sine wave,
|
||||||
|
// making 1024 steps per complete wave, add what I've called frequency
|
||||||
|
// to an accumulator and move on whenever that exceeds 2^(10 - octave).
|
||||||
|
//
|
||||||
|
// TODO: but, how does that apply to the two operator multipliers?
|
||||||
|
//
|
||||||
|
// Or: 2^19?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stateful information.
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Child> class OPLBase: public ::Outputs::Speaker::SampleSource {
|
template <typename Child> class OPLBase: public ::Outputs::Speaker::SampleSource {
|
||||||
|
Loading…
Reference in New Issue
Block a user