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.

267 lines
8.0KB

  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 "StreamPlugin.h"
  19. #include "StreamPluginGUI.h"
  20. #include <FL/Fl_Button.H>
  21. #include "SpiralIcon.xpm"
  22. #include "../../NoteTable.h"
  23. #include <stdio.h>
  24. #include "../../RiffWav.h"
  25. using namespace std;
  26. extern "C" {
  27. SpiralPlugin* SpiralPlugin_CreateInstance() { return new StreamPlugin; }
  28. char** SpiralPlugin_GetIcon() { return SpiralIcon_xpm; }
  29. int SpiralPlugin_GetID() { return 0x0119; }
  30. string SpiralPlugin_GetGroupName() { return "Delay/Sampling"; }
  31. }
  32. ///////////////////////////////////////////////////////
  33. static const float TRIG_THRESH = 0.1;
  34. static const float BUFSECONDS = 1.0f;
  35. StreamPlugin::StreamPlugin() :
  36. m_SampleRate (44100),
  37. m_SampleSize (256),
  38. m_StreamPos (0),
  39. m_GlobalPos (0),
  40. m_Pitch (1.0f),
  41. m_SamplePos (-1),
  42. m_Pos (0),
  43. m_Mode(STOPM)
  44. {
  45. m_PluginInfo.Name = "Stream";
  46. m_PluginInfo.Width = 245;
  47. m_PluginInfo.Height = 160;
  48. m_PluginInfo.NumInputs = 3;
  49. m_PluginInfo.NumOutputs = 5;
  50. m_PluginInfo.PortTips.push_back ("Pitch CV");
  51. m_PluginInfo.PortTips.push_back ("Play Trigger");
  52. m_PluginInfo.PortTips.push_back ("Stop Trigger");
  53. m_PluginInfo.PortTips.push_back ("Left Out");
  54. m_PluginInfo.PortTips.push_back ("Right Out");
  55. m_PluginInfo.PortTips.push_back ("Finish Trigger");
  56. m_PluginInfo.PortTips.push_back ("Playing Trigger");
  57. m_PluginInfo.PortTips.push_back ("Position CV");
  58. m_GUIArgs.Volume = 1.0f;
  59. m_GUIArgs.PitchMod = 1.0f;
  60. m_GUIArgs.PlayOut = false;
  61. strcpy (m_GUIArgs.FileName, "");
  62. m_AudioCH->Register ("Volume", &m_GUIArgs.Volume);
  63. m_AudioCH->Register ("Pitch", &m_GUIArgs.PitchMod, ChannelHandler::INPUT);
  64. m_AudioCH->RegisterData ("FileName", ChannelHandler::INPUT,
  65. &m_GUIArgs.FileName, sizeof (m_GUIArgs.FileName));
  66. m_AudioCH->RegisterData ("EchoFileName", ChannelHandler::OUTPUT,
  67. &m_GUIArgs.FileName, sizeof (m_GUIArgs.FileName));
  68. m_AudioCH->Register ("Time", &m_GUIArgs.Time);
  69. m_AudioCH->Register ("TimeOut", &m_GUIArgs.TimeOut, ChannelHandler::OUTPUT);
  70. m_AudioCH->Register ("MaxTime", &m_GUIArgs.MaxTime, ChannelHandler::OUTPUT);
  71. m_AudioCH->Register ("Playing", &m_GUIArgs.PlayOut, ChannelHandler::OUTPUT);
  72. }
  73. StreamPlugin::~StreamPlugin()
  74. {
  75. }
  76. PluginInfo &StreamPlugin::Initialise(const HostInfo *Host)
  77. {
  78. PluginInfo& Info = SpiralPlugin::Initialise(Host);
  79. return Info;
  80. }
  81. SpiralGUIType *StreamPlugin::CreateGUI() {
  82. return new StreamPluginGUI(m_PluginInfo.Width, m_PluginInfo.Height, this, m_AudioCH, m_HostInfo);
  83. }
  84. void StreamPlugin::Reset()
  85. {
  86. ResetPorts();
  87. m_StreamPos = 0;
  88. m_GlobalPos = 0;
  89. m_SamplePos = -1;
  90. m_Pos = 0;
  91. }
  92. void StreamPlugin::Execute() {
  93. if (m_File.IsOpen()) {
  94. for (int n=0; n<m_HostInfo->BUFSIZE; n++) {
  95. bool FinTrig = false;
  96. float CVPitch = GetInput(0, n)*10.0f;
  97. if (GetInput (1, n) > 0) m_Mode = PLAYM;
  98. if (GetInput (2, n) > 0) {
  99. m_Mode = STOPM;
  100. m_Pos = 0;
  101. m_GlobalPos = 0;
  102. m_StreamPos = 0;
  103. }
  104. if (m_Pos<0) {
  105. m_Pos = m_SampleSize - 1;
  106. m_StreamPos -= m_SampleSize;
  107. FinTrig = m_StreamPos < 0;
  108. if (FinTrig) {
  109. m_StreamPos = m_File.GetSize() - m_SampleSize;
  110. m_GlobalPos = m_StreamPos;
  111. }
  112. m_File.SeekToChunk (m_StreamPos);
  113. if ((m_File.GetSize() - m_StreamPos) < 256)
  114. m_SampleSize = m_File.GetSize() - m_StreamPos;
  115. else
  116. m_SampleSize = 256;
  117. m_File.LoadChunk (m_SampleSize, m_SampleL, m_SampleR);
  118. }
  119. else if (m_Pos >= m_SampleSize) {
  120. m_Pos = 0;
  121. m_StreamPos += m_SampleSize;
  122. FinTrig = m_StreamPos >= m_File.GetSize();
  123. if (FinTrig) {
  124. m_StreamPos = 0;
  125. m_GlobalPos = 0;
  126. }
  127. m_File.SeekToChunk (m_StreamPos);
  128. if ((m_File.GetSize() - m_StreamPos) < 256)
  129. m_SampleSize = m_File.GetSize() - m_StreamPos;
  130. else
  131. m_SampleSize = 256;
  132. m_File.LoadChunk (m_SampleSize, m_SampleL, m_SampleR);
  133. }
  134. // finished trigger
  135. if (FinTrig) SetOutput (2, n, 1);
  136. else SetOutput (2, n, 0);
  137. if (m_Mode==PLAYM) {
  138. // left and right outputs
  139. SetOutput (0, n, m_SampleL[m_Pos] * m_GUIArgs.Volume);
  140. SetOutput (1, n, m_SampleR[m_Pos] * m_GUIArgs.Volume);
  141. // play trigger
  142. SetOutput (3, n, 1);
  143. m_Pos += m_GUIArgs.PitchMod + CVPitch;
  144. m_GlobalPos += m_GUIArgs.PitchMod + CVPitch;
  145. float plop = m_GlobalPos / (float)m_File.GetSize();
  146. SetOutput (4, n, plop);
  147. }
  148. else {
  149. SetOutput (0, n, 0);
  150. SetOutput (1, n, 0);
  151. SetOutput (3, n, 0);
  152. SetOutput (4, n, 0);
  153. }
  154. }
  155. m_GUIArgs.TimeOut = m_GlobalPos / (float)m_SampleRate;
  156. m_GUIArgs.PlayOut = m_Mode==PLAYM;
  157. }
  158. }
  159. void StreamPlugin::ExecuteCommands() {
  160. if (m_AudioCH->IsCommandWaiting()) {
  161. switch (m_AudioCH->GetCommand()) {
  162. case SET_TIME:
  163. SetTime();
  164. break;
  165. case LOAD:
  166. OpenStream();
  167. break;
  168. case RESTART:
  169. m_StreamPos = 0;
  170. m_GlobalPos = 0;
  171. break;
  172. case STOP:
  173. m_Mode = STOPM;
  174. break;
  175. case PLAY:
  176. m_Mode = PLAYM;
  177. break;
  178. }
  179. }
  180. }
  181. void StreamPlugin::SetTime (void) {
  182. m_GlobalPos = m_SampleRate * m_GUIArgs.Time;
  183. m_StreamPos = (int)(m_SampleRate * m_GUIArgs.Time);
  184. m_Pos = m_SampleSize;
  185. }
  186. void StreamPlugin::OpenStream (void) {
  187. m_StreamPos = 0;
  188. m_GlobalPos = 0;
  189. if (m_File.IsOpen ()) m_File.Close ();
  190. m_File.Open (m_GUIArgs.FileName, WavFile::READ);
  191. if (m_File.GetSize() < 256)
  192. m_SampleSize = m_File.GetSize();
  193. else
  194. m_SampleSize = 256;
  195. m_SampleL.Allocate (m_SampleSize);
  196. m_SampleR.Allocate (m_SampleSize);
  197. m_Pitch = m_SampleRate / (float)m_HostInfo->SAMPLERATE;
  198. if (m_File.IsStereo ()) {
  199. m_Pitch *= 2;
  200. m_GUIArgs.MaxTime = GetLength();
  201. }
  202. else m_GUIArgs.MaxTime = GetLength() / 2;
  203. }
  204. float StreamPlugin::GetLength (void) {
  205. if (m_File.IsStereo()) return m_File.GetSize() / (float)m_File.GetSamplerate ();
  206. else return m_File.GetSize() / (float)m_File.GetSamplerate () * 2;
  207. }
  208. void StreamPlugin::StreamOut (ostream &s) {
  209. s << m_Version << " "
  210. << m_GUIArgs.Volume << " "
  211. << m_GUIArgs.PitchMod << " "
  212. << strlen (m_GUIArgs.FileName) << " "
  213. << m_GUIArgs.FileName << " "
  214. // is it really necessary to save this lot??
  215. << m_Pos << " "
  216. << m_StreamPos << " "
  217. << m_GlobalPos << " "
  218. << m_Pitch << " " << endl;
  219. }
  220. void StreamPlugin::StreamIn(istream &s) {
  221. int version;
  222. s >> version;
  223. s >> m_GUIArgs.Volume >> m_GUIArgs.PitchMod;
  224. int size;
  225. s >> size;
  226. if (size > 255) size = 255;
  227. s.ignore (1);
  228. s.get (m_GUIArgs.FileName, size+1);
  229. if (m_GUIArgs.FileName != "None") OpenStream ();
  230. // is it really necessary to load this lot??
  231. s >> m_Pos;
  232. s >> m_StreamPos;
  233. s >> m_GlobalPos;
  234. s >> m_Pitch;
  235. }