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.

465 lines
8.8KB

  1. /* SpiralLoops
  2. * Copyleft (C) 2000 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 <FL/fl_file_chooser.h>
  19. #include "Loop.h"
  20. #include "../../RiffWav.h"
  21. //#include "SpiralLoopsInfo.h"
  22. static const int RECBUFFERSIZE = 16384;
  23. static const float RECORD_GAIN = 1.0f;
  24. Loop::Loop() :
  25. m_Id(0),
  26. m_Pos(0),
  27. m_IntPos(0),
  28. m_PlayBufPos(0),
  29. m_Playing(true),
  30. m_Recording(false),
  31. m_Master(false),
  32. m_DelMe(false),
  33. m_LoopPoint(0),
  34. m_Speed(1.0f),
  35. m_Volume(1.0f),
  36. m_RecordingSource(NULL),
  37. m_Balance(1.0f),
  38. m_LeftVol(1.0f),
  39. m_RightVol(1.0f),
  40. m_FirstRecord(true),
  41. m_FixedRecord(false),
  42. m_RecLength(0),
  43. m_EffectsOn(false)
  44. {
  45. }
  46. Loop::~Loop()
  47. {
  48. }
  49. void Loop::LoadWav(const char *Filename)
  50. {
  51. WavFile wav;
  52. if (wav.Open(Filename, WavFile::READ))
  53. {
  54. Clear();
  55. AllocateMem(wav.GetSize());
  56. wav.Load(m_StoreBuffer);
  57. //((Fl_Loop*)(m_GUI->GetGUI()))->DrawEveryThing();
  58. m_GUI->UpdateDataPtr();
  59. }
  60. }
  61. void Loop::SaveWav(const char *Filename)
  62. {
  63. WavFile wav;
  64. if (wav.Open(Filename, WavFile::WRITE, WavFile::MONO))
  65. {
  66. wav.Save(m_StoreBuffer);
  67. }
  68. m_Sample=Filename;
  69. }
  70. bool Loop::GetOutput(Sample &data)
  71. {
  72. if (!m_Recording && !m_Playing)
  73. {
  74. return false;
  75. }
  76. if (!m_Recording && m_StoreBuffer.GetLength()==0)
  77. {
  78. return false;
  79. }
  80. if (m_Recording)
  81. {
  82. RecordBuf(m_Pos, data.GetLength());
  83. if (!m_StoreBuffer.GetLength())
  84. {
  85. return false;
  86. }
  87. }
  88. int Pos;
  89. for (int n=0; n<data.GetLength(); n++)
  90. {
  91. Pos=static_cast<int>(m_Pos);
  92. // brute force fix
  93. if (Pos>0 && Pos<m_LoopPoint)
  94. {
  95. data.Set(n,m_StoreBuffer[m_Pos]*m_Volume);
  96. }
  97. else data.Set(n,0);
  98. m_Pos+=m_Speed;
  99. if (static_cast<int>(m_Pos)>=m_LoopPoint)
  100. {
  101. m_Pos=0;
  102. }
  103. }
  104. m_Filter.GetOutput(0,data);
  105. // causes problems if we save to a hold buffer
  106. // while we're recording, as we might not know
  107. // the size of the final buffer
  108. if (!m_Recording)
  109. {
  110. for (int n=0; n<data.GetLength(); n++)
  111. {
  112. if (m_PlayBufPos>=m_LoopPoint)
  113. {
  114. m_PlayBufPos=0;
  115. }
  116. m_HoldBuffer.Set(m_PlayBufPos,data[n]);
  117. m_PlayBufPos++;
  118. }
  119. }
  120. m_IntPos=static_cast<int>(m_Pos);
  121. m_GUI->UpdatePos();
  122. return true;
  123. }
  124. void Loop::AllocateMem(int Length)
  125. {
  126. // We might need to keep these values (if loading workspace)
  127. if (m_LoopPoint>Length) m_LoopPoint=Length;
  128. if (m_Pos>Length) m_Pos=0;
  129. if (m_LoopPoint==0) m_LoopPoint=Length;
  130. if (!m_StoreBuffer.Allocate(Length) ||
  131. !m_HoldBuffer.Allocate(Length))
  132. {
  133. cerr<<"AllocateMem can't allocate any more memory!"<<endl;
  134. Clear();
  135. }
  136. }
  137. void Loop::Clear()
  138. {
  139. m_StoreBuffer.Clear();
  140. m_HoldBuffer.Clear();
  141. //m_LoopPoint=0;
  142. }
  143. void Loop::RecordBuf(float Pos, int Length)
  144. {
  145. if (!m_RecordingSource) return;
  146. static float OldPos=Pos;
  147. if (m_FirstRecord)
  148. {
  149. // Find out if we want a fixed length record
  150. // based on the last sample length, or not
  151. if (m_StoreBuffer.GetLength())
  152. {
  153. m_FixedRecord=true;
  154. }
  155. else
  156. {
  157. m_FixedRecord=false;
  158. m_RecBuffer.Allocate(RECBUFFERSIZE);
  159. m_StoreBuffer.Clear();
  160. m_RecPos=0;
  161. }
  162. m_FirstRecord=false;
  163. m_RecLength=0;
  164. OldPos=Pos;
  165. }
  166. if (m_FixedRecord)
  167. {
  168. m_RecLength=m_LoopPoint;
  169. if (Pos>=m_StoreBuffer.GetLength())
  170. {
  171. Pos=0;
  172. }
  173. for (int n=0; n<Length; n++)
  174. {
  175. // just add directly to the old buffer
  176. float temp=m_StoreBuffer[static_cast<int>(Pos)]+m_RecordingSource[n]*RECORD_GAIN;
  177. // fill in all the samples between the speed jump with the same value
  178. m_StoreBuffer.Set((int)Pos,temp);
  179. for (int i=static_cast<int>(OldPos); i<=static_cast<int>(Pos); i++)
  180. {
  181. m_StoreBuffer.Set(i,temp);
  182. }
  183. OldPos=Pos;
  184. Pos+=m_Speed;
  185. if (Pos>=m_StoreBuffer.GetLength())
  186. {
  187. Pos-=m_StoreBuffer.GetLength();
  188. // remember to fill up to the end of the last buffer
  189. for (int i=static_cast<int>(OldPos); i<m_StoreBuffer.GetLength(); i++)
  190. {
  191. m_StoreBuffer.Set(i,temp);
  192. }
  193. // and the beggining of this one
  194. for (int i=0; i<Pos; i++)
  195. {
  196. m_StoreBuffer.Set(i,temp);
  197. }
  198. OldPos=0;
  199. }
  200. }
  201. }
  202. else
  203. {
  204. for (int n=0; n<Length; n++)
  205. {
  206. // see if we need a new buffer
  207. if (m_RecPos>=RECBUFFERSIZE)
  208. {
  209. // put the two buffers together
  210. m_StoreBuffer.Add(m_RecBuffer);
  211. m_RecPos=0;
  212. }
  213. long temp=(long)(m_RecordingSource[n]*RECORD_GAIN);
  214. m_RecBuffer.Set(m_RecPos,temp);
  215. m_RecLength++;
  216. m_RecPos++;
  217. }
  218. }
  219. }
  220. void Loop::EndRecordBuf()
  221. {
  222. m_FirstRecord=true;
  223. m_LoopPoint=m_StoreBuffer.GetLength();
  224. if (!m_FixedRecord)
  225. {
  226. // reallocate the hold buffer for the new size
  227. // (if the size has changed)
  228. m_HoldBuffer.Allocate(m_LoopPoint);
  229. }
  230. }
  231. void Loop::Crop()
  232. {
  233. if (m_LoopPoint<m_StoreBuffer.GetLength())
  234. {
  235. m_StoreBuffer.CropTo(m_LoopPoint);
  236. m_HoldBuffer.CropTo(m_LoopPoint);
  237. }
  238. }
  239. void Loop::Double()
  240. {
  241. Crop();
  242. m_StoreBuffer.Add(m_StoreBuffer);
  243. m_HoldBuffer.Add(m_HoldBuffer);
  244. m_LoopPoint=m_StoreBuffer.GetLength();
  245. }
  246. void Loop::MatchLength(int Len)
  247. {
  248. // set the length, and make sure enough data is allocated
  249. if (m_StoreBuffer.GetLength()>Len)
  250. {
  251. SetLength(Len);
  252. return;
  253. }
  254. else
  255. {
  256. // if it's empty
  257. if (!m_StoreBuffer.GetLength())
  258. {
  259. AllocateMem(Len);
  260. m_StoreBuffer.Zero();
  261. }
  262. else
  263. // there is something in the buffer already, but we need to
  264. // add on some extra data to make the length the same
  265. {
  266. int ExtraLen=Len-m_StoreBuffer.GetLength();
  267. m_StoreBuffer.Expand(ExtraLen);
  268. m_HoldBuffer.Expand(ExtraLen);
  269. }
  270. }
  271. }
  272. void Loop::Cut(int Start, int End)
  273. {
  274. //m_Parent->Cut(m_StoreBuffer,Start,End);
  275. if (m_StoreBuffer.GetLength()<m_LoopPoint)
  276. {
  277. m_LoopPoint=m_StoreBuffer.GetLength();
  278. }
  279. if (m_Pos>m_LoopPoint)
  280. {
  281. m_Pos=0;
  282. }
  283. m_HoldBuffer.Allocate(m_StoreBuffer.GetLength());
  284. }
  285. void Loop::Copy(int Start, int End)
  286. {
  287. //m_Parent->Copy(m_StoreBuffer,Start,End);
  288. }
  289. void Loop::Paste(int Start)
  290. {
  291. //m_Parent->Paste(m_StoreBuffer,Start);
  292. if (m_StoreBuffer.GetLength()<m_LoopPoint)
  293. {
  294. m_LoopPoint=m_StoreBuffer.GetLength();
  295. }
  296. if (m_Pos>m_LoopPoint)
  297. {
  298. m_Pos=0;
  299. }
  300. m_HoldBuffer.Allocate(m_StoreBuffer.GetLength());
  301. }
  302. void Loop::PasteMix(int Start)
  303. {
  304. //m_Parent->PasteMix(m_StoreBuffer,Start);
  305. }
  306. void Loop::ZeroRange(int Start, int End)
  307. {
  308. for (int n=Start; n<End; n++)
  309. {
  310. m_StoreBuffer.Set(n,0);
  311. }
  312. }
  313. void Loop::ReverseRange(int Start, int End)
  314. {
  315. m_StoreBuffer.Reverse(Start,End);
  316. }
  317. void Loop::Halve()
  318. {
  319. m_StoreBuffer.Shrink(m_StoreBuffer.GetLength()/2);
  320. m_HoldBuffer.Shrink(m_HoldBuffer.GetLength()/2);
  321. if (m_StoreBuffer.GetLength()<m_LoopPoint)
  322. {
  323. m_LoopPoint=m_StoreBuffer.GetLength();
  324. }
  325. if (m_Pos>m_LoopPoint)
  326. {
  327. m_Pos=0;
  328. }
  329. }
  330. void Loop::SelectAll()
  331. {
  332. }
  333. void Loop::Move(int Start)
  334. {
  335. m_StoreBuffer.Move(Start);
  336. }
  337. void Loop::StreamIn(istream &s)
  338. {
  339. s>>m_Id>>m_Pos>>m_IntPos>>m_PlayBufPos>>m_Playing>>m_Master>>m_LoopPoint>>
  340. m_Speed>>m_Volume>>m_Balance>>m_LeftVol>>m_RightVol>>m_Filter>>
  341. m_EffectsOn;
  342. }
  343. void Loop::StreamOut(ostream &s)
  344. {
  345. s<<m_Id<<" "<<m_Pos<<" "<<m_IntPos<<" "<<m_PlayBufPos<<" "<<m_Playing
  346. <<" "<<m_Master<<" "<<m_LoopPoint<<" "<<m_Speed<<" "<<m_Volume<<" "
  347. <<m_Balance<<" "<<m_LeftVol<<" "<<m_RightVol<<" "<<m_Filter<<" "
  348. <<m_EffectsOn<<" ";
  349. }
  350. istream &operator>>(istream &s, Loop &o)
  351. {
  352. s>>o.m_Id>>o.m_Pos>>o.m_IntPos>>o.m_PlayBufPos>>o.m_Playing>>o.m_Master>>o.m_LoopPoint>>
  353. o.m_Speed>>o.m_Volume>>o.m_Balance>>o.m_LeftVol>>o.m_RightVol>>o.m_Filter>>
  354. o.m_EffectsOn;
  355. char Buf[4096];
  356. int size;
  357. s>>size;
  358. s.ignore(1);
  359. s.get(Buf,size+1);
  360. o.m_Sample=Buf;
  361. if (o.m_Sample!="")
  362. {
  363. o.LoadWav(o.m_Sample.c_str());
  364. }
  365. return s;
  366. }
  367. ostream &operator<<(ostream &s, Loop &o)
  368. {
  369. // if this sample is not saved, get the user to pick a filename.
  370. if (o.m_Sample=="")
  371. {
  372. char *fn=fl_file_chooser("Save loop as Wav file", "*.wav", NULL);
  373. if (fn && fn!="")
  374. {
  375. o.m_Sample=fn;
  376. o.SaveWav(o.m_Sample.c_str());
  377. }
  378. }
  379. else
  380. {
  381. if (fl_ask("Save loop sample %s?",o.m_Sample.c_str()))
  382. {
  383. o.SaveWav(o.m_Sample.c_str());
  384. }
  385. }
  386. s<<o.m_Id<<" "<<o.m_Pos<<" "<<o.m_IntPos<<" "<<o.m_PlayBufPos<<" "<<o.m_Playing
  387. <<" "<<o.m_Master<<" "<<o.m_LoopPoint<<" "<<o.m_Speed<<" "<<o.m_Volume<<" "
  388. <<o.m_Balance<<" "<<o.m_LeftVol<<" "<<o.m_RightVol<<" "<<o.m_Filter<<" "
  389. <<o.m_EffectsOn<<" "<<o.m_Sample.size()<<" "<<o.m_Sample<<" ";
  390. return s;
  391. }