1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2
3 #include "smmorphoutput.hh"
4 #include "smmorphplan.hh"
5 #include "smleakdebugger.hh"
6
7 #include <assert.h>
8
9 #define CHANNEL_OP_COUNT 4
10
11 using namespace SpectMorph;
12
13 using std::string;
14 using std::vector;
15
16 static LeakDebugger leak_debugger ("SpectMorph::MorphOutput");
17
MorphOutput(MorphPlan * morph_plan)18 MorphOutput::MorphOutput (MorphPlan *morph_plan) :
19 MorphOperator (morph_plan),
20 channel_ops (CHANNEL_OP_COUNT)
21 {
22 connect (morph_plan->signal_operator_removed, this, &MorphOutput::on_operator_removed);
23
24 m_velocity_sensitivity = 24; /* dB */
25
26 m_sines = true;
27 m_noise = true;
28
29 m_unison = false;
30 m_unison_voices = 2;
31 m_unison_detune = 6.0;
32
33 m_adsr = false;
34 m_adsr_skip = 500;
35 m_adsr_attack = 15;
36 m_adsr_decay = 20;
37 m_adsr_sustain = 70;
38 m_adsr_release = 50;
39
40 m_portamento = false;
41 m_portamento_glide = 200; /* ms */
42
43 m_vibrato = false;
44 m_vibrato_depth = 10; /* cent */
45 m_vibrato_frequency = 4; /* Hz */
46 m_vibrato_attack = 0; /* ms */
47
48 leak_debugger.add (this);
49 }
50
MorphOutputProperties(MorphOutput * output)51 MorphOutputProperties::MorphOutputProperties (MorphOutput *output) :
52 adsr_skip (output, "Skip", "%.1f ms", 0, 1000, &MorphOutput::adsr_skip, &MorphOutput::set_adsr_skip),
53 adsr_attack (output, "Attack", "%.1f %%", 0, 100, &MorphOutput::adsr_attack, &MorphOutput::set_adsr_attack),
54 adsr_decay (output, "Decay", "%.1f %%", 0, 100, &MorphOutput::adsr_decay, &MorphOutput::set_adsr_decay),
55 adsr_sustain (output, "Sustain", "%.1f %%", 0, 100, &MorphOutput::adsr_sustain, &MorphOutput::set_adsr_sustain),
56 adsr_release (output, "Release", "%.1f %%", 0, 100, &MorphOutput::adsr_release, &MorphOutput::set_adsr_release),
57 portamento_glide (output, "Glide", "%.2f ms", 0, 1000, 3, &MorphOutput::portamento_glide, &MorphOutput::set_portamento_glide),
58 vibrato_depth (output, "Depth", "%.2f Cent", 0, 50, &MorphOutput::vibrato_depth, &MorphOutput::set_vibrato_depth),
59 vibrato_frequency (output, "Frequency", "%.3f Hz", 1.0, 15, &MorphOutput::vibrato_frequency, &MorphOutput::set_vibrato_frequency),
60 vibrato_attack (output, "Attack", "%.2f ms", 0, 1000, &MorphOutput::vibrato_attack, &MorphOutput::set_vibrato_attack),
61 velocity_sensitivity (output, "Velocity Sns", "%.2f dB", 0, 48, &MorphOutput::velocity_sensitivity, &MorphOutput::set_velocity_sensitivity)
62 {
63 }
64
~MorphOutput()65 MorphOutput::~MorphOutput()
66 {
67 leak_debugger.del (this);
68 }
69
70 const char *
type()71 MorphOutput::type()
72 {
73 return "SpectMorph::MorphOutput";
74 }
75
76 int
insert_order()77 MorphOutput::insert_order()
78 {
79 return 1000;
80 }
81
82 bool
save(OutFile & out_file)83 MorphOutput::save (OutFile& out_file)
84 {
85 for (size_t i = 0; i < channel_ops.size(); i++)
86 {
87 string name;
88
89 if (channel_ops[i]) // NULL pointer => name = ""
90 name = channel_ops[i]->name();
91
92 out_file.write_string ("channel", name);
93 }
94 out_file.write_bool ("sines", m_sines);
95 out_file.write_bool ("noise", m_noise);
96
97 out_file.write_bool ("unison", m_unison);
98 out_file.write_int ("unison_voices", m_unison_voices);
99 out_file.write_float ("unison_detune", m_unison_detune);
100
101 out_file.write_bool ("adsr", m_adsr);
102 out_file.write_float ("adsr_skip", m_adsr_skip);
103 out_file.write_float ("adsr_attack", m_adsr_attack);
104 out_file.write_float ("adsr_decay", m_adsr_decay);
105 out_file.write_float ("adsr_sustain", m_adsr_sustain);
106 out_file.write_float ("adsr_release", m_adsr_release);
107
108 out_file.write_bool ("portamento", m_portamento);
109 out_file.write_float ("portamento_glide", m_portamento_glide);
110
111 out_file.write_bool ("vibrato", m_vibrato);
112 out_file.write_float ("vibrato_depth", m_vibrato_depth);
113 out_file.write_float ("vibrato_frequency", m_vibrato_frequency);
114 out_file.write_float ("vibrato_attack", m_vibrato_attack);
115
116 out_file.write_float ("velocity_sensitivity", m_velocity_sensitivity);
117
118 return true;
119 }
120
121 bool
load(InFile & ifile)122 MorphOutput::load (InFile& ifile)
123 {
124 load_channel_op_names.clear();
125
126 while (ifile.event() != InFile::END_OF_FILE)
127 {
128 if (ifile.event() == InFile::STRING)
129 {
130 if (ifile.event_name() == "channel")
131 {
132 load_channel_op_names.push_back (ifile.event_data());
133 }
134 else
135 {
136 g_printerr ("bad string\n");
137 return false;
138 }
139 }
140 else if (ifile.event() == InFile::BOOL)
141 {
142 if (ifile.event_name() == "sines")
143 {
144 m_sines = ifile.event_bool();
145 }
146 else if (ifile.event_name() == "noise")
147 {
148 m_noise = ifile.event_bool();
149 }
150 else if (ifile.event_name() == "unison")
151 {
152 m_unison = ifile.event_bool();
153 }
154 else if (ifile.event_name() == "adsr")
155 {
156 m_adsr = ifile.event_bool();
157 }
158 else if (ifile.event_name() == "portamento")
159 {
160 m_portamento = ifile.event_bool();
161 }
162 else if (ifile.event_name() == "vibrato")
163 {
164 m_vibrato = ifile.event_bool();
165 }
166 else
167 {
168 g_printerr ("bad bool\n");
169 return false;
170 }
171 }
172 else if (ifile.event() == InFile::INT)
173 {
174 if (ifile.event_name() == "unison_voices")
175 {
176 m_unison_voices = ifile.event_int();
177 }
178 else
179 {
180 g_printerr ("bad int\n");
181 return false;
182 }
183 }
184 else if (ifile.event() == InFile::FLOAT)
185 {
186 if (ifile.event_name() == "unison_detune")
187 {
188 m_unison_detune = ifile.event_float();
189 }
190 else if (ifile.event_name() == "adsr_skip")
191 {
192 m_adsr_skip = ifile.event_float();
193 }
194 else if (ifile.event_name() == "adsr_attack")
195 {
196 m_adsr_attack = ifile.event_float();
197 }
198 else if (ifile.event_name() == "adsr_decay")
199 {
200 m_adsr_decay = ifile.event_float();
201 }
202 else if (ifile.event_name() == "adsr_sustain")
203 {
204 m_adsr_sustain = ifile.event_float();
205 }
206 else if (ifile.event_name() == "adsr_release")
207 {
208 m_adsr_release = ifile.event_float();
209 }
210 else if (ifile.event_name() == "portamento_glide")
211 {
212 m_portamento_glide = ifile.event_float();
213 }
214 else if (ifile.event_name() == "vibrato_depth")
215 {
216 m_vibrato_depth = ifile.event_float();
217 }
218 else if (ifile.event_name() == "vibrato_frequency")
219 {
220 m_vibrato_frequency = ifile.event_float();
221 }
222 else if (ifile.event_name() == "vibrato_attack")
223 {
224 m_vibrato_attack = ifile.event_float();
225 }
226 else if (ifile.event_name() == "velocity_sensitivity")
227 {
228 m_velocity_sensitivity = ifile.event_float();
229 }
230 else
231 {
232 g_printerr ("bad float\n");
233 return false;
234 }
235 }
236 else
237 {
238 g_printerr ("bad event\n");
239 return false;
240 }
241 ifile.next_event();
242 }
243 return true;
244 }
245
246 void
post_load(OpNameMap & op_name_map)247 MorphOutput::post_load (OpNameMap& op_name_map)
248 {
249 for (size_t i = 0; i < channel_ops.size(); i++)
250 {
251 if (i < load_channel_op_names.size())
252 {
253 string name = load_channel_op_names[i];
254 channel_ops[i] = op_name_map[name];
255 }
256 }
257 }
258
259 MorphOperator::OutputType
output_type()260 MorphOutput::output_type()
261 {
262 return OUTPUT_NONE;
263 }
264
265 void
set_channel_op(int ch,MorphOperator * op)266 MorphOutput::set_channel_op (int ch, MorphOperator *op)
267 {
268 assert (ch >= 0 && ch < CHANNEL_OP_COUNT);
269
270 channel_ops[ch] = op;
271 m_morph_plan->emit_plan_changed();
272 }
273
274 MorphOperator *
channel_op(int ch)275 MorphOutput::channel_op (int ch)
276 {
277 assert (ch >= 0 && ch < CHANNEL_OP_COUNT);
278
279 return channel_ops[ch];
280 }
281
282 bool
sines() const283 MorphOutput::sines() const
284 {
285 return m_sines;
286 }
287
288 void
set_sines(bool es)289 MorphOutput::set_sines (bool es)
290 {
291 m_sines = es;
292
293 m_morph_plan->emit_plan_changed();
294 }
295
296 bool
noise() const297 MorphOutput::noise() const
298 {
299 return m_noise;
300 }
301
302 void
set_noise(bool en)303 MorphOutput::set_noise (bool en)
304 {
305 m_noise = en;
306
307 m_morph_plan->emit_plan_changed();
308 }
309
310 //---- unison effect ----
311
312 bool
unison() const313 MorphOutput::unison() const
314 {
315 return m_unison;
316 }
317
318 void
set_unison(bool eu)319 MorphOutput::set_unison (bool eu)
320 {
321 m_unison = eu;
322
323 m_morph_plan->emit_plan_changed();
324 }
325
326 int
unison_voices() const327 MorphOutput::unison_voices() const
328 {
329 return m_unison_voices;
330 }
331
332 void
set_unison_voices(int voices)333 MorphOutput::set_unison_voices (int voices)
334 {
335 m_unison_voices = voices;
336
337 m_morph_plan->emit_plan_changed();
338 }
339
340 float
unison_detune() const341 MorphOutput::unison_detune() const
342 {
343 return m_unison_detune;
344 }
345
346 void
set_unison_detune(float detune)347 MorphOutput::set_unison_detune (float detune)
348 {
349 m_unison_detune = detune;
350
351 m_morph_plan->emit_plan_changed();
352 }
353
354 //---- adsr ----
355
356 bool
adsr() const357 MorphOutput::adsr() const
358 {
359 return m_adsr;
360 }
361
362 void
set_adsr(bool ea)363 MorphOutput::set_adsr (bool ea)
364 {
365 m_adsr = ea;
366
367 m_morph_plan->emit_plan_changed();
368 }
369
370 float
adsr_skip() const371 MorphOutput::adsr_skip() const
372 {
373 return m_adsr_skip;
374 }
375
376 void
set_adsr_skip(float skip)377 MorphOutput::set_adsr_skip (float skip)
378 {
379 m_adsr_skip = skip;
380
381 m_morph_plan->emit_plan_changed();
382 }
383
384 float
adsr_attack() const385 MorphOutput::adsr_attack() const
386 {
387 return m_adsr_attack;
388 }
389
390 void
set_adsr_attack(float attack)391 MorphOutput::set_adsr_attack (float attack)
392 {
393 m_adsr_attack = attack;
394
395 m_morph_plan->emit_plan_changed();
396 }
397
398 float
adsr_decay() const399 MorphOutput::adsr_decay() const
400 {
401 return m_adsr_decay;
402 }
403
404 void
set_adsr_decay(float decay)405 MorphOutput::set_adsr_decay (float decay)
406 {
407 m_adsr_decay = decay;
408
409 m_morph_plan->emit_plan_changed();
410 }
411
412 float
adsr_release() const413 MorphOutput::adsr_release() const
414 {
415 return m_adsr_release;
416 }
417
418 void
set_adsr_release(float release)419 MorphOutput::set_adsr_release (float release)
420 {
421 m_adsr_release = release;
422
423 m_morph_plan->emit_plan_changed();
424 }
425
426 float
adsr_sustain() const427 MorphOutput::adsr_sustain() const
428 {
429 return m_adsr_sustain;
430 }
431
432 void
set_adsr_sustain(float sustain)433 MorphOutput::set_adsr_sustain (float sustain)
434 {
435 m_adsr_sustain = sustain;
436
437 m_morph_plan->emit_plan_changed();
438 }
439
440 //---- portamento/mono mode ----
441
442 bool
portamento() const443 MorphOutput::portamento() const
444 {
445 return m_portamento;
446 }
447
448 void
set_portamento(bool ep)449 MorphOutput::set_portamento (bool ep)
450 {
451 m_portamento = ep;
452
453 m_morph_plan->emit_plan_changed();
454 }
455
456 float
portamento_glide() const457 MorphOutput::portamento_glide() const
458 {
459 return m_portamento_glide;
460 }
461
462 void
set_portamento_glide(float glide)463 MorphOutput::set_portamento_glide (float glide)
464 {
465 m_portamento_glide = glide;
466
467 m_morph_plan->emit_plan_changed();
468 }
469
470 //---- vibrato ----
471
472 bool
vibrato() const473 MorphOutput::vibrato() const
474 {
475 return m_vibrato;
476 }
477
478 void
set_vibrato(bool ev)479 MorphOutput::set_vibrato (bool ev)
480 {
481 m_vibrato = ev;
482
483 m_morph_plan->emit_plan_changed();
484 }
485
486 float
vibrato_depth() const487 MorphOutput::vibrato_depth() const
488 {
489 return m_vibrato_depth;
490 }
491
492 void
set_vibrato_depth(float depth)493 MorphOutput::set_vibrato_depth (float depth)
494 {
495 m_vibrato_depth = depth;
496
497 m_morph_plan->emit_plan_changed();
498 }
499
500 float
vibrato_frequency() const501 MorphOutput::vibrato_frequency() const
502 {
503 return m_vibrato_frequency;
504 }
505
506 void
set_vibrato_frequency(float frequency)507 MorphOutput::set_vibrato_frequency (float frequency)
508 {
509 m_vibrato_frequency = frequency;
510
511 m_morph_plan->emit_plan_changed();
512 }
513
514 float
vibrato_attack() const515 MorphOutput::vibrato_attack() const
516 {
517 return m_vibrato_attack;
518 }
519
520 void
set_vibrato_attack(float attack)521 MorphOutput::set_vibrato_attack (float attack)
522 {
523 m_vibrato_attack = attack;
524
525 m_morph_plan->emit_plan_changed();
526 }
527
528 float
velocity_sensitivity() const529 MorphOutput::velocity_sensitivity() const
530 {
531 return m_velocity_sensitivity;
532 }
533
534 void
set_velocity_sensitivity(float velocity_sensitivity)535 MorphOutput::set_velocity_sensitivity (float velocity_sensitivity)
536 {
537 m_velocity_sensitivity = velocity_sensitivity;
538
539 m_morph_plan->emit_plan_changed();
540 }
541
542 void
on_operator_removed(MorphOperator * op)543 MorphOutput::on_operator_removed (MorphOperator *op)
544 {
545 for (size_t ch = 0; ch < channel_ops.size(); ch++)
546 {
547 if (channel_ops[ch] == op)
548 channel_ops[ch] = NULL;
549 }
550 }
551
552 vector<MorphOperator *>
dependencies()553 MorphOutput::dependencies()
554 {
555 return channel_ops;
556 }
557