diff --git a/plugin/chassis.cpp b/plugin/chassis.cpp index 230daef..6006ba2 100644 --- a/plugin/chassis.cpp +++ b/plugin/chassis.cpp @@ -56,9 +56,15 @@ void Chassis::activate() { s.pitchCV[i] = (440.0f * powf(2, (i - 49) / 12.0f)) / sampleRate; } - //ic1.ram[0xc6] = 0x42; - //ic1.ram[0xb6] = 0; - //ic1.resetVoices(); + // resetvoices + for (uint8_t i=0; i<8; i++) { + s.noteTbl[i] = 0x80; + s.voiceTbl[i] = i; + s.voice[i].phase = (0.7*((rand()%65536)/65536.0f));//(60*s.voice[i].omega*i); + printf("%f %d\n", s.voice[i].phase, i); + + } + } void Chassis::deactivate() { @@ -67,13 +73,33 @@ void Chassis::deactivate() { } void Chassis::noteOn(uint8_t note) { - uint32_t i; + // needed for LFO for now + s.keyon = true; + // Unison Voice On + for (uint8_t i=0; i<8; i++ ) { + //s.noteTbl[i] = note; + s.voice[i].on(note, false); + s.voice[i].voicenum=i; + // printf("%f %i\n", s.voice[i].phase, i); + + } + + //s.voice[vPtr].on(note, true); + } void Chassis::noteOff(uint8_t note) { + // Unison Voice On + for (uint8_t i=0; i<8; i++ ) { + //s.noteTbl[i] = note; + s.voice[i].off(); + } + // s.voice[i].off(); + s.keyon=false; + } void Chassis::doMidi(const MidiEvent *ev, uint32_t count, uint32_t timeLimit) { diff --git a/plugin/chassis.hpp b/plugin/chassis.hpp index fc78c7b..38db6d9 100644 --- a/plugin/chassis.hpp +++ b/plugin/chassis.hpp @@ -64,8 +64,10 @@ class Chassis : public Plugin { paramChorusMode, paramPolyMode, - + paramUnisonDetune, + paramModWheel, + parameterCount }; diff --git a/plugin/ic1.cpp b/plugin/ic1.cpp index 7c4417a..5c99983 100644 --- a/plugin/ic1.cpp +++ b/plugin/ic1.cpp @@ -236,6 +236,8 @@ // 019c: 63 bf STAW $FFBF // save flag // scan keys again +// this populates the key scan table +// and also decides if we need to emit some MIDI // 019e: 24 ff 1f LXI DE,$1FFF // keypad MUX // 01a1: 34 50 ff LXI HL,$FF50 // key bitfield // 01a4: 6a e8 MVI B,$E8 // first column diff --git a/plugin/ic1.hpp b/plugin/ic1.hpp index 16820c0..b7b6190 100644 --- a/plugin/ic1.hpp +++ b/plugin/ic1.hpp @@ -38,7 +38,11 @@ class Assigner { uint16_t a = 0, b = 0, c = 0, eal = 0, eah = 0; uint32_t bc, de, hl, ea = 0; - +/* +23:31 < Alipha> gordonjcp: struct reg16 { uint16_t value; uint8_t hi() const { return value >> 8; } uint8_t lo() const { return value; + } }; +23:31 < gordonjcp> Alipha +*/ }; diff --git a/plugin/parameters.cpp b/plugin/parameters.cpp index 8c350a4..d94fcfd 100644 --- a/plugin/parameters.cpp +++ b/plugin/parameters.cpp @@ -300,6 +300,7 @@ void Chassis::initParameter(uint32_t index, Parameter& parameter) { parameter.midiCC = 93; break; +/* case paramPolyMode: parameter.hints = kParameterIsAutomatable | kParameterIsInteger; parameter.name = "Poly"; @@ -322,8 +323,16 @@ void Chassis::initParameter(uint32_t index, Parameter& parameter) { } break; - - +*/ + case paramUnisonDetune: + parameter.hints = kParameterIsAutomatable; + parameter.name = "Detune"; + parameter.symbol = "ch_detune"; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 1.0f; + parameter.ranges.def = 0.2f; + parameter.midiCC=84; + break; case paramModWheel: parameter.hints = kParameterIsAutomatable | kParameterIsHidden; @@ -332,7 +341,7 @@ void Chassis::initParameter(uint32_t index, Parameter& parameter) { parameter.ranges.min = 0.0f; parameter.ranges.max = 127.0f; parameter.ranges.def = 0.0f; - parameter.midiCC = 1; + //parameter.midiCC = 1; break; } // chorus, porta, bend range, key mode still to do @@ -441,8 +450,12 @@ void Chassis::setParameterValue(uint32_t index, float value) { case paramModWheel: s.ff64 = (int)value << 1; break; - case paramPolyMode: - s.polymode = (int)value; + //case paramPolyMode: + // s.polymode = (int)value; + // break; + + case paramUnisonDetune: + s.unisonDetune = value; break; } } @@ -530,6 +543,10 @@ float Chassis::getParameterValue(uint32_t index) const { case paramVCALevel: return s.patchRam.vca; + break; + + case paramUnisonDetune: + return s.unisonDetune; break; } return 0; diff --git a/plugin/voice.cpp b/plugin/voice.cpp index 3a3abc8..9dfcdb2 100644 --- a/plugin/voice.cpp +++ b/plugin/voice.cpp @@ -42,16 +42,17 @@ void Voice::run(Synth &s, float *buffer, uint32_t samples) { float fb, res = s.patchRam.vcfReso / 28.0f; // guess float cut = 248.0f * (powf(2, (vcfenv - 0x1880) / 1143.0f)); + cut *= (1-detune[voicenum]); // now radians cut = 0.25 * 6.2832 * cut / 48000.0f; // now correct cut = cut / (1 + cut); - float sqr = (s.patchRam.switch1 & 0x08) ? 0.65 : 0; //? 0.175 : 0; - float saw = (s.patchRam.switch1 & 0x10) ? 0.83 : 0; //? 0.220 : 0; - float sub = (s.patchRam.sub / 127.0f); // * 0.275; - // noise is 0.8 + float sqr = (s.patchRam.switch1 & 0x08) ? 0.65 : 0; + float saw = (s.patchRam.switch1 & 0x10) ? 0.83 : 0; + float sub = (s.patchRam.sub / 127.0f); + float noise = (s.patchRam.noise / 127.0f) * 0.8; float gain = 0.5*powf(2, (4*s.patchRam.vca / 127.0f) - 1.0f); @@ -101,6 +102,11 @@ void Voice::run(Synth &s, float *buffer, uint32_t samples) { // out = (2 * y) - 1; out = y; + + lcg = (lcg*519)+3; + + out += noise * ((lcg / 2147483647.0f)-1); + // widthDelay = pw; out *= 0.707; @@ -122,7 +128,7 @@ void Voice::run(Synth &s, float *buffer, uint32_t samples) { lastpw = pw; // gain for fully resonant needs to be 128mV output - out = b4 * (0.625); + out = b4 * (0.1625); buffer[i] += (gain * out * vr58c106); } diff --git a/plugin/voice.hpp b/plugin/voice.hpp index 918265a..dde404c 100644 --- a/plugin/voice.hpp +++ b/plugin/voice.hpp @@ -27,6 +27,8 @@ class Synth; class Voice { public: uint8_t note = 60; // per-voice note, set to middle C at 02b1h + float detune[8] = {-0.13, -0.09, -0.05, -0.025, 0.018, 0.06, 0.11, 0.16}; + uint8_t voicenum; void on(uint32_t key, bool reset); void off(); @@ -40,6 +42,8 @@ class Voice { float omega; uint16_t vcfenv; + float phase = 0, subosc = 1; + private: enum { ATTACK, @@ -61,10 +65,10 @@ class Voice { uint16_t env; - float phase = 0, subosc = 1; // float env, target; float delay; uint8_t pulseStage = 0; + uint32_t lcg; float lastpw = 0; float vr58c106 = 0; @@ -80,6 +84,10 @@ class Synth { uint32_t framesLeft = 0; uint8_t polymode; + uint8_t noteTbl[8]; + uint8_t voiceTbl[8]; + + float unisonDetune; bool keyon; uint8_t ff63 = 0; diff --git a/plugin/voicecpu.cpp b/plugin/voicecpu.cpp index 4ca2ff7..42a0bb4 100644 --- a/plugin/voicecpu.cpp +++ b/plugin/voicecpu.cpp @@ -296,6 +296,10 @@ h0407: h0432: // printf("setting omega for note %d \n", a); omega = ((s.pitchCV[a + 1] - s.pitchCV[a]) * (s.ff6e / 256.0)) + s.pitchCV[a]; + + omega *= 1 + (s.unisonDetune*0.25*detune[voicenum]); + //printf("%f %f %d\n", s.unisonDetune, omega, voicenum); + //phase = (2.4*omega*voicenum); // 0432 onwards calculates the address for the CV // table at E60 and stacks it // 043a onwards fetches the value from the divider