diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 3488b3538..6921eda0f 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -63,6 +63,7 @@ // #define LB_24_IGNORE_ENVELOPE #define LB_FILTERED +//#define LB_DECAY //#define LB_24_RES_TRICK #define LB_DIST_RATIO 4.0 @@ -105,7 +106,7 @@ plugin::descriptor lb302_plugin_descriptor = // lb302Filter // -lb302Filter::lb302Filter(lb302FilterState* p_fs) : +lb302Filter::lb302Filter(lb302FilterKnobState* p_fs) : fs(p_fs), vcf_c0(0), vcf_e0(0), @@ -120,12 +121,14 @@ void lb302Filter::recalc() vcf_e0*=M_PI/44100.0; vcf_e1*=M_PI/44100.0; vcf_e1 -= vcf_e0; + + vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso)); }; void lb302Filter::envRecalc() { vcf_c0 *= fs->envdecay; // Filter Decay. vcf_decay is adjusted for Hz and ENVINC - vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso)); + // vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso)); moved above }; void lb302Filter::playNote() @@ -137,7 +140,7 @@ void lb302Filter::playNote() // lb302FilterIIR2 // -lb302FilterIIR2::lb302FilterIIR2(lb302FilterState* p_fs) : +lb302FilterIIR2::lb302FilterIIR2(lb302FilterKnobState* p_fs) : lb302Filter(p_fs), vcf_d1(0), vcf_d2(0), @@ -196,12 +199,30 @@ float lb302FilterIIR2::process(const float& samp) return ret; } +void lb302FilterIIR2::getState(lb302FilterState* fs) +{ + fs->iir.vcf_c0 = vcf_c0; + fs->iir.vcf_a = vcf_a; + fs->iir.vcf_b = vcf_b; + fs->iir.vcf_c = vcf_c; + fs->iir.vcf_d1 = vcf_d1; + fs->iir.vcf_d2 = vcf_d2; +} +void lb302FilterIIR2::setState(const lb302FilterState* fs) +{ + vcf_c0 = fs->iir.vcf_c0; + vcf_a = fs->iir.vcf_a; + vcf_b = fs->iir.vcf_b; + vcf_c = fs->iir.vcf_c; + vcf_d1 = fs->iir.vcf_d1; + vcf_d2 = fs->iir.vcf_d2; +} // // lb302Filter3Pole // -lb302Filter3Pole::lb302Filter3Pole(lb302FilterState *p_fs) : +lb302Filter3Pole::lb302Filter3Pole(lb302FilterKnobState *p_fs) : lb302Filter(p_fs), ay1(0), ay2(0), @@ -265,6 +286,31 @@ float lb302Filter3Pole::process(const float& samp) return tanh(aout*value)*LB_24_VOL_ADJUST/(1.0+fs->dist); } +void lb302Filter3Pole::getState(lb302FilterState* fs) +{ + fs->pole.aout = aout; + fs->pole.vcf_c0 = vcf_c0; + fs->pole.kp = kp; + fs->pole.kp1h = kp1h; + fs->pole.kres = kres; + fs->pole.ay1 = ay1; + fs->pole.ay2 = ay2; + fs->pole.lastin = lastin; + fs->pole.value = value; +} + +void lb302Filter3Pole::setState(const lb302FilterState* fs) +{ + aout = fs->pole.aout; + vcf_c0 = fs->pole.vcf_c0; + kp = fs->pole.kp; + kp1h = fs->pole.kp1h; + kres = fs->pole.kres; + ay1 = fs->pole.ay1; + ay2 = fs->pole.ay2; + lastin = fs->pole.lastin; + value = fs->pole.value; +} // // LBSynth @@ -409,6 +455,7 @@ lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : vco_k = 0; vco_slide = 0; vco_slideinc = 0; + vco_slidebase = 0; fs.cutoff = 0; fs.envmod = 0; fs.reso = 0; fs.envdecay = 0; @@ -417,7 +464,7 @@ lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : vcf_envpos = ENVINC; vco_detune = 0; - vca_mode = 0; vca_a = 0; // Start VCA on an attack. + vca_mode = 3; vca_a = 0; // Start VCA on an attack. //vca_attack = 1.0 - 0.94406088; vca_attack = 1.0 - 0.96406088; @@ -426,9 +473,17 @@ lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : vco_shape = SAWTOOTH; vca_a0 = 0.5; // Experimenting between original (0.5) and 1.0 + vca_a = 9; + vca_mode = 3; vcf = new lb302FilterIIR2(&fs); + use_hold_note = false; + sample_cnt = 0; + release_frame = 1<<24; + catch_frame = 0; + catch_decay = 0; + recalcFilter(); lastFramesPlayed = 1; // because we subtract 1 later @@ -436,7 +491,6 @@ lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : period_states = NULL; period_states_cnt = 0; - note_count = 0; filterChanged(0.0); detuneChanged(0.0); @@ -594,6 +648,7 @@ int lb302Synth::process(sampleFrame *outbuf, const Uint32 size) float samp; + printf("process\n"); for(i=0;irelease_frame) { + if(i>=release_frame) { vca_mode=1; - }*/ + printf("Releasing!\n"); + } // Handle Envelope // TODO: Add decay once I figure out how to extend past the end of a note. @@ -721,17 +777,17 @@ int lb302Synth::process(sampleFrame *outbuf, const Uint32 size) } else if(vca_mode == 1) { vca_a *= vca_decay; - //printf("VCA: %d %f\n", dbgshit++, vca_a); + printf("VCA: %d %f\n", i, vca_a); // the following line actually speeds up processing - if(vca_a < (1/65536.0)) { vca_a = 0; vca_mode = 2; } + if(vca_a < (1/65536.0)) { vca_a = 0; vca_mode = 3; } } // Store state period_states[i].vco_c = vco_c; period_states[i].vca_a = vca_a; // Doesn't change anything (currently) period_states[i].vca_mode = vca_mode; // Doesn't change anything (currently) period_states[i].sample_cnt = sample_cnt; // Doesn't change anything (currently) - + vcf->getState(&period_states[i].fs); } return 1; @@ -748,10 +804,13 @@ void lb302Synth::initNote( lb302Note *n) vco_inc = n->vco_inc; // TODO: Try moving to the if() below - if(n->dead == 0) { + if(n->dead == 0 || (vca_mode==1 || vca_mode==3)) { sample_cnt = 0; vca_mode = 0; vca_a = 0; } + else { + vca_mode = 2; + } // Initiate Slide // TODO: Break out into function, should be called again on detuneChanged @@ -878,9 +937,18 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) ///=== WEIRD CODE FOR MONOPHONIC BEHAVIOUR - END === /// /// Malloc our period history buffer - if (period_states == NULL) + if (period_states == NULL) { period_states = new lb302State[framesPerPeriod]; + for (int i=0; i < framesPerPeriod; i++) { + period_states[i].vco_c = vco_c; + period_states[i].vca_a = vca_a; // Doesn't change anything (currently) + period_states[i].vca_mode = vca_mode; // Doesn't change anything (currently) + period_states[i].sample_cnt = sample_cnt; // Doesn't change anything (currently) + vcf->getState(&period_states[i].fs); + } + } + // now resume at the proper position and process as usual lb302State *state = &period_states[resume_pos]; @@ -890,7 +958,7 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) vca_a = state->vca_a; vca_mode = state->vca_mode; sample_cnt = state->sample_cnt; - + vcf->setState(&state->fs); /// Currently have release/decay disabled @@ -900,12 +968,14 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) release_frame = _n->framesLeft() - desiredReleaseFrames(); + printf("release at %d\n", release_frame); if ( _n->totalFramesPlayed() <= 0 ) { /// This code is obsolete, hence the "if false" // Existing note. Allow it to decay. if(deadToggle->value()==0 && decay_note) { +#ifdef LB_DECAY if (catch_decay < 1) { // BEGIN NOT SURE OF... //lb302State *st = &period_states[period_states_cnt-1]; @@ -919,6 +989,18 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) use_hold_note = true; catch_decay = 1; } + else { + printf("Oh no!\n"); + } +#else + lb302Note note; + note.vco_inc = _n->frequency()*vco_detune/LB_HZ; // TODO: Use actual sampling rate. + note.dead = deadToggle->value(); + initNote(¬e); + vca_mode=0; + vca_a = state->vca_a; + +#endif } /// Start a new note. else { @@ -929,7 +1011,6 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) use_hold_note = false; } - note_count=1; } sampleFrame *buf = new sampleFrame[frames]; diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index 22478593e..0311394e7 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -41,7 +41,7 @@ class knob; class notePlayHandle; -class lb302FilterState +class lb302FilterKnobState { public: float cutoff; @@ -51,10 +51,43 @@ class lb302FilterState float dist; }; +class lb302FilterIIR2State +{ + public: + float vcf_c0; + float vcf_a; + float vcf_b; + float vcf_c; + float vcf_d1; + float vcf_d2; +}; + +class lb302Filter3PoleState +{ + public: + float vcf_c0; + float kp, + kp1h, + kres, + ay1, + ay2, + lastin, + value; + float aout; +}; + +typedef union +{ + lb302FilterIIR2State iir; + lb302Filter3PoleState pole; +} +lb302FilterState; + + class lb302Filter { public: - lb302Filter(lb302FilterState* p_fs); + lb302Filter(lb302FilterKnobState* p_fs); virtual ~lb302Filter() {}; virtual void recalc(); @@ -62,8 +95,11 @@ class lb302Filter virtual float process(const float& samp)=0; virtual void playNote(); + virtual void getState(lb302FilterState* fs)=0; + virtual void setState(const lb302FilterState* fs)=0; + protected: - lb302FilterState *fs; + lb302FilterKnobState *fs; // Filter Decay float vcf_c0; // c0=e1 on retrigger; c0*=ed every sample; cutoff=e0+c0 @@ -75,13 +111,16 @@ class lb302Filter class lb302FilterIIR2 : public lb302Filter { public: - lb302FilterIIR2(lb302FilterState* p_fs); + lb302FilterIIR2(lb302FilterKnobState* p_fs); virtual ~lb302FilterIIR2(); virtual void recalc(); virtual void envRecalc(); virtual float process(const float& samp); + virtual void getState(lb302FilterState* fs); + virtual void setState(const lb302FilterState* fs); + protected: float vcf_d1, // d1 and d2 are added back into the sample with vcf_d2; // vcf_a and b as coefficients. IIR2 resonance @@ -96,16 +135,20 @@ class lb302FilterIIR2 : public lb302Filter effectLib::distortion<> * m_dist; }; + class lb302Filter3Pole : public lb302Filter { public: - lb302Filter3Pole(lb302FilterState* p_fs); + lb302Filter3Pole(lb302FilterKnobState* p_fs); //virtual void recalc(); virtual void envRecalc(); virtual void recalc(); virtual float process(const float& samp); + virtual void getState(lb302FilterState* fs); + virtual void setState(const lb302FilterState* fs); + protected: float kfcn, kp, @@ -119,6 +162,8 @@ class lb302Filter3Pole : public lb302Filter value; }; + + class lb302State { public: @@ -126,6 +171,8 @@ public: float vca_a; int vca_mode; int sample_cnt; + + lb302FilterState fs; }; class lb302Note @@ -160,7 +207,7 @@ public: virtual f_cnt_t desiredReleaseFrames( void ) const { - return 512; + return 4048; } private: @@ -212,7 +259,7 @@ private: vco_shape_t vco_shape; // User settings - lb302FilterState fs; + lb302FilterKnobState fs; lb302Filter *vcf; lb302Note hold_note; bool use_hold_note; @@ -242,7 +289,6 @@ private: int catch_frame; int catch_decay; - int note_count; void recalcFilter();