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