1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 
3 #include "smmorphlfo.hh"
4 #include "smmorphplan.hh"
5 #include "smleakdebugger.hh"
6 
7 #include <assert.h>
8 
9 using namespace SpectMorph;
10 
11 using std::string;
12 using std::vector;
13 
14 static LeakDebugger leak_debugger ("SpectMorph::MorphLFO");
15 
MorphLFOProperties(MorphLFO * lfo)16 MorphLFOProperties::MorphLFOProperties (MorphLFO *lfo) :
17   frequency (lfo, "Frequency", "%.3f Hz", 0.01, 10, &MorphLFO::frequency, &MorphLFO::set_frequency),
18   depth (lfo, "Depth", "-", 0, 1, &MorphLFO::depth, &MorphLFO::set_depth),
19   center (lfo, "Center", "%.2f", -1, 1, &MorphLFO::center, &MorphLFO::set_center),
20   start_phase (lfo, "Start Phase", "%.1f", -180, 180, &MorphLFO::start_phase, &MorphLFO::set_start_phase)
21 {
22   /* FIXME: ideally the storage format should be changed -> store depth as percent */
23   depth.set_custom_formatter ([](float f) -> string { return string_locale_printf ("%.1f %%", f * 100); });
24 }
25 
MorphLFO(MorphPlan * morph_plan)26 MorphLFO::MorphLFO (MorphPlan *morph_plan) :
27   MorphOperator (morph_plan)
28 {
29   m_wave_type = WAVE_SINE;
30   m_frequency = 1;
31   m_depth = 1;
32   m_center = 0;
33   m_start_phase = 0;
34   m_sync_voices = false;
35   m_beat_sync = false;
36   m_note = NOTE_1_4;
37   m_note_mode = NOTE_MODE_STRAIGHT;
38 
39   leak_debugger.add (this);
40 }
41 
~MorphLFO()42 MorphLFO::~MorphLFO()
43 {
44   leak_debugger.del (this);
45 }
46 
47 const char *
type()48 MorphLFO::type()
49 {
50   return "SpectMorph::MorphLFO";
51 }
52 
53 int
insert_order()54 MorphLFO::insert_order()
55 {
56   return 200;
57 }
58 
59 bool
save(OutFile & out_file)60 MorphLFO::save (OutFile& out_file)
61 {
62   out_file.write_int ("wave_type", m_wave_type);
63   out_file.write_float ("frequency", m_frequency);
64   out_file.write_float ("depth", m_depth);
65   out_file.write_float ("center", m_center);
66   out_file.write_float ("start_phase", m_start_phase);
67   out_file.write_bool ("sync_voices", m_sync_voices);
68   out_file.write_bool ("beat_sync", m_beat_sync);
69   out_file.write_int ("note", m_note);
70   out_file.write_int ("note_mode", m_note_mode);
71 
72   return true;
73 }
74 
75 bool
load(InFile & ifile)76 MorphLFO::load (InFile& ifile)
77 {
78   while (ifile.event() != InFile::END_OF_FILE)
79     {
80       if (ifile.event() == InFile::INT)
81         {
82           if (ifile.event_name() == "wave_type")
83             {
84               m_wave_type = static_cast<WaveType> (ifile.event_int());
85             }
86           else if (ifile.event_name() == "note")
87             {
88               m_note = static_cast<Note> (ifile.event_int());
89             }
90           else if (ifile.event_name() == "note_mode")
91             {
92               m_note_mode = static_cast<NoteMode> (ifile.event_int());
93             }
94           else
95             {
96               g_printerr ("bad int\n");
97               return false;
98             }
99         }
100       else if (ifile.event() == InFile::FLOAT)
101         {
102           if (ifile.event_name() == "frequency")
103             {
104               m_frequency = ifile.event_float();
105             }
106           else if (ifile.event_name() == "depth")
107             {
108               m_depth = ifile.event_float();
109             }
110           else if (ifile.event_name() == "center")
111             {
112               m_center = ifile.event_float();
113             }
114           else if (ifile.event_name() == "start_phase")
115             {
116               m_start_phase = ifile.event_float();
117             }
118           else
119             {
120               g_printerr ("bad float\n");
121               return false;
122             }
123         }
124       else if (ifile.event() == InFile::BOOL)
125         {
126           if (ifile.event_name() == "sync_voices")
127             {
128               m_sync_voices = ifile.event_bool();
129             }
130           else if (ifile.event_name() == "beat_sync")
131             {
132               m_beat_sync = ifile.event_bool();
133             }
134           else
135             {
136               g_printerr ("bad bool\n");
137               return false;
138             }
139         }
140       else
141         {
142           g_printerr ("bad event\n");
143           return false;
144         }
145       ifile.next_event();
146     }
147   return true;
148 }
149 
150 MorphOperator::OutputType
output_type()151 MorphLFO::output_type()
152 {
153   return OUTPUT_CONTROL;
154 }
155 
156 MorphLFO::WaveType
wave_type()157 MorphLFO::wave_type()
158 {
159   return m_wave_type;
160 }
161 
162 void
set_wave_type(WaveType new_wave_type)163 MorphLFO::set_wave_type (WaveType new_wave_type)
164 {
165   m_wave_type = new_wave_type;
166 
167   m_morph_plan->emit_plan_changed();
168 }
169 
170 float
frequency() const171 MorphLFO::frequency() const
172 {
173   return m_frequency;
174 }
175 
176 void
set_frequency(float frequency)177 MorphLFO::set_frequency (float frequency)
178 {
179   m_frequency = frequency;
180 
181   m_morph_plan->emit_plan_changed();
182 }
183 
184 float
depth() const185 MorphLFO::depth() const
186 {
187   return m_depth;
188 }
189 
190 void
set_depth(float depth)191 MorphLFO::set_depth (float depth)
192 {
193   m_depth = depth;
194 
195   m_morph_plan->emit_plan_changed();
196 }
197 
198 float
center() const199 MorphLFO::center() const
200 {
201   return m_center;
202 }
203 
204 void
set_center(float center)205 MorphLFO::set_center (float center)
206 {
207   m_center = center;
208 
209   m_morph_plan->emit_plan_changed();
210 }
211 
212 float
start_phase() const213 MorphLFO::start_phase() const
214 {
215   return m_start_phase;
216 }
217 
218 void
set_start_phase(float start_phase)219 MorphLFO::set_start_phase (float start_phase)
220 {
221   m_start_phase = start_phase;
222 
223   m_morph_plan->emit_plan_changed();
224 }
225 
226 bool
sync_voices() const227 MorphLFO::sync_voices() const
228 {
229   return m_sync_voices;
230 }
231 
232 void
set_sync_voices(float sync_voices)233 MorphLFO::set_sync_voices (float sync_voices)
234 {
235   m_sync_voices = sync_voices;
236 
237   m_morph_plan->emit_plan_changed();
238 }
239 
240 bool
beat_sync() const241 MorphLFO::beat_sync() const
242 {
243   return m_beat_sync;
244 }
245 
246 void
set_beat_sync(bool beat_sync)247 MorphLFO::set_beat_sync (bool beat_sync)
248 {
249   m_beat_sync = beat_sync;
250 
251   m_morph_plan->emit_plan_changed();
252 }
253 
254 MorphLFO::Note
note() const255 MorphLFO::note() const
256 {
257   return m_note;
258 }
259 
260 void
set_note(Note note)261 MorphLFO::set_note (Note note)
262 {
263   m_note = note;
264 
265   m_morph_plan->emit_plan_changed();
266 }
267 
268 MorphLFO::NoteMode
note_mode() const269 MorphLFO::note_mode() const
270 {
271   return m_note_mode;
272 }
273 
274 void
set_note_mode(NoteMode mode)275 MorphLFO::set_note_mode (NoteMode mode)
276 {
277   m_note_mode = mode;
278 
279   m_morph_plan->emit_plan_changed();
280 }
281