You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
8.3KB

  1. /* SpiralSound
  2. * Copyleft (C) 2001 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. #include "MatrixPlugin.h"
  19. #include "MatrixPluginGUI.h"
  20. #include <FL/Fl_Button.h>
  21. #include "SpiralIcon.xpm"
  22. #include "../../RiffWav.h"
  23. #include "../../NoteTable.h"
  24. extern "C" {
  25. SpiralPlugin* CreateInstance()
  26. {
  27. return new MatrixPlugin;
  28. }
  29. char** GetIcon()
  30. {
  31. return SpiralIcon_xpm;
  32. }
  33. int GetID()
  34. {
  35. return 0x0012;
  36. }
  37. }
  38. ///////////////////////////////////////////////////////
  39. MatrixPlugin::MatrixPlugin() :
  40. m_TickTime(1.0f),
  41. m_StepTime(1.0f),
  42. m_Time(0.0f),
  43. m_Step(0),
  44. m_Loop(true),
  45. m_NoteCut(false),
  46. m_Current(0),
  47. m_CurrentNoteCV(0),
  48. m_CurrentTriggerCV(0),
  49. m_Triggered(false),
  50. m_ClockHigh(false),
  51. m_CopyPattern(0)
  52. {
  53. m_Version=2;
  54. m_PluginInfo.Name="Matrix";
  55. m_PluginInfo.Width=555;
  56. m_PluginInfo.Height=270;
  57. m_PluginInfo.NumInputs=5;
  58. m_PluginInfo.NumOutputs=19;
  59. m_PluginInfo.PortTips.push_back("Play Trigger");
  60. m_PluginInfo.PortTips.push_back("StepTime CV");
  61. m_PluginInfo.PortTips.push_back("Input Pitch CV");
  62. m_PluginInfo.PortTips.push_back("Input Trigger CV");
  63. m_PluginInfo.PortTips.push_back("External Clock");
  64. m_PluginInfo.PortTips.push_back("Output Pitch");
  65. m_PluginInfo.PortTips.push_back("Output Trigger");
  66. m_PluginInfo.PortTips.push_back("Trigger 1");
  67. m_PluginInfo.PortTips.push_back("Trigger 2");
  68. m_PluginInfo.PortTips.push_back("Trigger 3");
  69. m_PluginInfo.PortTips.push_back("Trigger 4");
  70. m_PluginInfo.PortTips.push_back("Trigger 5");
  71. m_PluginInfo.PortTips.push_back("Trigger 6");
  72. m_PluginInfo.PortTips.push_back("Trigger 7");
  73. m_PluginInfo.PortTips.push_back("Trigger 8");
  74. m_PluginInfo.PortTips.push_back("Trigger 9");
  75. m_PluginInfo.PortTips.push_back("Trigger 10");
  76. m_PluginInfo.PortTips.push_back("Trigger 11");
  77. m_PluginInfo.PortTips.push_back("Trigger 12");
  78. m_PluginInfo.PortTips.push_back("Trigger 13");
  79. m_PluginInfo.PortTips.push_back("Trigger 14");
  80. m_PluginInfo.PortTips.push_back("Trigger 15");
  81. m_PluginInfo.PortTips.push_back("Trigger 16");
  82. m_PluginInfo.PortTips.push_back("Reset Trigger");
  83. for (int n=0; n<NUM_PATTERNS; n++)
  84. {
  85. m_Matrix[n].Length=32;
  86. m_Matrix[n].Speed=1.0f;
  87. m_Matrix[n].Octave=0;
  88. for (int x=0; x<MATX; x++)
  89. for (int y=0; y<MATY; y++)
  90. {
  91. m_Matrix[n].Matrix[x][y]=false;
  92. }
  93. m_TriggerLevel[n]=0;
  94. }
  95. }
  96. MatrixPlugin::~MatrixPlugin()
  97. {
  98. }
  99. PluginInfo &MatrixPlugin::Initialise(const HostInfo *Host)
  100. {
  101. PluginInfo& Info = SpiralPlugin::Initialise(Host);
  102. m_TickTime = 1.0f/(float)m_HostInfo->SAMPLERATE;
  103. return Info;
  104. }
  105. SpiralGUIType *MatrixPlugin::CreateGUI()
  106. {
  107. m_GUI = new MatrixPluginGUI(m_PluginInfo.Width,
  108. m_PluginInfo.Height,
  109. this,m_HostInfo);
  110. m_GUI->hide();
  111. return m_GUI;
  112. }
  113. void MatrixPlugin::Execute()
  114. {
  115. for (int n=0; n<m_HostInfo->BUFSIZE; n++)
  116. {
  117. if (InputExists(1)) m_StepTime = GetInput(1,n);
  118. // inc time
  119. m_Time+=m_TickTime;
  120. SetOutputPitch(0,n,m_CurrentNoteCV);
  121. SetOutput(1,n,m_CurrentTriggerCV);
  122. if (m_Step+1 >= m_Matrix[m_Current].Length) SetOutput(18, n, 1);
  123. else SetOutput(18, n, 0);
  124. if (GetInputPitch(0,n)>0)
  125. {
  126. if (!m_Triggered)
  127. {
  128. float Freq=GetInputPitch(0,n);
  129. // Notes 0 to 16 trigger patterns 0 to 16
  130. // No other notes catered for
  131. for (int i=0; i<NUM_PATTERNS; i++)
  132. {
  133. if (feq(Freq,NoteTable[i],0.01f))
  134. {
  135. m_Current=i;
  136. break;
  137. }
  138. }
  139. // make it so the next note to trigger
  140. // will be the first one
  141. if (m_GUI) ((MatrixPluginGUI*)m_GUI)->UpdateValues();
  142. m_Time=m_StepTime*(1/m_Matrix[m_Current].Speed);
  143. m_Step=-1;
  144. m_Triggered=true;
  145. }
  146. }
  147. else
  148. {
  149. m_Triggered=false;
  150. }
  151. // set the individual triggers
  152. for (int t=0; t<NUM_PATTERNS; t++) SetOutput(t+2,n,m_TriggerLevel[t]);
  153. bool ExternalClock = InputExists(4);
  154. bool ExternalClockTriggered=false;
  155. if (ExternalClock)
  156. {
  157. if (GetInput(4,n)>0)
  158. {
  159. if(!m_ClockHigh)
  160. {
  161. m_ClockHigh=true;
  162. ExternalClockTriggered=true;
  163. }
  164. }
  165. else
  166. {
  167. if (m_ClockHigh)
  168. {
  169. m_ClockHigh=false;
  170. ExternalClockTriggered=true;
  171. }
  172. }
  173. }
  174. // An external clock pulse overrides the internal timing
  175. if ((!ExternalClock && m_Time>=m_StepTime*(1/m_Matrix[m_Current].Speed)) ||
  176. (ExternalClock && ExternalClockTriggered))
  177. {
  178. m_Time=0;
  179. m_Step++;
  180. if (m_Step >= m_Matrix[m_Current].Length) m_Step=0;
  181. if (m_GUI) ((MatrixPluginGUI*)m_GUI)->SetLED(m_Step);
  182. // Reset the values
  183. m_CurrentTriggerCV=0;
  184. if (m_NoteCut) m_CurrentNoteCV=0;
  185. for (int t=0; t<NUM_PATTERNS; t++)
  186. {
  187. SetOutput(t+2,n,0);
  188. m_TriggerLevel[t]=0;
  189. }
  190. // Scan the matrix at current time
  191. for (int i=0; i<MATY; i++)
  192. {
  193. if (m_Matrix[m_Current].Matrix[m_Step][i])
  194. {
  195. m_CurrentNoteCV=NoteTable[i+m_Matrix[m_Current].Octave*12];
  196. m_CurrentTriggerCV=1;
  197. m_TriggerLevel[i]=1;
  198. }
  199. }
  200. // reset the triggers between steps to clear them
  201. // otherwise consecutive events wont get triggered
  202. SetOutput(1,n,0);
  203. for (int t=0; t<NUM_PATTERNS; t++) SetOutput(t+2,n,0);
  204. }
  205. }
  206. }
  207. void MatrixPlugin::PastePattern() {
  208. cerr<<hex<<this<<dec<<endl;
  209. cerr<<m_CopyPattern<<endl;
  210. m_Matrix[m_Current].Length = m_Matrix[m_CopyPattern].Length;
  211. m_Matrix[m_Current].Speed = m_Matrix[m_CopyPattern].Speed;
  212. m_Matrix[m_Current].Octave = m_Matrix[m_CopyPattern].Octave;
  213. for (int y=0; y<MATY; y++) {
  214. for (int x=0; x<MATX; x++) {
  215. m_Matrix[m_Current].Matrix[x][y] = m_Matrix[m_CopyPattern].Matrix[x][y];
  216. }
  217. }
  218. }
  219. void MatrixPlugin::ClearPattern() {
  220. for (int y=0; y<MATY; y++) {
  221. for (int x=0; x<MATX; x++) {
  222. m_Matrix[m_Current].Matrix[x][y] = 0;
  223. }
  224. }
  225. }
  226. void MatrixPlugin::TransposeUp() {
  227. int x, y;
  228. for (y=MATY-1; y>=0; y--) {
  229. for (x=0; x<MATX; x++) {
  230. m_Matrix[m_Current].Matrix[x][y] = m_Matrix[m_Current].Matrix[x][y-1];
  231. }
  232. }
  233. for (x=0; x<MATX; x++) {
  234. m_Matrix[m_Current].Matrix[x][0] = 0;
  235. }
  236. }
  237. void MatrixPlugin::TransposeDown()
  238. {
  239. int x, y;
  240. for (y=0; y<MATY-1; y++)
  241. {
  242. for (x=0; x<MATX; x++)
  243. {
  244. m_Matrix[m_Current].Matrix[x][y] = m_Matrix[m_Current].Matrix[x][y+1];
  245. }
  246. }
  247. for (x=0; x<MATX; x++)
  248. {
  249. m_Matrix[m_Current].Matrix[x][MATY-1] = 0;
  250. }
  251. }
  252. bool MatrixPlugin::CanTransposeDown()
  253. {
  254. for (int x=0; x<MATX; x++) if (m_Matrix[m_Current].Matrix[x][0]) return False;
  255. return True;
  256. }
  257. bool MatrixPlugin::CanTransposeUp()
  258. {
  259. for (int x=0; x<MATX; x++) if (m_Matrix[m_Current].Matrix[x][MATY-1]) return False;
  260. return True;
  261. }
  262. void MatrixPlugin::StreamOut(ostream &s)
  263. {
  264. s<<m_Version<<" ";
  265. s<<m_Current<<" "<<m_Time<<" "<<m_Step<<" "<<m_Loop<<" "<<m_NoteCut<<" "<<endl;
  266. for (int n=0; n<NUM_PATTERNS; n++)
  267. {
  268. s<<m_Matrix[n].Length<<" "<<m_Matrix[n].Speed<<" "<<m_Matrix[n].Octave<<endl;
  269. for (int y=0; y<MATY; y++)
  270. {
  271. for (int x=0; x<MATX; x++)
  272. {
  273. if (m_Matrix[n].Matrix[x][y]) s<<x<<" "<<y<<" ";
  274. }
  275. }
  276. s<<"-1 ";
  277. }
  278. }
  279. void MatrixPlugin::StreamIn(istream &s)
  280. {
  281. int version;
  282. s>>version;
  283. switch (version)
  284. {
  285. case 1:
  286. {
  287. s>>m_Current>>m_Time>>m_Step>>m_Loop>>m_NoteCut;
  288. for (int n=0; n<NUM_PATTERNS; n++)
  289. {
  290. s>>m_Matrix[n].Length>>m_Matrix[n].Speed>>m_Matrix[n].Octave;
  291. for (int y=0; y<MATY; y++)
  292. for (int x=0; x<MATX; x++)
  293. {
  294. s>>m_Matrix[n].Matrix[x][y];
  295. }
  296. }
  297. } break;
  298. case 2:
  299. {
  300. s>>m_Current>>m_Time>>m_Step>>m_Loop>>m_NoteCut;
  301. for (int n=0; n<NUM_PATTERNS; n++)
  302. {
  303. s>>m_Matrix[n].Length>>m_Matrix[n].Speed>>m_Matrix[n].Octave;
  304. int x=0,y=0;
  305. while(x!=-1)
  306. {
  307. s>>x;
  308. if (x!=-1)
  309. {
  310. s>>y;
  311. if (y!=-1) m_Matrix[n].Matrix[x][y]=true;
  312. }
  313. }
  314. }
  315. } break;
  316. }
  317. }