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.

274 lines
5.2KB

  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 "SeqPlugin.h"
  19. #include "SeqPluginGUI.h"
  20. #include <FL/Fl_Button.h>
  21. #include "SpiralIcon.xpm"
  22. #include "../../NoteTable.h"
  23. using namespace std;
  24. // for note on's
  25. static const float TRIGGER_LEV=0.1;
  26. extern "C" {
  27. SpiralPlugin* SpiralPlugin_CreateInstance()
  28. {
  29. return new SeqPlugin;
  30. }
  31. char** SpiralPlugin_GetIcon()
  32. {
  33. return SpiralIcon_xpm;
  34. }
  35. int SpiralPlugin_GetID()
  36. {
  37. return 0x0011;
  38. }
  39. string SpiralPlugin_GetGroupName()
  40. {
  41. return "Sequencing";
  42. }
  43. }
  44. ///////////////////////////////////////////////////////
  45. SeqPlugin::SeqPlugin() :
  46. m_Time(0.0f),
  47. m_Length(10.0f),
  48. m_SpeedMod(1.0f),
  49. m_CurrentNoteCV(0),
  50. m_CurrentTriggerCV(0),
  51. m_InNoteDown(false),
  52. m_InNoteID(0),
  53. m_CurrentPattern(0),
  54. m_Triggered(false)
  55. {
  56. m_Version=2;
  57. m_PluginInfo.Name="Sequencer";
  58. m_PluginInfo.Width=540;
  59. m_PluginInfo.Height=290;
  60. m_PluginInfo.NumInputs=4;
  61. m_PluginInfo.NumOutputs=2;
  62. m_PluginInfo.PortTips.push_back("Play Trigger");
  63. m_PluginInfo.PortTips.push_back("Speed CV");
  64. m_PluginInfo.PortTips.push_back("Input Pitch CV");
  65. m_PluginInfo.PortTips.push_back("Input Trigger CV");
  66. m_PluginInfo.PortTips.push_back("Output Pitch");
  67. m_PluginInfo.PortTips.push_back("Output Trigger");
  68. }
  69. SeqPlugin::~SeqPlugin()
  70. {
  71. }
  72. PluginInfo &SeqPlugin::Initialise(const HostInfo *Host)
  73. {
  74. return SpiralPlugin::Initialise(Host);
  75. }
  76. SpiralGUIType *SeqPlugin::CreateGUI()
  77. {
  78. m_GUI = new SeqPluginGUI(m_PluginInfo.Width,
  79. m_PluginInfo.Height,
  80. this,m_HostInfo);
  81. m_GUI->hide();
  82. return m_GUI;
  83. }
  84. void SeqPlugin::SetPattern(int s)
  85. {
  86. m_Eventmap[m_CurrentPattern]->hide();
  87. m_CurrentPattern=s;
  88. m_Eventmap[m_CurrentPattern]->show();
  89. }
  90. void SeqPlugin::Execute()
  91. {
  92. float Speed;
  93. for (int n=0; n<m_HostInfo->BUFSIZE; n++)
  94. {
  95. if (GetInputPitch(0,n)>0)
  96. {
  97. if (!m_Triggered)
  98. {
  99. float Freq=GetInputPitch(0,n);
  100. // Notes 0 to 16 trigger patterns 0 to 16
  101. // No other notes catered for
  102. for (int i=0; i<NUM_PATTERNS; i++)
  103. {
  104. if (feq(Freq,NoteTable[i],0.01f))
  105. {
  106. SetPattern(i);
  107. break;
  108. }
  109. }
  110. m_Time=0;
  111. m_Triggered=true;
  112. }
  113. }
  114. else
  115. {
  116. m_Triggered=false;
  117. }
  118. if (InputExists(1))
  119. Speed =(1.1025f/m_HostInfo->SAMPLERATE) * (GetInput(1,n)+1.0f);
  120. else
  121. Speed =1.1025f/m_HostInfo->SAMPLERATE;
  122. if (!m_InNoteDown)
  123. {
  124. // Check trigger
  125. if (GetInput(3,n)>TRIGGER_LEV)
  126. {
  127. m_InNoteDown=true;
  128. float Freq=GetInputPitch(2,n);
  129. int NoteNum=0;
  130. for (int i=0; i<131; i++)
  131. {
  132. if (feq(Freq,NoteTable[i],0.01f))
  133. {
  134. NoteNum=i;
  135. break;
  136. }
  137. }
  138. /*cerr<<"note recieved ="<<NoteNum<<" f="<<Freq
  139. <<" t-1="<<NoteTable[NoteNum-1]
  140. <<" t="<<NoteTable[NoteNum]
  141. <<" t+1="<<NoteTable[NoteNum+1]<<endl;
  142. */
  143. m_InNoteID=m_Eventmap[m_CurrentPattern]->AddEventTime(m_Time, NoteNum, 0.5, Fl_SEvent::MELODY, false);
  144. m_InNoteTime=m_Time;
  145. }
  146. }
  147. else
  148. {
  149. // Check trigger
  150. if (GetInput(3,n)<TRIGGER_LEV)
  151. {
  152. m_Eventmap[m_CurrentPattern]->SetEventLength(m_InNoteID, m_Time-m_InNoteTime);
  153. m_InNoteDown=false;
  154. }
  155. }
  156. // Get the notes from the map
  157. vector<EventInfo> NoteVec=m_Eventmap[m_CurrentPattern]->GetEvents(m_Time);
  158. // play all the notes found
  159. for (vector<EventInfo>::iterator i=NoteVec.begin();
  160. i!=NoteVec.end(); i++)
  161. {
  162. if (i->m_Type==EventInfo::START)
  163. {
  164. m_CurrentNoteCV=NoteTable[i->m_Group];
  165. m_CurrentTriggerCV=1;
  166. }
  167. if (i->m_Type==EventInfo::END)
  168. {
  169. m_CurrentTriggerCV=0;
  170. if (m_NoteCut) m_CurrentNoteCV=0;
  171. }
  172. }
  173. SetOutputPitch(0,n,m_CurrentNoteCV);
  174. SetOutput(1,n,m_CurrentTriggerCV);
  175. m_Time+=Speed*m_SpeedMod;
  176. if (m_Time>m_Length)
  177. {
  178. m_Time=0;
  179. }
  180. if (m_Time<0)
  181. {
  182. m_Time=m_Length;
  183. }
  184. }
  185. }
  186. void SeqPlugin::StreamOut(ostream &s)
  187. {
  188. s<<m_Version<<" ";
  189. switch (m_Version)
  190. {
  191. case 2:
  192. {
  193. s<<m_Time<<" ";
  194. s<<m_Length<<" ";
  195. s<<m_SpeedMod<<" ";
  196. s<<m_Loop<<" ";
  197. s<<m_NoteCut<<" ";
  198. s<<m_CurrentPattern<<" ";
  199. }
  200. // fallthrough
  201. case 1:
  202. {
  203. for(int n=0; n<NUM_PATTERNS; n++)
  204. {
  205. s<<*m_Eventmap[n]<<" ";
  206. }
  207. } break;
  208. }
  209. }
  210. void SeqPlugin::StreamIn(istream &s)
  211. {
  212. int version;
  213. s>>version;
  214. switch (version)
  215. {
  216. case 2:
  217. {
  218. s>>m_Time;
  219. s>>m_Length;
  220. s>>m_SpeedMod;
  221. s>>m_Loop;
  222. s>>m_NoteCut;
  223. s>>m_CurrentPattern;
  224. }
  225. // fallthrough
  226. case 1:
  227. {
  228. for(int n=0; n<NUM_PATTERNS; n++)
  229. {
  230. s>>*m_Eventmap[n];
  231. }
  232. } break;
  233. }
  234. }