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.

471 lines
17KB

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