1 /* SpiralSynth
2 * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "Synth.h"
20
21 #include <FL/Fl.H>
22 #include <FL/Enumerations.H>
23 #include <fstream>
24 #include <strstream>
25 #include <string>
26 #include <time.h>
27 #include <stdlib.h>
28
29 #include "SpiralSound/Oscillator.h"
30 #include "SpiralSound/Output.h"
31 #include "SpiralSound/Midi.h"
32
33 //#define PLUGIN
34
35 // midi controlled cutoff is set to effect 1
36 static const int MIDI_CUTOFF_CONTROL=91;
37
Synth()38 Synth::Synth():
39 m_Oct(5),
40 m_Databuf(NULL),
41 m_Databuf2(NULL),
42 m_Databuf3(NULL),
43 m_OscControlbuf1(NULL),
44 m_OscControlbuf2(NULL),
45 m_OscControlbuf3(NULL),
46 m_EnvControlbuf(NULL),
47 m_LFOControlbuf(NULL),
48 m_BothControlbuf(NULL),
49 m_Osc1GUI(&m_Osc1),
50 m_Osc2GUI(&m_Osc2),
51 m_Osc3GUI(&m_Osc3),
52 m_Env1GUI(&m_Env1),
53 m_Env2GUI(&m_Env2),
54 m_Env3GUI(&m_Env3),
55 m_FilterGUI(&m_Filter),
56 m_MixerGUI(&m_Mixer),
57 m_Mixer2GUI(&m_Mixer2),
58 m_DelayGUI(&m_Delay),
59 m_FilterEnvGUI(&m_FilterEnv),
60 m_LFOGUI(&m_LFO),
61 m_OutGUI(&m_Out)
62 {
63 AllocMem();
64
65 m_VoiceNote = new int[SpiralInfo::POLY];
66 m_VoiceOctave = new int[SpiralInfo::POLY];
67 for (int n=0; n<SpiralInfo::POLY; n++)
68 {
69 m_VoiceNote[n] = -1;
70 m_VoiceOctave[n] = -1;
71 }
72
73 if (!m_Databuf || !m_Databuf2 || !m_Databuf3 || !m_OscControlbuf1
74 || !m_OscControlbuf2 || !m_OscControlbuf3 || !m_EnvControlbuf
75 || !m_LFOControlbuf || !m_BothControlbuf )
76 {
77 cerr<<"Not enough memory availible"<<endl;
78 exit(0);
79 }
80
81 m_KeyVoice = new char[SpiralInfo::POLY];
82
83 for (int n=0; n<SpiralInfo::POLY; n++)
84 {
85 m_KeyVoice[n]=' ';
86 }
87
88 LoadPatch(1);
89 }
90
~Synth()91 Synth::~Synth()
92 {
93 CloseMidi();
94
95 delete[] m_Databuf;
96 delete[] m_Databuf2;
97 delete[] m_Databuf3;
98 delete[] m_OscControlbuf1;
99 delete[] m_OscControlbuf2;
100 delete[] m_OscControlbuf3;
101 delete[] m_EnvControlbuf;
102 delete[] m_LFOControlbuf;
103 delete[] m_BothControlbuf;
104 delete[] m_XModbuf1;
105 delete[] m_XModbuf2;
106 delete[] m_VoiceNote;
107 delete[] m_VoiceOctave;
108 delete[] m_KeyVoice;
109 }
110
AllocMem()111 void Synth::AllocMem()
112 {
113 m_Databuf = new short[SpiralInfo::BUFSIZE];
114 m_Databuf2 = new short[SpiralInfo::BUFSIZE];
115 m_Databuf3 = new short[SpiralInfo::BUFSIZE];
116 m_OscControlbuf1 = new short[SpiralInfo::BUFSIZE];
117 m_OscControlbuf2 = new short[SpiralInfo::BUFSIZE];
118 m_OscControlbuf3 = new short[SpiralInfo::BUFSIZE];
119 m_EnvControlbuf = new short[SpiralInfo::BUFSIZE];
120 m_LFOControlbuf = new short[SpiralInfo::BUFSIZE];
121 m_BothControlbuf = new short[SpiralInfo::BUFSIZE];
122
123 m_XModbuf1 = new short*[SpiralInfo::POLY];
124 m_XModbuf2 = new short*[SpiralInfo::POLY];
125
126 for (int n=0; n<SpiralInfo::POLY; n++)
127 {
128 m_XModbuf1[n] = new short[SpiralInfo::BUFSIZE];
129 m_XModbuf2[n] = new short[SpiralInfo::BUFSIZE];
130 }
131 }
132
CreateWindow()133 Fl_Window *Synth::CreateWindow()
134 {
135 Fl_Window* w;
136 { Fl_Window* o = Window = new Fl_Window(785, 395, "SpiralSynth 0.1.7");
137 w = o;
138 o->color(SpiralInfo::GUIBG_COLOUR);
139
140 // put part guis here
141 m_Osc1GUI.CreateGUI(5,5,"Osc1");
142 m_Osc2GUI.CreateGUI(5,120,"Osc2");
143 m_Osc3GUI.CreateGUI(5,235,"Osc3");
144 m_Env1GUI.CreateGUI(255,5,"Envelope1");
145 m_Env2GUI.CreateGUI(255,120,"Envelope2");
146 m_Env3GUI.CreateGUI(255,235,"Envelope3");
147 m_FilterGUI.CreateGUI(485,5,"Filter");
148 m_MixerGUI.CreateGUI(380,5,"Mixer 1&2");
149 m_Mixer2GUI.CreateGUI(380,120,"Mixer [1,2]&3");
150 m_DelayGUI.CreateGUI(610,5,"Delay");
151 m_FilterEnvGUI.CreateGUI(485,120,"Extra Envelope");
152 m_LFOGUI.CreateGUI(610,120,"LFO");
153 m_OutGUI.CreateGUI(695,5,"Output");
154 m_PatchBank.CreateGUI(5,350,"Patch Bank");
155 m_LFORouteGUI.CreateGUI(610,292,"LFO Route");
156 m_EnvRouteGUI.CreateGUI(610,235,"Envelope Route");
157
158 m_Scope.CreateGUI(380,235,"Scope");
159 }
160
161 return w;
162 }
163
164 void Synth::Trigger(int octave, int note, int vol=128)
165 {
166 // Move to the next voice
167 m_CurrentVoice++;
168
169 if (m_CurrentVoice>=SpiralInfo::POLY)
170 {
171 m_CurrentVoice=0;
172 }
173
174 // if it's not free
175 if (m_VoiceNote[m_CurrentVoice]!=-1)
176 {
177 // look for a free voice
178 for (int n=0; n<SpiralInfo::POLY; n++)
179 {
180 if (m_VoiceNote[n]==-1 && m_VoiceOctave[n]==-1)
181 {
182 m_CurrentVoice=n;
183 }
184 }
185 }
186
187 m_VoiceNote[m_CurrentVoice]=note;
188 m_VoiceOctave[m_CurrentVoice]=octave;
189
190 m_Osc1.NoteTrigger(m_CurrentVoice,octave,note,vol); m_Env1.Trigger(m_CurrentVoice);
191 m_Osc2.NoteTrigger(m_CurrentVoice,octave,note,vol); m_Env2.Trigger(m_CurrentVoice);
192 m_Osc3.NoteTrigger(m_CurrentVoice,octave,note,vol); m_Env3.Trigger(m_CurrentVoice);
193 m_FilterEnv.Trigger(m_CurrentVoice);
194 }
195
196 void Synth::UnTrigger(int octave=-1,int note=-1)
197 {
198 // clear all voices
199 if (octave==-1 && note==-1)
200 {
201 for (int n=0; n<SpiralInfo::POLY; n++)
202 {
203 m_Env1.UnTrigger(n);
204 m_Env2.UnTrigger(n);
205 m_Env3.UnTrigger(n);
206 m_FilterEnv.UnTrigger(n);
207 m_VoiceNote[n]=-1;
208 m_VoiceOctave[n]=-1;
209 }
210 }
211 else
212 {
213 // look for the voice and clear it
214 for (int n=0; n<SpiralInfo::POLY; n++)
215 {
216 if (m_VoiceOctave[n]==octave && m_VoiceNote[n]==note)
217 {
218 m_Env1.UnTrigger(n);
219 m_Env2.UnTrigger(n);
220 m_Env3.UnTrigger(n);
221 m_FilterEnv.UnTrigger(n);
222 m_VoiceNote[n]=-1;
223 m_VoiceOctave[n]=-1;
224 }
225 }
226 }
227
228 }
229
PitchBend(int amount)230 void Synth::PitchBend(int amount)
231 {
232 m_Osc1GUI.MidiPitchBend(amount);
233 m_Osc2GUI.MidiPitchBend(amount);
234 m_Osc3GUI.MidiPitchBend(amount);
235 }
236
ChangeParameter(int CC,int amount)237 void Synth::ChangeParameter(int CC, int amount)
238 {
239 if (CC==MIDI_CUTOFF_CONTROL)
240 {
241 m_FilterGUI.MidiCutoff(amount);
242 }
243 }
244
DoIdle()245 short *Synth::DoIdle()
246 {
247 if (Fl::event_key(FL_F+1)) m_Oct=0;
248 if (Fl::event_key(FL_F+2)) m_Oct=1;
249 if (Fl::event_key(FL_F+3)) m_Oct=2;
250 if (Fl::event_key(FL_F+4)) m_Oct=3;
251 if (Fl::event_key(FL_F+5)) m_Oct=4;
252 if (Fl::event_key(FL_F+6)) m_Oct=5;
253 if (Fl::event_key(FL_F+7)) m_Oct=6;
254 if (Fl::event_key(FL_F+8)) m_Oct=7;
255 if (Fl::event_key(FL_F+9)) m_Oct=8;
256 if (Fl::event_key(FL_F+10)) m_Oct=9;
257 if (Fl::event_key(FL_F+11)) m_Oct=10;
258
259 int note=0;
260 int oct=0;
261 char KeyChar=0;
262 bool KeyPressed=false;
263
264 for (int key=0; key<SpiralInfo::NKEYS; key++)
265 {
266 KeyChar=SpiralInfo::KEYMAP.c_str()[key];
267
268 // check if a key's been pressed
269 if (Fl::event_key(KeyChar))
270 {
271 KeyPressed=true;
272
273 // check it was pressed last time
274 bool Found=false;
275 for (int n=0; n<SpiralInfo::POLY; n++)
276 {
277 if (m_KeyVoice[n]==KeyChar)
278 {
279 Found=true;
280 }
281 }
282
283 if (!Found)
284 {
285 Trigger(m_Oct+oct,note);
286 m_KeyVoice[m_CurrentVoice]=KeyChar;
287 }
288 }
289 else // it's not pressed down
290 {
291 //see if the note was pressed down last time
292 for (int n=0; n<SpiralInfo::POLY; n++)
293 {
294 if (m_KeyVoice[n]==KeyChar)
295 {
296 UnTrigger(m_Oct+oct,note);
297 m_KeyVoice[n]=' ';
298 }
299 }
300 }
301
302 note++;
303 if (note>11)
304 {
305 note=0;
306 oct++;
307 }
308 }
309
310 m_CurrentEvent=m_Midi.GetEvent();
311
312 int midicount=0;
313 // get all the midi events since the last check
314 while(m_CurrentEvent.GetType()!=MidiEvent::NONE)
315 {
316 if (m_CurrentEvent.GetType()==MidiEvent::ON)
317 {
318 Trigger(m_CurrentEvent.GetOctave(),
319 m_CurrentEvent.GetNote(),
320 m_CurrentEvent.GetVolume());
321 }
322
323 if (m_CurrentEvent.GetType()==MidiEvent::OFF)
324 {
325 UnTrigger(m_CurrentEvent.GetOctave(),m_CurrentEvent.GetNote());
326 }
327
328 if (m_CurrentEvent.GetType()==MidiEvent::PITCHBEND)
329 {
330 PitchBend(m_CurrentEvent.GetVolume());
331 }
332
333 if (m_CurrentEvent.GetType()==MidiEvent::PARAMETER)
334 {
335 ChangeParameter(m_CurrentEvent.GetNote(),
336 m_CurrentEvent.GetVolume());
337 }
338
339 m_CurrentEvent=m_Midi.GetEvent();
340 midicount++;
341 }
342
343 float f;
344 m_Out.ClearBuffer();
345
346 m_LFO.GetOutput(0,m_LFOControlbuf);
347
348 // run the synth!
349 for (int Voice=0; Voice<SpiralInfo::POLY; Voice++)
350 {
351 // Xmod routing
352 if (m_Mixer.GetType()==Mixer::XMOD)
353 {
354 m_Osc2.ModulateFreq(m_XModbuf1[Voice]);
355 }
356
357 if (m_Mixer2.GetType()==Mixer::XMOD)
358 {
359 m_Osc3.ModulateFreq(m_XModbuf2[Voice]);
360 }
361
362 m_FilterEnv.GetOutput(Voice, m_EnvControlbuf);
363
364 for (int n=0; n<SpiralInfo::BUFSIZE; n++)
365 m_BothControlbuf[n] = m_LFOControlbuf[n]+m_EnvControlbuf[n];
366
367 m_Osc1.GetOutput(Voice, m_Databuf);
368 m_Osc2.GetOutput(Voice, m_Databuf2);
369 m_Osc3.GetOutput(Voice, m_Databuf3);
370 m_Env1.GetOutput(Voice, m_OscControlbuf1);
371 m_Env2.GetOutput(Voice, m_OscControlbuf2);
372 m_Env3.GetOutput(Voice, m_OscControlbuf3);
373 m_OscAmp1.GetOutput(m_OscControlbuf1,m_Databuf);
374 m_OscAmp2.GetOutput(m_OscControlbuf2,m_Databuf2);
375 m_OscAmp3.GetOutput(m_OscControlbuf3,m_Databuf3);
376
377 // store the buffer here for feeding back into the oscillator
378 if (m_Mixer.GetType()==Mixer::XMOD)
379 {
380 CopyBuffer(m_Databuf,m_XModbuf1[Voice]);
381 }
382
383 m_Mixer.GetOutput(m_Databuf2,m_Databuf);
384
385 // store the buffer here for feeding back into the oscillator
386 if (m_Mixer2.GetType()==Mixer::XMOD)
387 {
388 CopyBuffer(m_Databuf2,m_XModbuf2[Voice]);
389 }
390
391 m_Mixer2.GetOutput(m_Databuf3,m_Databuf);
392 m_Filter.GetOutput(Voice,m_Databuf);
393
394 m_Out.Send(m_Databuf);
395 }
396
397 m_Delay.GetOutput(m_Out.GetBuffer());
398
399 m_Scope.Display(m_Out.GetBuffer());
400
401 m_Out.Play();
402
403 m_CurrentPatch=m_PatchBank.GetOutput();
404
405 if (m_CurrentPatch>=0)
406 {
407 m_Filter.Reset();
408 if (m_PatchBank.IsSaving())
409 {
410 SavePatch(m_CurrentPatch);
411 }
412 else
413 {
414 LoadPatch(m_CurrentPatch);
415 UpdateValues();
416 }
417 }
418
419 if (m_CurrentPatch==-2)
420 {
421 Randomise();
422 }
423
424 Route();
425
426 return m_Out.GetBuffer();
427 }
428
SavePatch(int n)429 void Synth::SavePatch(int n)
430 {
431 char buf[1024];
432 ostrstream os(buf,1024,ios::out);
433 os<<*this<<"| ";
434 WritePatch(n,buf);
435 }
436
LoadPatch(int n)437 void Synth::LoadPatch(int n)
438 {
439 char buf[1024];
440 if (ReadPatch(n,buf))
441 {
442 istrstream is(buf);
443 is>>*this;
444 }
445 }
446
447
ReadPatch(int n,char * out)448 int Synth::ReadPatch(int n, char *out)
449 {
450 string Patchfn(SpiralInfo::Get()->GetHomeDir()+"/.SpiralPatches.bank");
451 ifstream is(Patchfn.c_str());
452
453 if (!is.good()) // make a patch file
454 {
455 cerr<<"SpiralPatches.bank not found - writing new patch file."<<endl;
456
457 ofstream os(Patchfn.c_str());
458 for (int n=0; n<NUM_PATCHES; n++)
459 os<<*this<<"| ";
460
461 return 0;
462 }
463
464 char c=0;
465 int count=0;
466
467 while(is.good() && count!=n)
468 {
469 is.get(c);
470 //cerr<<"c="<<c<<" count="<<count<<endl;
471 if (c=='|') count++;
472 }
473
474 if(is.good())
475 {
476 is.get(out,1024);
477 }
478
479 return 1;
480 }
481
WritePatch(int n,char * in)482 void Synth::WritePatch(int n, char *in)
483 {
484 // todo: get rid of this cheesy implementation
485 string Patchfn(SpiralInfo::Get()->GetHomeDir()+"/.SpiralPatches.bank");
486 string Tempfn(SpiralInfo::Get()->GetHomeDir()+"/temp");
487 ifstream is(Patchfn.c_str());
488 ofstream os(Tempfn.c_str());
489
490 char c=0;
491 int count=0;
492 int count2=0;
493 bool IgnorePatch=false;
494
495 while(is.good())
496 {
497 is.get(c);
498
499 while (count==n) // this is the patch to overwrite
500 {
501 c=in[count2++];
502
503 if (c=='|') // end of patch
504 {
505 IgnorePatch=true;
506 count++;
507 os<<c<<" ";
508 is.get(c);
509 }
510 else os<<c;
511 }
512
513 if (IgnorePatch) // step through until end
514 {
515
516 if (c=='|')
517 {
518 IgnorePatch=false;
519 count++;
520 }
521 }
522 else // normal write mode
523 {
524 if (c=='|')
525 {
526 count++;
527 }
528
529 os<<c;
530 }
531
532 }
533
534 string command("mv -f "+Tempfn+" "+Patchfn);
535 system(command.c_str());
536 }
537
Route()538 void Synth::Route()
539 {
540 m_Osc1.ModulateFreq(NULL);
541 m_Osc1.ModulatePulseWidth(NULL);
542 m_Osc2.ModulateFreq(NULL);
543 m_Osc2.ModulatePulseWidth(NULL);
544 m_Filter.ModulateCutoff(NULL);
545 m_Filter.ModulateResonance(NULL);
546
547 if (m_LFORouteGUI.Query(RouteGUI::OSC1FREQ))
548 m_Osc1.ModulateFreq(m_LFOControlbuf);
549
550 if (m_LFORouteGUI.Query(RouteGUI::OSC1PW))
551 m_Osc1.ModulatePulseWidth(m_LFOControlbuf);
552
553 if (m_LFORouteGUI.Query(RouteGUI::OSC2FREQ))
554 m_Osc2.ModulateFreq(m_LFOControlbuf);
555
556 if (m_LFORouteGUI.Query(RouteGUI::OSC2PW))
557 m_Osc2.ModulatePulseWidth(m_LFOControlbuf);
558
559 if (m_LFORouteGUI.Query(RouteGUI::FILTERC))
560 m_Filter.ModulateCutoff(m_LFOControlbuf);
561
562 if (m_LFORouteGUI.Query(RouteGUI::FILTERR))
563 m_Filter.ModulateResonance(m_LFOControlbuf);
564
565
566 if (m_EnvRouteGUI.Query(RouteGUI::OSC1FREQ))
567 m_Osc1.ModulateFreq(m_EnvControlbuf);
568
569 if (m_EnvRouteGUI.Query(RouteGUI::OSC1PW))
570 m_Osc1.ModulatePulseWidth(m_EnvControlbuf);
571
572 if (m_EnvRouteGUI.Query(RouteGUI::OSC2FREQ))
573 m_Osc2.ModulateFreq(m_EnvControlbuf);
574
575 if (m_EnvRouteGUI.Query(RouteGUI::OSC2PW))
576 m_Osc2.ModulatePulseWidth(m_EnvControlbuf);
577
578 if (m_EnvRouteGUI.Query(RouteGUI::FILTERC))
579 m_Filter.ModulateCutoff(m_EnvControlbuf);
580
581 if (m_EnvRouteGUI.Query(RouteGUI::FILTERR))
582 m_Filter.ModulateResonance(m_EnvControlbuf);
583
584
585 if (m_LFORouteGUI.Query(RouteGUI::OSC1FREQ) &&
586 m_EnvRouteGUI.Query(RouteGUI::OSC1FREQ))
587 m_Osc1.ModulateFreq(m_BothControlbuf);
588
589 if (m_LFORouteGUI.Query(RouteGUI::OSC1PW) &&
590 m_EnvRouteGUI.Query(RouteGUI::OSC1PW))
591 m_Osc1.ModulatePulseWidth(m_BothControlbuf);
592
593 if (m_LFORouteGUI.Query(RouteGUI::OSC2FREQ) &&
594 m_EnvRouteGUI.Query(RouteGUI::OSC2FREQ))
595 m_Osc2.ModulateFreq(m_BothControlbuf);
596
597 if (m_LFORouteGUI.Query(RouteGUI::OSC2PW) &&
598 m_EnvRouteGUI.Query(RouteGUI::OSC2PW))
599 m_Osc2.ModulatePulseWidth(m_BothControlbuf);
600
601 if (m_LFORouteGUI.Query(RouteGUI::FILTERC) &&
602 m_EnvRouteGUI.Query(RouteGUI::FILTERC))
603 m_Filter.ModulateCutoff(m_BothControlbuf);
604
605 if (m_LFORouteGUI.Query(RouteGUI::FILTERR) &&
606 m_EnvRouteGUI.Query(RouteGUI::FILTERR))
607 m_Filter.ModulateResonance(m_BothControlbuf);
608 }
609
UpdateValues()610 void Synth::UpdateValues()
611 {
612 m_Osc1GUI.UpdateValues();
613 m_Osc2GUI.UpdateValues();
614 m_Osc3GUI.UpdateValues();
615 m_Env1GUI.UpdateValues();
616 m_Env2GUI.UpdateValues();
617 m_Env3GUI.UpdateValues();
618 m_FilterGUI.UpdateValues();
619 m_MixerGUI.UpdateValues();
620 m_Mixer2GUI.UpdateValues();
621 m_DelayGUI.UpdateValues();
622 m_FilterEnvGUI.UpdateValues();
623 m_LFOGUI.UpdateValues();
624 m_LFORouteGUI.UpdateValues();
625 m_EnvRouteGUI.UpdateValues();
626 }
627
Randomise()628 void Synth::Randomise()
629 {
630 m_Osc1.Randomise();
631 m_Osc2.Randomise();
632 m_Osc3.Randomise();
633 m_Env1.Randomise();
634 m_Env2.Randomise();
635 m_Env3.Randomise();
636 m_Filter.Randomise();
637 m_Mixer.Randomise();
638 m_Mixer2.Randomise();
639 m_FilterEnv.Randomise();
640 m_LFO.Randomise();
641 m_LFORouteGUI.Randomise();
642 m_EnvRouteGUI.Randomise();
643
644 UpdateValues();
645 }
646
647 istream &operator>>(istream &s, Synth &o)
648 {
649 char t;
650 s>>o.m_Osc1>>o.m_Osc2>>o.m_Osc3>>o.m_Env1>>o.m_Env2>>
651 o.m_Env3>>o.m_Filter>>o.m_Mixer>>o.m_Mixer2>>o.m_Delay>>
652 o.m_FilterEnv>>o.m_LFO>>o.m_LFORouteGUI>>o.m_EnvRouteGUI;
653 return s;
654 }
655
656 ostream &operator<<(ostream &s, Synth &o)
657 {
658 s<<" "<<o.m_Osc1<<o.m_Osc2<<o.m_Osc3<<o.m_Env1
659 <<o.m_Env2<<o.m_Env3<<o.m_Filter<<o.m_Mixer
660 <<o.m_Mixer2<<o.m_Delay<<o.m_FilterEnv<<o.m_LFO
661 <<o.m_LFORouteGUI<<o.m_EnvRouteGUI<<endl;
662 return s;
663 }
664
665 #ifdef PLUGIN
666
667 Synth *synth;
668
Create()669 void Create()
670 {
671 cerr<<"Loading SpiralSynth plugin"<<endl;
672
673 srand(time(NULL));cerr<<1<<endl;
674 SpiralInfo::Get()->LoadPrefs();
675
676 synth = new Synth;
677
678 Fl::visual(FL_DOUBLE|FL_RGB);
679 synth->CreateWindow();
680 synth->Window->show();
681 }
682
Run()683 short *Run()
684 {
685 if (!synth)
686 {
687 cerr<<"Error in SpiralSynth plugin - not created!"<<endl;
688 return 0;
689 }
690
691 Fl::check();
692 return synth->DoIdle();
693 }
694
Destroy()695 void Destroy()
696 {
697 if (!synth)
698 {
699 cerr<<"Error in SpiralSynth plugin - not created!"<<endl;
700 return;
701 }
702 synth->Window->hide();
703 delete synth->Window;
704 delete synth;
705 }
706
707 #else
708
main(int argc,char ** argv)709 int main(int argc, char **argv)
710 {
711 srand(time(NULL));
712 SpiralInfo::Get()->LoadPrefs();
713
714 Synth *synth=new Synth;
715
716 Fl::visual(FL_DOUBLE|FL_RGB);
717 synth->CreateWindow();
718 synth->Window->show(argc, argv);
719
720 for (;;)
721 {
722 if (!Fl::check()) break;
723 synth->DoIdle();
724 }
725
726 delete synth;
727
728 return 1;
729 }
730
731 #endif
732