/* SpiralSynth * Copyleft (C) 2000 David Griffiths * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Synth.h" #include #include #include #include #include #include #include #include "SpiralSound/Oscillator.h" #include "SpiralSound/Output.h" #include "SpiralSound/Midi.h" //#define PLUGIN // midi controlled cutoff is set to effect 1 static const int MIDI_CUTOFF_CONTROL=91; Synth::Synth(): m_Oct(5), m_Databuf(NULL), m_Databuf2(NULL), m_Databuf3(NULL), m_OscControlbuf1(NULL), m_OscControlbuf2(NULL), m_OscControlbuf3(NULL), m_EnvControlbuf(NULL), m_LFOControlbuf(NULL), m_BothControlbuf(NULL), m_Osc1GUI(&m_Osc1), m_Osc2GUI(&m_Osc2), m_Osc3GUI(&m_Osc3), m_Env1GUI(&m_Env1), m_Env2GUI(&m_Env2), m_Env3GUI(&m_Env3), m_FilterGUI(&m_Filter), m_MixerGUI(&m_Mixer), m_Mixer2GUI(&m_Mixer2), m_DelayGUI(&m_Delay), m_FilterEnvGUI(&m_FilterEnv), m_LFOGUI(&m_LFO), m_OutGUI(&m_Out) { AllocMem(); m_VoiceNote = new int[SpiralInfo::POLY]; m_VoiceOctave = new int[SpiralInfo::POLY]; for (int n=0; ncolor(SpiralInfo::GUIBG_COLOUR); // put part guis here m_Osc1GUI.CreateGUI(5,5,"Osc1"); m_Osc2GUI.CreateGUI(5,120,"Osc2"); m_Osc3GUI.CreateGUI(5,235,"Osc3"); m_Env1GUI.CreateGUI(255,5,"Envelope1"); m_Env2GUI.CreateGUI(255,120,"Envelope2"); m_Env3GUI.CreateGUI(255,235,"Envelope3"); m_FilterGUI.CreateGUI(485,5,"Filter"); m_MixerGUI.CreateGUI(380,5,"Mixer 1&2"); m_Mixer2GUI.CreateGUI(380,120,"Mixer [1,2]&3"); m_DelayGUI.CreateGUI(610,5,"Delay"); m_FilterEnvGUI.CreateGUI(485,120,"Extra Envelope"); m_LFOGUI.CreateGUI(610,120,"LFO"); m_OutGUI.CreateGUI(695,5,"Output"); m_PatchBank.CreateGUI(5,350,"Patch Bank"); m_LFORouteGUI.CreateGUI(610,292,"LFO Route"); m_EnvRouteGUI.CreateGUI(610,235,"Envelope Route"); m_Scope.CreateGUI(380,235,"Scope"); } return w; } void Synth::Trigger(int octave, int note, int vol=128) { // Move to the next voice m_CurrentVoice++; if (m_CurrentVoice>=SpiralInfo::POLY) { m_CurrentVoice=0; } // if it's not free if (m_VoiceNote[m_CurrentVoice]!=-1) { // look for a free voice for (int n=0; n11) { note=0; oct++; } } m_CurrentEvent=m_Midi.GetEvent(); int midicount=0; // get all the midi events since the last check while(m_CurrentEvent.GetType()!=MidiEvent::NONE) { if (m_CurrentEvent.GetType()==MidiEvent::ON) { Trigger(m_CurrentEvent.GetOctave(), m_CurrentEvent.GetNote(), m_CurrentEvent.GetVolume()); } if (m_CurrentEvent.GetType()==MidiEvent::OFF) { UnTrigger(m_CurrentEvent.GetOctave(),m_CurrentEvent.GetNote()); } if (m_CurrentEvent.GetType()==MidiEvent::PITCHBEND) { PitchBend(m_CurrentEvent.GetVolume()); } if (m_CurrentEvent.GetType()==MidiEvent::PARAMETER) { ChangeParameter(m_CurrentEvent.GetNote(), m_CurrentEvent.GetVolume()); } m_CurrentEvent=m_Midi.GetEvent(); midicount++; } float f; m_Out.ClearBuffer(); m_LFO.GetOutput(0,m_LFOControlbuf); // run the synth! for (int Voice=0; Voice=0) { m_Filter.Reset(); if (m_PatchBank.IsSaving()) { SavePatch(m_CurrentPatch); } else { LoadPatch(m_CurrentPatch); UpdateValues(); } } if (m_CurrentPatch==-2) { Randomise(); } Route(); return m_Out.GetBuffer(); } void Synth::SavePatch(int n) { char buf[1024]; ostrstream os(buf,1024,ios::out); os<<*this<<"| "; WritePatch(n,buf); } void Synth::LoadPatch(int n) { char buf[1024]; if (ReadPatch(n,buf)) { istrstream is(buf); is>>*this; } } int Synth::ReadPatch(int n, char *out) { string Patchfn(SpiralInfo::Get()->GetHomeDir()+"/.SpiralPatches.bank"); ifstream is(Patchfn.c_str()); if (!is.good()) // make a patch file { cerr<<"SpiralPatches.bank not found - writing new patch file."<GetHomeDir()+"/temp"); ifstream is(Patchfn.c_str()); ofstream os(Tempfn.c_str()); char c=0; int count=0; int count2=0; bool IgnorePatch=false; while(is.good()) { is.get(c); while (count==n) // this is the patch to overwrite { c=in[count2++]; if (c=='|') // end of patch { IgnorePatch=true; count++; os<>(istream &s, Synth &o) { char t; s>>o.m_Osc1>>o.m_Osc2>>o.m_Osc3>>o.m_Env1>>o.m_Env2>> o.m_Env3>>o.m_Filter>>o.m_Mixer>>o.m_Mixer2>>o.m_Delay>> o.m_FilterEnv>>o.m_LFO>>o.m_LFORouteGUI>>o.m_EnvRouteGUI; return s; } ostream &operator<<(ostream &s, Synth &o) { s<<" "<LoadPrefs(); synth = new Synth; Fl::visual(FL_DOUBLE|FL_RGB); synth->CreateWindow(); synth->Window->show(); } short *Run() { if (!synth) { cerr<<"Error in SpiralSynth plugin - not created!"<DoIdle(); } void Destroy() { if (!synth) { cerr<<"Error in SpiralSynth plugin - not created!"<Window->hide(); delete synth->Window; delete synth; } #else int main(int argc, char **argv) { srand(time(NULL)); SpiralInfo::Get()->LoadPrefs(); Synth *synth=new Synth; Fl::visual(FL_DOUBLE|FL_RGB); synth->CreateWindow(); synth->Window->show(argc, argv); for (;;) { if (!Fl::check()) break; synth->DoIdle(); } delete synth; return 1; } #endif