1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 2 3 #include "smmorphlfomodule.hh" 4 #include "smmorphlfo.hh" 5 #include "smmorphplan.hh" 6 #include "smwavsetrepo.hh" 7 #include "smleakdebugger.hh" 8 #include "smmorphplanvoice.hh" 9 #include "smmorphplansynth.hh" 10 #include "smmath.hh" 11 12 using namespace SpectMorph; 13 14 using std::string; 15 using std::vector; 16 using std::max; 17 18 static LeakDebugger leak_debugger ("SpectMorph::MorphLFOModule"); 19 20 MorphLFOModule::MorphLFOModule (MorphPlanVoice *voice) : 21 MorphOperatorModule (voice) 22 { 23 leak_debugger.add (this); 24 25 shared_state = NULL; 26 } 27 28 MorphLFOModule::~MorphLFOModule() 29 { 30 leak_debugger.del (this); 31 } 32 33 static double 34 normalize_phase (double phase) 35 { 36 return fmod (phase + 1, 1); 37 } 38 39 void 40 MorphLFOModule::set_config (MorphOperator *op) 41 { 42 MorphLFO *lfo = dynamic_cast<MorphLFO *> (op); 43 44 frequency = lfo->frequency(); 45 depth = lfo->depth(); 46 center = lfo->center(); 47 start_phase = lfo->start_phase(); 48 sync_voices = lfo->sync_voices(); 49 wave_type = lfo->wave_type(); 50 beat_sync = lfo->beat_sync(); 51 note = lfo->note(); 52 note_mode = lfo->note_mode(); 53 54 MorphPlanSynth *synth = morph_plan_voice->morph_plan_synth(); 55 if (synth) 56 { 57 shared_state = dynamic_cast<SharedState *> (synth->shared_state (op)); 58 if (!shared_state) 59 { 60 shared_state = new SharedState(); 61 restart_lfo (shared_state->global_lfo_state, /* start from zero time */ TimeInfo()); 62 synth->set_shared_state (op, shared_state); 63 } 64 } 65 } 66 67 float 68 MorphLFOModule::value() 69 { 70 TimeInfo time = time_info(); 71 72 if (sync_voices) 73 { 74 auto lfo_state = shared_state->global_lfo_state; 75 update_lfo_value (lfo_state, time); 76 77 return lfo_state.value; 78 } 79 else 80 { 81 update_lfo_value (local_lfo_state, time); 82 return local_lfo_state.value; 83 } 84 } 85 86 void 87 MorphLFOModule::reset_value (const TimeInfo& time_info) 88 { 89 restart_lfo (local_lfo_state, time_info); 90 } 91 92 void 93 MorphLFOModule::restart_lfo (LFOState& state, const TimeInfo& time_info) 94 { 95 state = LFOState(); /* reset to defaults */ 96 state.last_random_value = random_gen()->random_double_range (-1, 1); 97 state.random_value = random_gen()->random_double_range (-1, 1); 98 /* compute initial value */ 99 TimeInfo zero_time; 100 update_lfo_value (state, zero_time); 101 state.last_time_ms = time_info.time_ms; 102 state.last_ppq_pos = time_info.ppq_pos; 103 } 104 105 void 106 MorphLFOModule::update_lfo_value (LFOState& state, const TimeInfo& time_info) 107 { 108 if (!beat_sync) 109 { 110 if (time_info.time_ms > state.last_time_ms) 111 state.raw_phase += (time_info.time_ms - state.last_time_ms) / 1000 * frequency; 112 state.last_time_ms = time_info.time_ms; 113 } 114 else 115 { 116 if (time_info.ppq_pos > state.last_ppq_pos) 117 { 118 /* If sync_voices is disabled, each note should have its own phase. 119 * 120 * To compute this, we want to know how long the note has been playing. 121 * ppq_count tries to do this even in presence of backward jumps as 122 * they are caused by loops. There is a small error here, during 123 * jumps, but the result should be acceptable. 124 */ 125 state.ppq_count += time_info.ppq_pos - state.last_ppq_pos; 126 } 127 state.last_ppq_pos = time_info.ppq_pos; 128 129 double factor = pow (2, (MorphLFO::NOTE_1_4 - note)); // <- tempo is relative to quarter notes 130 switch (note_mode) 131 { 132 case MorphLFO::NOTE_MODE_TRIPLET: 133 factor *= 2.0 / 3.0; 134 break; 135 case MorphLFO::NOTE_MODE_DOTTED: 136 factor *= 3.0 / 2.0; 137 break; 138 default: 139 ; 140 } 141 if (sync_voices) 142 state.raw_phase = time_info.ppq_pos / factor; 143 else 144 state.raw_phase = state.ppq_count / factor; 145 } 146 const double old_phase = state.phase; 147 state.phase = normalize_phase (state.raw_phase + start_phase / 360); 148 constexpr double epsilon = 1 / 1000.; // reliable comparision of floating point values 149 if (state.phase + epsilon < old_phase) 150 { 151 // retrigger random lfo 152 state.last_random_value = state.random_value; 153 state.random_value = random_gen()->random_double_range (-1, 1); 154 } 155 156 if (wave_type == MorphLFO::WAVE_SINE) 157 { 158 state.value = sin (state.phase * M_PI * 2); 159 } 160 else if (wave_type == MorphLFO::WAVE_TRIANGLE) 161 { 162 if (state.phase < 0.25) 163 { 164 state.value = 4 * state.phase; 165 } 166 else if (state.phase < 0.75) 167 { 168 state.value = (state.phase - 0.5) * -4; 169 } 170 else 171 { 172 state.value = 4 * (state.phase - 1); 173 } 174 } 175 else if (wave_type == MorphLFO::WAVE_SAW_UP) 176 { 177 state.value = -1 + 2 * state.phase; 178 } 179 else if (wave_type == MorphLFO::WAVE_SAW_DOWN) 180 { 181 state.value = 1 - 2 * state.phase; 182 } 183 else if (wave_type == MorphLFO::WAVE_SQUARE) 184 { 185 if (state.phase < 0.5) 186 state.value = -1; 187 else 188 state.value = 1; 189 } 190 else if (wave_type == MorphLFO::WAVE_RANDOM_SH) 191 { 192 state.value = state.random_value; 193 } 194 else if (wave_type == MorphLFO::WAVE_RANDOM_LINEAR) 195 { 196 state.value = state.last_random_value * (1 - state.phase) + state.random_value * state.phase; 197 } 198 else 199 { 200 g_assert_not_reached(); 201 } 202 203 state.value = state.value * depth + center; 204 state.value = CLAMP (state.value, -1.0, 1.0); 205 } 206 207 void 208 MorphLFOModule::update_shared_state (const TimeInfo& time_info) 209 { 210 update_lfo_value (shared_state->global_lfo_state, time_info); 211 } 212