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.

473 lines
18KB

  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 "../../NoteTable.h"
  23. #include "../../RiffWav.h"
  24. #include <stdio.h>
  25. using namespace std;
  26. static const int NOTETRIG = NUM_SAMPLES * 2 + 1;
  27. static const int REC_INPUT = 16;
  28. static const int S1_INPUT = 18;
  29. static const int S2_INPUT = 19;
  30. static const int S3_INPUT = 20;
  31. extern "C" {
  32. SpiralPlugin* SpiralPlugin_CreateInstance() { return new PoshSamplerPlugin; }
  33. char** SpiralPlugin_GetIcon() { return SpiralIcon_xpm; }
  34. int SpiralPlugin_GetID() { return 32; }
  35. string SpiralPlugin_GetGroupName() { return "Delay/Sampling"; }
  36. }
  37. ///////////////////////////////////////////////////////
  38. PoshSamplerPlugin::PoshSamplerPlugin() :
  39. m_Recording(false)
  40. {
  41. m_PluginInfo.Name = "PoshSampler";
  42. m_PluginInfo.Width = 400;
  43. m_PluginInfo.Height = 215;
  44. m_PluginInfo.NumInputs = 21;
  45. m_PluginInfo.NumOutputs = 9;
  46. m_PluginInfo.PortTips.push_back ("Sample 1 Pitch");
  47. m_PluginInfo.PortTips.push_back ("Sample 1 Trigger");
  48. m_PluginInfo.PortTips.push_back ("Sample 2 Pitch");
  49. m_PluginInfo.PortTips.push_back ("Sample 2 Trigger");
  50. m_PluginInfo.PortTips.push_back ("Sample 3 Pitch");
  51. m_PluginInfo.PortTips.push_back ("Sample 3 Trigger");
  52. m_PluginInfo.PortTips.push_back ("Sample 4 Pitch");
  53. m_PluginInfo.PortTips.push_back ("Sample 4 Trigger");
  54. m_PluginInfo.PortTips.push_back ("Sample 5 Pitch");
  55. m_PluginInfo.PortTips.push_back ("Sample 5 Trigger");
  56. m_PluginInfo.PortTips.push_back ("Sample 6 Pitch");
  57. m_PluginInfo.PortTips.push_back ("Sample 6 Trigger");
  58. m_PluginInfo.PortTips.push_back ("Sample 7 Pitch");
  59. m_PluginInfo.PortTips.push_back ("Sample 7 Trigger");
  60. m_PluginInfo.PortTips.push_back ("Sample 8 Pitch");
  61. m_PluginInfo.PortTips.push_back ("Sample 8 Trigger");
  62. m_PluginInfo.PortTips.push_back ("Input");
  63. m_PluginInfo.PortTips.push_back ("Sample trigger pitch");
  64. m_PluginInfo.PortTips.push_back ("Sample 1 Start Pos");
  65. m_PluginInfo.PortTips.push_back ("Sample 2 Start Pos");
  66. m_PluginInfo.PortTips.push_back ("Sample 3 Start Pos");
  67. m_PluginInfo.PortTips.push_back ("Mixed Output");
  68. m_PluginInfo.PortTips.push_back ("Sample 1 Output");
  69. m_PluginInfo.PortTips.push_back ("Sample 2 Output");
  70. m_PluginInfo.PortTips.push_back ("Sample 3 Output");
  71. m_PluginInfo.PortTips.push_back ("Sample 4 Output");
  72. m_PluginInfo.PortTips.push_back ("Sample 5 Output");
  73. m_PluginInfo.PortTips.push_back ("Sample 6 Output");
  74. m_PluginInfo.PortTips.push_back ("Sample 7 Output");
  75. m_PluginInfo.PortTips.push_back ("Sample 8 Output");
  76. for (int n=0; n<NUM_SAMPLES; n++) {
  77. Sample* NewSample = new Sample;
  78. m_SampleVec.push_back (NewSample);
  79. SampleDesc* NewDesc = new SampleDesc;
  80. InitializeSampleDescription (NewDesc, n, n);
  81. m_SampleDescVec.push_back (NewDesc);
  82. }
  83. m_Version = 4;
  84. m_Current = 0;
  85. m_AudioCH->Register ("Num", &m_GUIArgs.Num);
  86. m_AudioCH->Register ("Value", &m_GUIArgs.Value);
  87. m_AudioCH->Register ("Bool", &m_GUIArgs.Boole);
  88. m_AudioCH->Register ("Int", &m_GUIArgs.Int);
  89. m_AudioCH->Register ("Start", &m_GUIArgs.Start);
  90. m_AudioCH->Register ("End", &m_GUIArgs.End);
  91. m_AudioCH->Register ("LoopStart", &m_GUIArgs.LoopStart);
  92. m_AudioCH->RegisterData ("Name", ChannelHandler::INPUT, &m_GUIArgs.Name, sizeof (m_GUIArgs.Name));
  93. m_AudioCH->Register ("PlayPos", &m_CurrentPlayPos, ChannelHandler::OUTPUT);
  94. m_AudioCH->RegisterData ("SampleBuffer", ChannelHandler::OUTPUT_REQUEST, &m_SampleBuffer, TRANSBUF_SIZE);
  95. m_AudioCH->Register ("SampleSize", &m_SampleSize, ChannelHandler::OUTPUT_REQUEST);
  96. m_AudioCH->Register ("BoolEcho", &m_GUIArgs.BoolEcho, ChannelHandler::OUTPUT);
  97. m_AudioCH->Register ("ValEcho", &m_GUIArgs.ValEcho, ChannelHandler::OUTPUT);
  98. m_AudioCH->Register ("IntEcho", &m_GUIArgs.IntEcho, ChannelHandler::OUTPUT);
  99. }
  100. PoshSamplerPlugin::~PoshSamplerPlugin() {
  101. for (vector<Sample*>::iterator i=m_SampleVec.begin(); i!=m_SampleVec.end(); i++)
  102. delete(*i);
  103. for (vector<SampleDesc*>::iterator i=m_SampleDescVec.begin(); i!=m_SampleDescVec.end(); i++)
  104. delete(*i);
  105. }
  106. PluginInfo &PoshSamplerPlugin::Initialise (const HostInfo *Host) {
  107. return SpiralPlugin::Initialise (Host);
  108. }
  109. SpiralGUIType *PoshSamplerPlugin::CreateGUI() {
  110. return new PoshSamplerPluginGUI (m_PluginInfo.Width, m_PluginInfo.Height, this, m_AudioCH, m_HostInfo);
  111. }
  112. void PoshSamplerPlugin::Reset() {
  113. ResetPorts();
  114. m_Current = 0;
  115. for (int s=0; s<NUM_SAMPLES; s++) {
  116. m_SampleDescVec[s]->Pitch = m_InitialPitch[s] * m_SampleDescVec[s]->SampleRate / (float)m_HostInfo->SAMPLERATE;
  117. m_SampleDescVec[s]->LoopEnd = m_SampleVec[s]->GetLength() - 1;
  118. }
  119. }
  120. void PoshSamplerPlugin::Execute() {
  121. static bool Pong = false;
  122. for (int s=0; s<NUM_SAMPLES+1; s++) GetOutputBuf (s)->Zero();
  123. float Freq = 0;
  124. for (int n=0; n<m_HostInfo->BUFSIZE; n++) {
  125. Freq = GetInputPitch (NOTETRIG, n);
  126. for (int s=0; s<NUM_SAMPLES; s++) {
  127. SampleDesc *S = m_SampleDescVec[s];
  128. // if we have a sample here
  129. if (m_SampleVec[s]->GetLength()) {
  130. // Convert the CV input into a useable trigger
  131. if (S->ReTrig || (S->SamplePos == -1)) {
  132. if (GetInput (s*2 + 1, n) > 0 || feq (Freq, NoteTable[S->Note], 0.01f)) {
  133. if (S->TriggerUp) {
  134. if (s==0 && InputExists (S1_INPUT))
  135. S->PlayStart = (long int)((GetInput (S1_INPUT, n) * 0.5 + 0.5f) * (S->LoopEnd-S->LoopStart)) + S->LoopStart;
  136. if (s==1 && InputExists (S2_INPUT))
  137. S->PlayStart = (long int)((GetInput (S2_INPUT, n) * 0.5 + 0.5f) * (S->LoopEnd-S->LoopStart)) + S->LoopStart;
  138. if (s==2 && InputExists (S3_INPUT))
  139. S->PlayStart = (long int)((GetInput (S3_INPUT, n) * 0.5 + 0.5f) * (S->LoopEnd-S->LoopStart)) + S->LoopStart;
  140. if (S->PlayStart < 0) S->PlayStart = 0;
  141. S->SamplePos = S->PlayStart;
  142. S->TriggerUp = false;
  143. S->Velocity = GetInput (s * 2 + 1, n);
  144. }
  145. }
  146. else {
  147. S->TriggerUp = true;
  148. // end it if it's looping
  149. if (S->Loop) S->SamplePos = -1;
  150. }
  151. }
  152. // if the sample has ended
  153. if (S->SamplePos >= S->LoopEnd || S->SamplePos >= m_SampleVec[s]->GetLength()) {
  154. if (S->Loop) {
  155. if (S->PingPong) Pong = true;
  156. else S->SamplePos = S->LoopStart;
  157. }
  158. else {
  159. S->SamplePos = -1;
  160. }
  161. }
  162. // if the sample has ended ponging
  163. if (Pong && S->SamplePos <= S->LoopStart)
  164. Pong = false;
  165. if (S->SamplePos != -1) {
  166. if (InputExists (s * 2)) {
  167. // Get the pitch from the CV
  168. float PlayFreq = GetInputPitch (s * 2, n);
  169. // assumtion: base frequency = 440 (middle A)
  170. S->Pitch = PlayFreq / 440;
  171. S->Pitch *= S->SampleRate / (float)m_HostInfo->SAMPLERATE;
  172. }
  173. // mix the sample to the output.
  174. MixOutput (0, n, (*m_SampleVec[s])[S->SamplePos] * S->Volume * S->Velocity);
  175. // copy the sample to it's individual output.
  176. SetOutput (s + 1, n, ((*m_SampleVec[s])[S->SamplePos] * S->Volume));
  177. float Freq = S->Pitch;
  178. if (S->Octave > 0) Freq *= 1 << (S->Octave);
  179. if (S->Octave < 0) Freq /= 1 << (-S->Octave);
  180. if (Pong) S->SamplePos -= Freq * S->PitchMod;
  181. else S->SamplePos += Freq * S->PitchMod;
  182. }
  183. }
  184. }
  185. }
  186. // record
  187. static int LastRecording = false;
  188. if (m_Recording && InputExists (REC_INPUT)) {
  189. int s = 0; //GUI->GetCurrentSample();
  190. if (!LastRecording) m_SampleVec[s]->Clear();
  191. // new sample
  192. if (m_SampleVec[s]->GetLength() == 0) {
  193. *m_SampleVec[s] =* GetInput (REC_INPUT);
  194. m_SampleDescVec[s]->SampleRate = m_HostInfo->SAMPLERATE;
  195. m_SampleDescVec[s]->Stereo = false;
  196. m_SampleDescVec[s]->Pitch *= 1.0f;
  197. m_InitialPitch[s] = m_SampleDescVec[s]->Pitch;
  198. m_SampleDescVec[s]->LoopEnd = m_SampleVec[s]->GetLength();
  199. }
  200. else {
  201. m_SampleVec[s]->Add (*GetInput (REC_INPUT));
  202. m_SampleDescVec[s]->LoopEnd = m_SampleVec[s]->GetLength();
  203. }
  204. }
  205. LastRecording = m_Recording;
  206. if (m_SampleDescVec[m_Current]->SamplePos > 0) {
  207. m_CurrentPlayPos = (long)m_SampleDescVec[m_Current]->SamplePos;
  208. }
  209. }
  210. void PoshSamplerPlugin::ExecuteCommands() {
  211. if (m_AudioCH->IsCommandWaiting()) {
  212. switch (m_AudioCH->GetCommand()) {
  213. case LOAD:
  214. LoadSample (m_GUIArgs.Num, m_GUIArgs.Name);
  215. break;
  216. case SAVE:
  217. SaveSample (m_GUIArgs.Num, m_GUIArgs.Name);
  218. break;
  219. case SETVOL:
  220. m_SampleDescVec[m_GUIArgs.Num]->Volume=m_GUIArgs.Value;
  221. break;
  222. case SETPITCH:
  223. m_SampleDescVec[m_GUIArgs.Num]->PitchMod=m_GUIArgs.Value;
  224. break;
  225. case SETLOOP:
  226. m_SampleDescVec[m_GUIArgs.Num]->Loop=m_GUIArgs.Boole;
  227. break;
  228. case SETPING:
  229. m_SampleDescVec[m_GUIArgs.Num]->PingPong=m_GUIArgs.Boole;
  230. break;
  231. case SETNOTE:
  232. m_SampleDescVec[m_GUIArgs.Num]->Note=m_GUIArgs.Int;
  233. break;
  234. case SETOCT:
  235. m_SampleDescVec[m_GUIArgs.Num]->Octave=m_GUIArgs.Int-6;
  236. break;
  237. case SETPLAYPOINTS:
  238. m_SampleDescVec[m_GUIArgs.Num]->PlayStart=m_GUIArgs.Start;
  239. m_SampleDescVec[m_GUIArgs.Num]->LoopStart=m_GUIArgs.LoopStart;
  240. m_SampleDescVec[m_GUIArgs.Num]->LoopEnd=m_GUIArgs.End;
  241. break;
  242. case SETREC:
  243. m_Recording=m_GUIArgs.Boole;
  244. break;
  245. case CUT:
  246. Cut (m_GUIArgs.Num, m_GUIArgs.Start, m_GUIArgs.End);
  247. break;
  248. case COPY:
  249. Copy (m_GUIArgs.Num, m_GUIArgs.Start, m_GUIArgs.End);
  250. break;
  251. case PASTE:
  252. Paste (m_GUIArgs.Num, m_GUIArgs.Start, m_GUIArgs.End);
  253. break;
  254. case MIX:
  255. Mix (m_GUIArgs.Num, m_GUIArgs.Start, m_GUIArgs.End);
  256. break;
  257. case CROP:
  258. Crop (m_GUIArgs.Num, m_GUIArgs.Start, m_GUIArgs.End);
  259. break;
  260. case REV:
  261. Reverse (m_GUIArgs.Num, m_GUIArgs.Start, m_GUIArgs.End);
  262. break;
  263. case AMP:
  264. Amp (m_GUIArgs.Num, m_GUIArgs.Start, m_GUIArgs.End);
  265. break;
  266. case SETCURRENT:
  267. m_Current = m_GUIArgs.Num;
  268. break;
  269. case GETSAMPLE:
  270. m_AudioCH->SetupBulkTransfer ((void*)m_SampleVec[m_Current]->GetBuffer());
  271. m_SampleSize = m_SampleVec[m_Current]->GetLengthInBytes();
  272. break;
  273. case SETRETRIG:
  274. m_SampleDescVec[m_GUIArgs.Num]->ReTrig = m_GUIArgs.Boole;
  275. break;
  276. case GETLOOP:
  277. m_GUIArgs.BoolEcho = m_SampleDescVec[m_Current]->Loop;
  278. break;
  279. case GETPING:
  280. m_GUIArgs.BoolEcho = m_SampleDescVec[m_Current]->PingPong;
  281. break;
  282. case GETRETRIG:
  283. m_GUIArgs.BoolEcho = m_SampleDescVec[m_Current]->ReTrig;
  284. break;
  285. case GETVOL:
  286. m_GUIArgs.ValEcho = m_SampleDescVec[m_Current]->Volume;
  287. break;
  288. case GETPITCH:
  289. m_GUIArgs.ValEcho = m_SampleDescVec[m_Current]->PitchMod;
  290. break;
  291. case GETOCT:
  292. m_GUIArgs.IntEcho = m_SampleDescVec[m_Current]->Octave + 6;
  293. break;
  294. case GETNOTE:
  295. m_GUIArgs.IntEcho = m_SampleDescVec[m_Current]->Note;
  296. break;
  297. };
  298. }
  299. }
  300. void PoshSamplerPlugin::InitializeSampleDescription (SampleDesc* NewDesc, int num, int Note) {
  301. if (NewDesc) {
  302. NewDesc->Volume = 1.0f;
  303. NewDesc->Velocity = 1.0f;
  304. NewDesc->Pitch = 1.0f;
  305. NewDesc->PitchMod = 1.0f;
  306. NewDesc->SamplePos = -1;
  307. NewDesc->Loop = false;
  308. NewDesc->PingPong = false;
  309. NewDesc->Note = Note;
  310. NewDesc->Octave = 0;
  311. NewDesc->TriggerUp = true;
  312. NewDesc->SamplePos = -1;
  313. NewDesc->SampleRate = 44100;
  314. NewDesc->Stereo = false;
  315. NewDesc->PlayStart = 0;
  316. NewDesc->LoopStart = 0;
  317. NewDesc->LoopEnd = INT_MAX;
  318. NewDesc->ReTrig = true;
  319. }
  320. }
  321. void PoshSamplerPlugin::StreamOut (ostream &s) {
  322. s << m_Version << " ";
  323. for (int n=0; n<NUM_SAMPLES; n++) {
  324. s << m_SampleDescVec[n]->Volume << " " <<
  325. m_SampleDescVec[n]->PitchMod << " " <<
  326. m_SampleDescVec[n]->Loop << " " <<
  327. m_SampleDescVec[n]->PingPong << " " <<
  328. m_SampleDescVec[n]->Note << " " <<
  329. m_SampleDescVec[n]->Octave << " " <<
  330. m_SampleDescVec[n]->SamplePos << " " <<
  331. m_SampleDescVec[n]->PlayStart << " " <<
  332. m_SampleDescVec[n]->LoopStart << " " <<
  333. m_SampleDescVec[n]->LoopEnd << " " <<
  334. m_SampleDescVec[n]->Note << " " <<
  335. m_SampleDescVec[n]->ReTrig << " ";
  336. }
  337. }
  338. void PoshSamplerPlugin::StreamIn (istream &s) {
  339. int version;
  340. s >> version;
  341. for (int n=0; n<NUM_SAMPLES; n++) {
  342. s >> m_SampleDescVec[n]->Volume >>
  343. m_SampleDescVec[n]->PitchMod >>
  344. m_SampleDescVec[n]->Loop >>
  345. m_SampleDescVec[n]->PingPong >>
  346. m_SampleDescVec[n]->Note >>
  347. m_SampleDescVec[n]->Octave >>
  348. m_SampleDescVec[n]->SamplePos >>
  349. m_SampleDescVec[n]->PlayStart >>
  350. m_SampleDescVec[n]->LoopStart >>
  351. m_SampleDescVec[n]->LoopEnd >>
  352. m_SampleDescVec[n]->Note;
  353. if (version < 3) {
  354. int size;
  355. s >> size;
  356. s.ignore (1);
  357. char Buf[4096];
  358. s.get (Buf, size+1);
  359. }
  360. if (version > 3) s >> m_SampleDescVec[n]->ReTrig;
  361. else m_SampleDescVec[n]->ReTrig = true;
  362. }
  363. }
  364. void PoshSamplerPlugin::LoadSample (int n, const string &Name) {
  365. WavFile Wav;
  366. if (Wav.Open (Name, WavFile::READ)) {
  367. m_SampleVec[n]->Allocate (Wav.GetSize());
  368. Wav.Load (*m_SampleVec[n]);
  369. // andy preston - if this is not commented out, when we load a patch this overwrites the
  370. // loaded data with the defaults
  371. // InitializeSampleDescription (m_SampleDescVec[n], n, n);
  372. m_SampleDescVec[n]->SampleRate = Wav.GetSamplerate();
  373. m_SampleDescVec[n]->Stereo = Wav.IsStereo();
  374. m_InitialPitch[n] = m_SampleDescVec[n]->Pitch;
  375. m_SampleDescVec[n]->Pitch = m_InitialPitch[n] * m_SampleDescVec[n]->SampleRate / (float)m_HostInfo->SAMPLERATE;
  376. m_SampleDescVec[n]->LoopEnd = m_SampleVec[n]->GetLength()-1;
  377. }
  378. }
  379. void PoshSamplerPlugin::SaveSample(int n, const string &Name)
  380. {
  381. if (m_SampleVec[n]->GetLength()==0) return;
  382. WavFile Wav;
  383. Wav.Open(Name,WavFile::WRITE,WavFile::MONO);
  384. Wav.Save(*m_SampleVec[n]);
  385. }
  386. void PoshSamplerPlugin::Cut(int n, long s, long e)
  387. {
  388. if (m_SampleVec[n]->GetLength()==0) return;
  389. m_SampleVec[n]->GetRegion(m_CopyBuffer, s, e);
  390. m_SampleVec[n]->Remove(s, e);
  391. }
  392. void PoshSamplerPlugin::Copy(int n, long s, long e)
  393. {
  394. if (m_SampleVec[n]->GetLength()==0) return;
  395. m_SampleVec[n]->GetRegion(m_CopyBuffer, s, e);
  396. }
  397. void PoshSamplerPlugin::Paste(int n, long s, long e)
  398. {
  399. if (m_SampleVec[n]->GetLength()==0) return;
  400. m_SampleVec[n]->Insert(m_CopyBuffer, s);
  401. }
  402. void PoshSamplerPlugin::Mix(int n, long s, long e)
  403. {
  404. if (m_SampleVec[n]->GetLength()==0) return;
  405. m_SampleVec[n]->Mix(m_CopyBuffer, s);
  406. }
  407. void PoshSamplerPlugin::Crop(int n, long s, long e)
  408. {
  409. if (m_SampleVec[n]->GetLength()==0) return;
  410. m_SampleVec[n]->Remove(0, s);
  411. m_SampleVec[n]->Remove(e, m_SampleVec[n]->GetLength()-1);
  412. }
  413. void PoshSamplerPlugin::Reverse(int n, long s, long e)
  414. {
  415. if (m_SampleVec[n]->GetLength()==0) return;
  416. m_SampleVec[n]->Reverse(s, e);
  417. }
  418. void PoshSamplerPlugin::Amp(int n, long s, long e)
  419. {
  420. if (m_SampleVec[n]->GetLength()==0) return;
  421. for (int m=0; m<m_SampleVec[n]->GetLength(); m++)
  422. {
  423. m_SampleVec[n]->Set(m,(*m_SampleVec[n])[m]*m_SampleDescVec[n]->Volume);
  424. }
  425. }
  426. // The sprintf's in here should use strstream, but the current implementation (GCC 2.95.3) is buggy
  427. bool PoshSamplerPlugin::SaveExternalFiles (const string &Dir) {
  428. char temp[256];
  429. for (int n=0; n<NUM_SAMPLES; n++) {
  430. // if it's not empty
  431. if (m_SampleVec[n]->GetLength() != 0) {
  432. sprintf (temp, "%sPoshSampler%d_%d.wav", Dir.c_str(), GetID(), n);
  433. SaveSample (n, temp);
  434. }
  435. }
  436. return true;
  437. }
  438. void PoshSamplerPlugin::LoadExternalFiles(const string &Dir, int withID) {
  439. int UseID = (withID==-1) ? GetID() : withID;
  440. char temp[256];
  441. for (int n=0; n<NUM_SAMPLES; n++) {
  442. sprintf (temp, "%sPoshSampler%d_%d.wav", Dir.c_str(), UseID, n);
  443. LoadSample (n, temp);
  444. }
  445. }