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.

447 lines
12KB

  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 "PoshSamplerPlugin.h"
  19. #include "PoshSamplerPluginGUI.h"
  20. #include <FL/Fl_Button.h>
  21. #include "SpiralIcon.xpm"
  22. #include "../../RiffWav.h"
  23. #include "../../NoteTable.h"
  24. #include <stdio.h>
  25. static const int NOTETRIG = NUM_SAMPLES*2+1;
  26. static const int REC_INPUT = 16;
  27. static const int S1_INPUT = 18;
  28. static const int S2_INPUT = 19;
  29. static const int S3_INPUT = 20;
  30. extern "C" {
  31. SpiralPlugin* CreateInstance()
  32. {
  33. return new PoshSamplerPlugin;
  34. }
  35. char** GetIcon()
  36. {
  37. return SpiralIcon_xpm;
  38. }
  39. int GetID()
  40. {
  41. return 32;
  42. }
  43. }
  44. ///////////////////////////////////////////////////////
  45. PoshSamplerPlugin::PoshSamplerPlugin() :
  46. m_Recording(false)
  47. {
  48. m_PluginInfo.Name="PoshSampler";
  49. m_PluginInfo.Width=400;
  50. m_PluginInfo.Height=215;
  51. m_PluginInfo.NumInputs=21;
  52. m_PluginInfo.NumOutputs=9;
  53. m_PluginInfo.PortTips.push_back("Sample 1 Pitch");
  54. m_PluginInfo.PortTips.push_back("Sample 1 Trigger");
  55. m_PluginInfo.PortTips.push_back("Sample 2 Pitch");
  56. m_PluginInfo.PortTips.push_back("Sample 2 Trigger");
  57. m_PluginInfo.PortTips.push_back("Sample 3 Pitch");
  58. m_PluginInfo.PortTips.push_back("Sample 3 Trigger");
  59. m_PluginInfo.PortTips.push_back("Sample 4 Pitch");
  60. m_PluginInfo.PortTips.push_back("Sample 4 Trigger");
  61. m_PluginInfo.PortTips.push_back("Sample 5 Pitch");
  62. m_PluginInfo.PortTips.push_back("Sample 5 Trigger");
  63. m_PluginInfo.PortTips.push_back("Sample 6 Pitch");
  64. m_PluginInfo.PortTips.push_back("Sample 6 Trigger");
  65. m_PluginInfo.PortTips.push_back("Sample 7 Pitch");
  66. m_PluginInfo.PortTips.push_back("Sample 7 Trigger");
  67. m_PluginInfo.PortTips.push_back("Sample 8 Pitch");
  68. m_PluginInfo.PortTips.push_back("Sample 8 Trigger");
  69. m_PluginInfo.PortTips.push_back("Input");
  70. m_PluginInfo.PortTips.push_back("Sample trigger pitch");
  71. m_PluginInfo.PortTips.push_back("Sample 1 Start Pos");
  72. m_PluginInfo.PortTips.push_back("Sample 2 Start Pos");
  73. m_PluginInfo.PortTips.push_back("Sample 3 Start Pos");
  74. m_PluginInfo.PortTips.push_back("Mixed Output");
  75. m_PluginInfo.PortTips.push_back("Sample 1 Output");
  76. m_PluginInfo.PortTips.push_back("Sample 2 Output");
  77. m_PluginInfo.PortTips.push_back("Sample 3 Output");
  78. m_PluginInfo.PortTips.push_back("Sample 4 Output");
  79. m_PluginInfo.PortTips.push_back("Sample 5 Output");
  80. m_PluginInfo.PortTips.push_back("Sample 6 Output");
  81. m_PluginInfo.PortTips.push_back("Sample 7 Output");
  82. m_PluginInfo.PortTips.push_back("Sample 8 Output");
  83. for (int n=0; n<NUM_SAMPLES; n++)
  84. {
  85. Sample* NewSample = new Sample;
  86. m_SampleVec.push_back(NewSample);
  87. SampleDesc* NewDesc = new SampleDesc;
  88. char temp[256];
  89. sprintf(temp,"PoshSampler%d_%d",GetID(),n);
  90. NewDesc->Pathname = temp;
  91. NewDesc->Volume = 1.0f;
  92. NewDesc->Velocity = 1.0f;
  93. NewDesc->Pitch = 1.0f;
  94. NewDesc->PitchMod = 1.0f;
  95. NewDesc->SamplePos = -1;
  96. NewDesc->Loop = false;
  97. NewDesc->PingPong = false;
  98. NewDesc->Note = n;
  99. NewDesc->Octave = 0;
  100. NewDesc->TriggerUp = true;
  101. NewDesc->SamplePos = -1;
  102. NewDesc->SampleRate = 44100;
  103. NewDesc->Stereo = false;
  104. NewDesc->PlayStart = 0;
  105. NewDesc->LoopStart = 0;
  106. NewDesc->LoopEnd = INT_MAX;
  107. m_SampleDescVec.push_back(NewDesc);
  108. }
  109. m_Version=3;
  110. }
  111. PoshSamplerPlugin::~PoshSamplerPlugin()
  112. {
  113. for (vector<Sample*>::iterator i=m_SampleVec.begin();
  114. i!=m_SampleVec.end(); i++)
  115. {
  116. delete(*i);
  117. }
  118. for (vector<SampleDesc*>::iterator i=m_SampleDescVec.begin();
  119. i!=m_SampleDescVec.end(); i++)
  120. {
  121. delete(*i);
  122. }
  123. }
  124. PluginInfo &PoshSamplerPlugin::Initialise(const HostInfo *Host)
  125. {
  126. return SpiralPlugin::Initialise(Host);;
  127. }
  128. SpiralGUIType *PoshSamplerPlugin::CreateGUI()
  129. {
  130. m_GUI = new PoshSamplerPluginGUI(m_PluginInfo.Width,
  131. m_PluginInfo.Height,
  132. this,m_HostInfo);
  133. m_GUI->hide();
  134. return m_GUI;
  135. }
  136. void PoshSamplerPlugin::Execute()
  137. {
  138. static bool Pong=false;
  139. for (int s=0; s<NUM_SAMPLES+1; s++)
  140. {
  141. GetOutputBuf(s)->Zero();
  142. }
  143. float Freq=0;
  144. for (int n=0; n<m_HostInfo->BUFSIZE; n++)
  145. {
  146. Freq=GetInputPitch(NOTETRIG,n);
  147. for (int s=0; s<NUM_SAMPLES; s++)
  148. {
  149. SampleDesc* S=m_SampleDescVec[s];
  150. // if we have a sample here
  151. if (m_SampleVec[s]->GetLength())
  152. {
  153. // Convert the CV input into a useable trigger
  154. if (GetInput(s*2+1,n)>0 || feq(Freq,NoteTable[S->Note],0.01f))
  155. {
  156. if (S->TriggerUp)
  157. {
  158. if (s==0 && InputExists(S1_INPUT))
  159. S->PlayStart=(long int)((GetInput(S1_INPUT,n)*0.5+0.5f)*(S->LoopEnd-S->LoopStart))+S->LoopStart;
  160. if (s==1 && InputExists(S2_INPUT))
  161. S->PlayStart=(long int)((GetInput(S2_INPUT,n)*0.5+0.5f)*(S->LoopEnd-S->LoopStart))+S->LoopStart;
  162. if (s==2 && InputExists(S3_INPUT))
  163. S->PlayStart=(long int)((GetInput(S3_INPUT,n)*0.5+0.5f)*(S->LoopEnd-S->LoopStart))+S->LoopStart;
  164. if (S->PlayStart<0) S->PlayStart=0;
  165. S->SamplePos=S->PlayStart;
  166. S->TriggerUp=false;
  167. S->Velocity=GetInput(s*2+1,n);
  168. }
  169. }
  170. else
  171. {
  172. S->TriggerUp=true;
  173. // end it if it's looping
  174. if (S->Loop)
  175. {
  176. S->SamplePos=-1;
  177. }
  178. }
  179. // if the sample has ended
  180. if (S->SamplePos>=S->LoopEnd || S->SamplePos>=m_SampleVec[s]->GetLength())
  181. {
  182. if (S->Loop)
  183. {
  184. if (S->PingPong) Pong=true;
  185. else S->SamplePos=S->LoopStart;
  186. }
  187. else
  188. {
  189. S->SamplePos=-1;
  190. }
  191. }
  192. // if the sample has ended ponging
  193. if (Pong && S->SamplePos<=S->LoopStart)
  194. {
  195. Pong=false;
  196. }
  197. if (S->SamplePos!=-1)
  198. {
  199. if (InputExists(s*2))
  200. {
  201. // Get the pitch from the CV
  202. float PlayFreq=GetInputPitch(s*2,n);
  203. // assumtion: base frequency = 440 (middle A)
  204. S->Pitch = PlayFreq/440;
  205. S->Pitch *= S->SampleRate/(float)m_HostInfo->SAMPLERATE;
  206. }
  207. // mix the sample to the output.
  208. MixOutput(0,n,(*m_SampleVec[s])[S->SamplePos]*S->Volume*S->Velocity);
  209. // copy the sample to it's individual output.
  210. SetOutput(s+1,n,((*m_SampleVec[s])[S->SamplePos]*S->Volume));
  211. float Freq=S->Pitch;
  212. if (S->Octave>0) Freq*=1<<(S->Octave);
  213. if (S->Octave<0) Freq/=1<<(-S->Octave);
  214. if (Pong) S->SamplePos-=Freq*S->PitchMod;
  215. else S->SamplePos+=Freq*S->PitchMod;
  216. }
  217. }
  218. }
  219. }
  220. PoshSamplerPluginGUI *GUI=(PoshSamplerPluginGUI *)m_GUI;
  221. // record
  222. static int LastRecording=false;
  223. if(m_Recording && InputExists(REC_INPUT))
  224. {
  225. int s=GUI->GetCurrentSample();
  226. if (!LastRecording) m_SampleVec[s]->Clear();
  227. // new sample
  228. if (m_SampleVec[s]->GetLength()==0)
  229. {
  230. *m_SampleVec[s]=*GetInput(REC_INPUT);
  231. m_SampleDescVec[s]->SampleRate=m_HostInfo->SAMPLERATE;
  232. m_SampleDescVec[s]->Stereo=false;
  233. m_SampleDescVec[s]->Pitch *= 1.0f;
  234. m_SampleDescVec[s]->LoopEnd=m_SampleVec[s]->GetLength();
  235. }
  236. else
  237. {
  238. m_SampleVec[s]->Add(*GetInput(REC_INPUT));
  239. m_SampleDescVec[s]->LoopEnd=m_SampleVec[s]->GetLength();
  240. }
  241. }
  242. LastRecording=m_Recording;
  243. if (m_SampleDescVec[GUI->GetCurrentSample()]->SamplePos>0)
  244. {
  245. GUI->SetPlayPos((int)m_SampleDescVec[GUI->GetCurrentSample()]->SamplePos);
  246. }
  247. }
  248. #include <FL/fl_file_chooser.H>
  249. void PoshSamplerPlugin::StreamOut(ostream &s)
  250. {
  251. s<<m_Version<<" ";
  252. for (int n=0; n<NUM_SAMPLES; n++)
  253. {
  254. s<<m_SampleDescVec[n]->Volume<<" "<<
  255. m_SampleDescVec[n]->PitchMod<<" "<<
  256. m_SampleDescVec[n]->Loop<<" "<<
  257. m_SampleDescVec[n]->PingPong<<" "<<
  258. m_SampleDescVec[n]->Note<<" "<<
  259. m_SampleDescVec[n]->Octave<<" "<<
  260. m_SampleDescVec[n]->SamplePos<<" "<<
  261. m_SampleDescVec[n]->PlayStart<<" "<<
  262. m_SampleDescVec[n]->LoopStart<<" "<<
  263. m_SampleDescVec[n]->LoopEnd<<" "<<
  264. m_SampleDescVec[n]->Note<<" ";
  265. }
  266. }
  267. void PoshSamplerPlugin::StreamIn(istream &s)
  268. {
  269. int version;
  270. s>>version;
  271. for (int n=0; n<NUM_SAMPLES; n++)
  272. {
  273. s>>m_SampleDescVec[n]->Volume>>
  274. m_SampleDescVec[n]->PitchMod>>
  275. m_SampleDescVec[n]->Loop>>
  276. m_SampleDescVec[n]->PingPong>>
  277. m_SampleDescVec[n]->Note>>
  278. m_SampleDescVec[n]->Octave>>
  279. m_SampleDescVec[n]->SamplePos>>
  280. m_SampleDescVec[n]->PlayStart>>
  281. m_SampleDescVec[n]->LoopStart>>
  282. m_SampleDescVec[n]->LoopEnd>>
  283. m_SampleDescVec[n]->Note;
  284. if (version<3)
  285. {
  286. int size;
  287. s>>size;
  288. s.ignore(1);
  289. char Buf[4096];
  290. s.get(Buf,size+1);
  291. }
  292. }
  293. ((PoshSamplerPluginGUI*)m_GUI)->UpdateValues();
  294. }
  295. void PoshSamplerPlugin::LoadSample(int n, const string &Name)
  296. {
  297. WavFile Wav;
  298. if (Wav.Open(Name,WavFile::READ))
  299. {
  300. m_SampleVec[n]->Allocate(Wav.GetSize());
  301. Wav.Load(*m_SampleVec[n]);
  302. m_SampleDescVec[n]->Pathname=Name;
  303. m_SampleDescVec[n]->SampleRate=Wav.GetSamplerate();
  304. m_SampleDescVec[n]->Stereo=Wav.IsStereo();
  305. m_SampleDescVec[n]->Pitch *= m_SampleDescVec[n]->SampleRate/(float)m_HostInfo->SAMPLERATE;
  306. m_SampleDescVec[n]->LoopEnd=m_SampleVec[n]->GetLength()-1;
  307. }
  308. }
  309. void PoshSamplerPlugin::SaveSample(int n, const string &Name)
  310. {
  311. if (m_SampleVec[n]->GetLength()==0) return;
  312. WavFile Wav;
  313. Wav.Open(Name,WavFile::WRITE,WavFile::MONO);
  314. Wav.Save(*m_SampleVec[n]);
  315. }
  316. void PoshSamplerPlugin::Cut(int n, long s, long e)
  317. {
  318. if (m_SampleVec[n]->GetLength()==0) return;
  319. m_SampleVec[n]->GetRegion(m_CopyBuffer, s, e);
  320. m_SampleVec[n]->Remove(s, e);
  321. }
  322. void PoshSamplerPlugin::Copy(int n, long s, long e)
  323. {
  324. if (m_SampleVec[n]->GetLength()==0) return;
  325. m_SampleVec[n]->GetRegion(m_CopyBuffer, s, e);
  326. }
  327. void PoshSamplerPlugin::Paste(int n, long s, long e)
  328. {
  329. if (m_SampleVec[n]->GetLength()==0) return;
  330. m_SampleVec[n]->Insert(m_CopyBuffer, s);
  331. }
  332. void PoshSamplerPlugin::Mix(int n, long s, long e)
  333. {
  334. if (m_SampleVec[n]->GetLength()==0) return;
  335. m_SampleVec[n]->Mix(m_CopyBuffer, s);
  336. }
  337. void PoshSamplerPlugin::Crop(int n, long s, long e)
  338. {
  339. if (m_SampleVec[n]->GetLength()==0) return;
  340. m_SampleVec[n]->Remove(0, s);
  341. m_SampleVec[n]->Remove(e, m_SampleVec[n]->GetLength()-1);
  342. }
  343. void PoshSamplerPlugin::Reverse(int n, long s, long e)
  344. {
  345. if (m_SampleVec[n]->GetLength()==0) return;
  346. m_SampleVec[n]->Reverse(s, e);
  347. }
  348. void PoshSamplerPlugin::Amp(int n, long s, long e)
  349. {
  350. if (m_SampleVec[n]->GetLength()==0) return;
  351. for (int m=0; m<m_SampleVec[n]->GetLength(); m++)
  352. {
  353. m_SampleVec[n]->Set(m,(*m_SampleVec[n])[m]*m_SampleDescVec[n]->Volume);
  354. }
  355. }
  356. bool PoshSamplerPlugin::SaveExternalFiles(const string &Dir)
  357. {
  358. for (int n=0; n<NUM_SAMPLES; n++)
  359. {
  360. char temp[256];
  361. sprintf(temp,"PoshSampler%d_%d.wav",GetID(),n);
  362. m_SampleDescVec[n]->Pathname = temp;
  363. }
  364. for (int n=0; n<NUM_SAMPLES; n++)
  365. {
  366. // if it's not empty
  367. if (m_SampleVec[n]->GetLength()!=0)
  368. {
  369. SaveSample(n,Dir+m_SampleDescVec[n]->Pathname);
  370. }
  371. }
  372. return true;
  373. }
  374. void PoshSamplerPlugin::LoadExternalFiles(const string &Dir)
  375. {
  376. for (int n=0; n<NUM_SAMPLES; n++)
  377. {
  378. char temp[256];
  379. sprintf(temp,"PoshSampler%d_%d.wav",GetID(),n);
  380. m_SampleDescVec[n]->Pathname = temp;
  381. }
  382. for (int n=0; n<NUM_SAMPLES; n++)
  383. {
  384. LoadSample(n,Dir+m_SampleDescVec[n]->Pathname);
  385. }
  386. }