/* SpiralSound * Copyleft (C) 2001 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 "MatrixPlugin.h" #include "MatrixPluginGUI.h" #include #include "SpiralIcon.xpm" #include "../../RiffWav.h" #include "../../NoteTable.h" extern "C" { SpiralPlugin* CreateInstance() { return new MatrixPlugin; } char** GetIcon() { return SpiralIcon_xpm; } int GetID() { return 0x0012; } } /////////////////////////////////////////////////////// MatrixPlugin::MatrixPlugin() : m_TickTime(1.0f), m_StepTime(1.0f), m_Time(0.0f), m_Step(0), m_Loop(true), m_NoteCut(false), m_Current(0), m_GUICurrent(0), m_CurrentNoteCV(0), m_CurrentTriggerCV(0), m_Triggered(false), m_ClockHigh(false), m_CopyPattern(0), m_PatAdvance(false), m_PatReset(false) { m_Version=3; m_PluginInfo.Name="Matrix"; m_PluginInfo.Width=560; m_PluginInfo.Height=270; m_PluginInfo.NumInputs=5; m_PluginInfo.NumOutputs=19; m_PluginInfo.PortTips.push_back("Play Trigger"); m_PluginInfo.PortTips.push_back("StepTime CV"); m_PluginInfo.PortTips.push_back("Input Pitch CV"); m_PluginInfo.PortTips.push_back("Input Trigger CV"); m_PluginInfo.PortTips.push_back("External Clock"); //m_PluginInfo.PortTips.push_back("Pattern Advance"); //m_PluginInfo.PortTips.push_back("Pattern Reset"); m_PluginInfo.PortTips.push_back("Output Pitch"); m_PluginInfo.PortTips.push_back("Output Trigger"); m_PluginInfo.PortTips.push_back("Trigger 1"); m_PluginInfo.PortTips.push_back("Trigger 2"); m_PluginInfo.PortTips.push_back("Trigger 3"); m_PluginInfo.PortTips.push_back("Trigger 4"); m_PluginInfo.PortTips.push_back("Trigger 5"); m_PluginInfo.PortTips.push_back("Trigger 6"); m_PluginInfo.PortTips.push_back("Trigger 7"); m_PluginInfo.PortTips.push_back("Trigger 8"); m_PluginInfo.PortTips.push_back("Trigger 9"); m_PluginInfo.PortTips.push_back("Trigger 10"); m_PluginInfo.PortTips.push_back("Trigger 11"); m_PluginInfo.PortTips.push_back("Trigger 12"); m_PluginInfo.PortTips.push_back("Trigger 13"); m_PluginInfo.PortTips.push_back("Trigger 14"); m_PluginInfo.PortTips.push_back("Trigger 15"); m_PluginInfo.PortTips.push_back("Trigger 16"); m_PluginInfo.PortTips.push_back("Reset Trigger"); for (int n=0; nRegister("NoteCut",&m_NoteCut,ChannelHandler::INPUT); m_AudioCH->Register("Volume",&m_GUIArgs.Volume,ChannelHandler::INPUT); m_AudioCH->Register("Current",&m_GUICurrent,ChannelHandler::INPUT); m_AudioCH->Register("StepTime",&m_StepTime,ChannelHandler::INPUT); m_AudioCH->Register("Num",&m_GUIArgs.Num,ChannelHandler::INPUT); m_AudioCH->Register("Length",&m_GUIArgs.Length,ChannelHandler::INPUT); m_AudioCH->Register("Speed",&m_GUIArgs.Speed,ChannelHandler::INPUT); m_AudioCH->Register("X",&m_GUIArgs.X,ChannelHandler::INPUT); m_AudioCH->Register("Y",&m_GUIArgs.Y,ChannelHandler::INPUT); m_AudioCH->Register("Octave",&m_GUIArgs.Octave,ChannelHandler::INPUT); m_AudioCH->Register("Step",&m_Step,ChannelHandler::OUTPUT); m_AudioCH->RegisterData("Matrix",ChannelHandler::OUTPUT_REQUEST,&m_Matrix,sizeof(m_Matrix)); } MatrixPlugin::~MatrixPlugin() { } PluginInfo &MatrixPlugin::Initialise(const HostInfo *Host) { PluginInfo& Info = SpiralPlugin::Initialise(Host); m_TickTime = 1.0f/(float)m_HostInfo->SAMPLERATE; return Info; } SpiralGUIType *MatrixPlugin::CreateGUI() { return new MatrixPluginGUI(m_PluginInfo.Width, m_PluginInfo.Height, this,m_AudioCH,m_HostInfo); } void MatrixPlugin::Execute() { for (int n=0; nBUFSIZE; n++) { if (InputExists(1)) m_StepTime = GetInput(1,n); // inc time m_Time+=m_TickTime; SetOutputPitch(0,n,m_CurrentNoteCV); SetOutput(1,n,m_CurrentTriggerCV); // clear the pattern sync SetOutput(18, n, 0); bool ExternalClock = InputExists(4); bool ExternalClockTriggered=false; if (GetInputPitch(0,n)>0) { if (!m_Triggered) { float Freq=GetInputPitch(0,n); // Notes 0 to 16 trigger patterns 0 to 16 // No other notes catered for for (int i=0; i0) { if(!m_ClockHigh) { m_ClockHigh=true; ExternalClockTriggered=true; } } else { if (m_ClockHigh) { m_ClockHigh=false; ExternalClockTriggered=true; } } // reset the position on a signal from input 1 if (InputExists(0) && GetInput(0,n)!=0) { m_Step=-1; ExternalClockTriggered=true; } } /* not yet... // external pattern advance if (GetInput(5,n)>0) { if (!m_PatAdvance) { m_Current++; if (m_Current==16) m_Current=0; m_PatAdvance=true; m_Step=-1; ExternalClockTriggered=true; } } else { m_PatAdvance=false; } // external pattern reset if (GetInput(6,n)>0) { if (!m_PatReset) { m_Current=0; m_PatReset=true; m_Step=-1; ExternalClockTriggered=true; } } else { m_PatReset=false; } */ // An external clock pulse overrides the internal timing if ((!ExternalClock && m_Time>=m_StepTime*(1/m_Matrix[m_Current].Speed)) || (ExternalClock && ExternalClockTriggered)) { m_Time=0; m_Step++; if (m_Step >= m_Matrix[m_Current].Length) { SetOutput(18, n, 1); m_Step=0; } // Reset the values m_CurrentTriggerCV=0; if (m_NoteCut) m_CurrentNoteCV=0; for (int t=0; tIsCommandWaiting()) { switch (m_AudioCH->GetCommand()) { case MAT_LENGTH : m_Matrix[m_GUICurrent].Length=m_GUIArgs.Length; break; case MAT_SPEED : m_Matrix[m_GUICurrent].Speed=m_GUIArgs.Speed; break; case MAT_ACTIVATE : m_Matrix[m_GUICurrent].Matrix[m_GUIArgs.X][m_GUIArgs.Y]=true; break; case MAT_DEACTIVATE : m_Matrix[m_GUICurrent].Matrix[m_GUIArgs.X][m_GUIArgs.Y]=false; break; case MAT_OCTAVE : m_Matrix[m_GUICurrent].Octave=m_GUIArgs.Octave; break; case COPY : CopyPattern(); break; case PASTE : PastePattern(); break; case CLEAR : ClearPattern(); break; case TUP : if (CanTransposeUp()) TransposeUp(); break; case TDOWN : if (CanTransposeDown()) TransposeDown(); break; case MAT_VOLUME : m_Matrix[m_GUICurrent].Volume[m_GUIArgs.X][m_GUIArgs.Y]=m_GUIArgs.Volume; break; case SET_CURRENT : m_Current=m_GUIArgs.Num; break; } } } void MatrixPlugin::PastePattern() { m_Matrix[m_GUICurrent].Length = m_Matrix[m_CopyPattern].Length; m_Matrix[m_GUICurrent].Speed = m_Matrix[m_CopyPattern].Speed; m_Matrix[m_GUICurrent].Octave = m_Matrix[m_CopyPattern].Octave; for (int y=0; y=0; y--) { for (x=0; x>version; switch (version) { case 1: { s>>m_Current>>m_Time>>m_Step>>m_Loop>>m_NoteCut; for (int n=0; n>m_Matrix[n].Length>>m_Matrix[n].Speed>>m_Matrix[n].Octave; for (int y=0; y>m_Matrix[n].Matrix[x][y]; } } } break; case 2: { s>>m_Current>>m_Time>>m_Step>>m_Loop>>m_NoteCut; for (int n=0; n>m_Matrix[n].Length>>m_Matrix[n].Speed>>m_Matrix[n].Octave; int x=0,y=0; while(x!=-1) { s>>x; if (x!=-1) { s>>y; if (y!=-1) m_Matrix[n].Matrix[x][y]=true; } } } } break; case 3: { s>>m_Current>>m_Time>>m_Step>>m_Loop>>m_NoteCut; for (int n=0; n>m_Matrix[n].Length>>m_Matrix[n].Speed>>m_Matrix[n].Octave; int x=0,y=0; float v; while(x!=-1) { s>>x; if (x!=-1) { s>>y>>v; if (y!=-1) { m_Matrix[n].Matrix[x][y]=true; m_Matrix[n].Volume[x][y]=v; } } } } } break; } }