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.

408 lines
13KB

  1. /*
  2. Copyright (C) 2006-2011 Nasca Octavian Paul
  3. Author: Nasca Octavian Paul
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of version 2 of the GNU General Public License
  6. as published by the Free Software Foundation.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License (version 2) for more details.
  11. You should have received a copy of the GNU General Public License (version 2)
  12. along with this program; if not, write to the Free Software Foundation,
  13. Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14. */
  15. #pragma once
  16. #include <string>
  17. #include "../JuceLibraryCode/JuceHeader.h"
  18. #include "InputS.h"
  19. #include <mutex>
  20. inline double ramp(int64_t pos, int64_t totallen, int64_t rampinlen, int64_t rampoutlen)
  21. {
  22. if (totallen < rampinlen + rampoutlen)
  23. return 1.0;
  24. if (pos < rampinlen)
  25. return 1.0 / rampinlen*pos;
  26. if (pos >= totallen - rampoutlen)
  27. return 1.0 - 1.0 / rampoutlen*(pos - totallen + rampoutlen);
  28. return 1.0;
  29. }
  30. using LockGuard = std::lock_guard<std::recursive_mutex>;
  31. class AInputS final : public InputS
  32. {
  33. public:
  34. AInputS(AudioFormatManager* mana) : m_manager(mana)
  35. {
  36. m_readbuf.setSize(2, 65536*8);
  37. m_readbuf.clear();
  38. m_crossfadebuf.setSize(2, 44100);
  39. m_crossfadebuf.clear();
  40. PlayRangeEndCallback=[](AInputS*){};
  41. }
  42. ~AInputS() {}
  43. void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len)
  44. {
  45. LockGuard locker(m_mutex);
  46. m_afreader = nullptr;
  47. m_using_memory_buffer = true;
  48. m_readbuf = *buf;
  49. info.nchannels = buf->getNumChannels();
  50. info.nsamples = len;
  51. info.samplerate = samplerate;
  52. m_currentsample = 0;
  53. m_loop_enabled = true;
  54. m_crossfadebuf.setSize(info.nchannels, m_crossfadebuf.getNumSamples());
  55. m_cached_file_range = { 0,len };
  56. seek(m_activerange.getStart());
  57. updateXFadeCache();
  58. }
  59. virtual AudioBuffer<float>* getAudioBuffer() override
  60. {
  61. if (m_using_memory_buffer)
  62. return &m_readbuf;
  63. return nullptr;
  64. }
  65. bool openAudioFile(File file) override
  66. {
  67. m_silenceoutputted = 0;
  68. AudioFormatReader* reader = m_manager->createReaderFor(file);
  69. if (reader)
  70. {
  71. LockGuard locker(m_mutex);
  72. m_using_memory_buffer = false;
  73. m_afreader = std::unique_ptr<AudioFormatReader>(reader);
  74. if (m_activerange.isEmpty())
  75. m_activerange = { 0.0,1.0 };
  76. m_currentsample = m_activerange.getStart()*info.nsamples;
  77. info.samplerate = (int)m_afreader->sampleRate;
  78. info.nchannels = m_afreader->numChannels;
  79. info.nsamples = m_afreader->lengthInSamples;
  80. if (m_readbuf.getNumChannels() < info.nchannels)
  81. {
  82. m_readbuf.setSize(info.nchannels, m_readbuf.getNumSamples());
  83. m_crossfadebuf.setSize(info.nchannels, m_crossfadebuf.getNumSamples());
  84. }
  85. updateXFadeCache();
  86. m_readbuf.clear();
  87. return true;
  88. }
  89. return false;
  90. }
  91. void close() override
  92. {
  93. m_afreader = nullptr;
  94. m_currentsample = 0;
  95. info.nchannels = 0;
  96. info.nsamples = 0;
  97. info.samplerate = 0;
  98. }
  99. int readNextBlock(AudioBuffer<float>& abuf, int nsmps, int numchans) override
  100. {
  101. LockGuard locker(m_mutex);
  102. if (m_afreader == nullptr && m_using_memory_buffer == false)
  103. {
  104. jassert(false);
  105. return 0;
  106. }
  107. int inchans = 0;
  108. if (m_afreader)
  109. inchans = m_afreader->numChannels;
  110. else inchans = m_readbuf.getNumChannels();
  111. int64_t subsect_t0 = 0;
  112. int64_t subsect_t1 = 0;
  113. int64_t subsectlen = 0;
  114. int xfadelen = 0;
  115. auto updatesamplepositions = [&,this]()
  116. {
  117. subsect_t0 = (int64_t)(m_activerange.getStart()*info.nsamples);
  118. subsect_t1 = (int64_t)(m_activerange.getEnd()*info.nsamples);
  119. subsectlen = subsect_t1 - subsect_t0;
  120. xfadelen = m_xfadelen;
  121. if (xfadelen >= subsectlen)
  122. xfadelen = int(subsectlen - 2);
  123. };
  124. updatesamplepositions();
  125. auto getSampleLambda=[this](int64_t pos, int ch)
  126. {
  127. if (m_cached_file_range.contains(pos))
  128. return m_readbuf.getSample(ch, int(pos - m_cached_file_range.getStart()));
  129. else
  130. {
  131. Range<int64_t> activerange((int64_t)(m_activerange.getStart()*info.nsamples),
  132. (int64_t)(m_activerange.getEnd()*info.nsamples+1));
  133. Range<int64_t> possiblerange(pos, pos + m_readbuf.getNumSamples() + 0);
  134. m_cached_file_range = activerange.getIntersectionWith(possiblerange);
  135. m_afreader->read(&m_readbuf, 0, (int)m_cached_file_range.getLength(), pos, true, true);
  136. m_disk_read_count += m_cached_file_range.getLength()*m_afreader->numChannels;
  137. return m_readbuf.getSample(ch, int(pos - m_cached_file_range.getStart()));
  138. }
  139. };
  140. auto getCrossFadedSampleLambda=[this,&getSampleLambda](int64_t playpos, int chan, int64_t subt0, int64_t subt1, int xfadelen)
  141. {
  142. if (m_loop_enabled == false && playpos >= subt1)
  143. return 0.0f;
  144. if (playpos >= subt0 && playpos <= subt1 - xfadelen)
  145. return getSampleLambda(playpos, chan);
  146. if (playpos > (subt1 - xfadelen) && playpos<subt1)
  147. {
  148. int64_t fadeindex = playpos - subt1 + xfadelen;
  149. double fadeoutgain = 1.0 - (1.0 / (xfadelen - 0))*fadeindex;
  150. float s0 = (float)(getSampleLambda(playpos, chan)*fadeoutgain);
  151. double fadeingain = (1.0 / (xfadelen - 0))*fadeindex;
  152. int64_t playpos2 = playpos - subt1 + xfadelen;
  153. jassert(playpos2>=0 && playpos2<=xfadelen);
  154. float s1 = (float)(m_crossfadebuf.getSample(chan, (int)playpos2)*fadeingain);
  155. return s0 + s1;
  156. }
  157. ++m_silenceoutputted;
  158. return 0.0f;
  159. };
  160. float** smps = abuf.getArrayOfWritePointers();
  161. int readinc = 1;
  162. if (m_reverseplay)
  163. readinc = -1;
  164. for (int i = 0; i < nsmps; ++i)
  165. {
  166. float seekfadegain = 1.0f;
  167. if (m_seekfade.state == 1)
  168. {
  169. //Logger::writeToLog("Seek requested to pos " + String(m_seekfade.requestedpos));
  170. m_seekfade.state = 2;
  171. }
  172. if (m_seekfade.state == 2)
  173. {
  174. seekfadegain = 1.0 - (1.0 / m_seekfade.length*m_seekfade.counter);
  175. ++m_seekfade.counter;
  176. if (m_seekfade.counter >= m_seekfade.length)
  177. {
  178. //Logger::writeToLog("Doing seek " + String(m_seekfade.requestedpos));
  179. m_seekfade.counter = 0;
  180. m_seekfade.state = 3;
  181. if (m_seekfade.requestedrange.isEmpty() == false)
  182. {
  183. setActiveRangeImpl(m_seekfade.requestedrange);
  184. updatesamplepositions();
  185. if (m_activerange.contains(getCurrentPositionPercent()) == false)
  186. seekImpl(m_activerange.getStart());
  187. }
  188. }
  189. }
  190. if (m_seekfade.state == 3)
  191. {
  192. seekfadegain = 1.0 / m_seekfade.length*m_seekfade.counter;
  193. ++m_seekfade.counter;
  194. if (m_seekfade.counter >= m_seekfade.length)
  195. {
  196. //Logger::writeToLog("Seek cycle finished");
  197. m_seekfade.counter = 0;
  198. m_seekfade.state = 0;
  199. m_seekfade.requestedpos = 0.0;
  200. m_seekfade.requestedrange = Range<double>();
  201. }
  202. }
  203. jassert(seekfadegain >= 0.0f && seekfadegain<=1.0f);
  204. if (inchans == 1 && numchans > 0)
  205. {
  206. float sig = getCrossFadedSampleLambda(m_currentsample, 0, subsect_t0, subsect_t1, xfadelen);
  207. for (int j = 0; j < numchans; ++j)
  208. {
  209. smps[j][i] = sig*seekfadegain;
  210. }
  211. }
  212. else if (inchans > 1 && numchans > 1)
  213. {
  214. for (int j = 0; j < numchans; ++j)
  215. {
  216. int inchantouse = j % inchans;
  217. smps[j][i] = seekfadegain*getCrossFadedSampleLambda(m_currentsample, inchantouse,
  218. subsect_t0, subsect_t1,xfadelen);
  219. }
  220. }
  221. m_currentsample += readinc;
  222. if (m_loop_enabled == true)
  223. {
  224. if (m_reverseplay == false && m_currentsample >= subsect_t1)
  225. {
  226. m_currentsample = subsect_t0+xfadelen;
  227. ++m_loopcount;
  228. }
  229. else if (m_reverseplay == true && m_currentsample < subsect_t0)
  230. {
  231. m_currentsample = subsect_t1 - 1;
  232. }
  233. } else
  234. {
  235. if (m_reverseplay == false && m_currentsample == subsect_t1)
  236. PlayRangeEndCallback(this);
  237. else if (m_reverseplay == true && m_currentsample == subsect_t0)
  238. PlayRangeEndCallback(this);
  239. }
  240. }
  241. return nsmps;
  242. }
  243. void seekImpl(double pos)
  244. {
  245. if (m_using_memory_buffer == true)
  246. {
  247. jassert(m_readbuf.getNumSamples() > 0 && m_afreader == nullptr);
  248. m_loopcount = 0;
  249. m_silenceoutputted = 0;
  250. m_cache_misses = 0;
  251. m_currentsample = (int64_t)(pos*m_readbuf.getNumSamples());
  252. m_currentsample = jlimit<int64_t>(0, m_readbuf.getNumSamples(), m_currentsample);
  253. m_cached_file_range = { 0,m_readbuf.getNumSamples() };
  254. return;
  255. }
  256. //jassert(m_afreader!=nullptr);
  257. if (m_afreader == nullptr)
  258. return;
  259. m_loopcount = 0;
  260. m_silenceoutputted = 0;
  261. m_cache_misses = 0;
  262. m_currentsample = (int64_t)(pos*m_afreader->lengthInSamples);
  263. m_currentsample = jlimit<int64_t>(0, m_afreader->lengthInSamples, m_currentsample);
  264. //Logger::writeToLog("Seeking to " + String(m_currentsample));
  265. //if (m_cached_file_range.contains(info.currentsample)==false)
  266. m_cached_file_range = Range<int64_t>();
  267. updateXFadeCache();
  268. //m_cached_crossfade_range = Range<int64_t>();
  269. }
  270. void seek(double pos) override //0=start,1.0=end
  271. {
  272. //seekImpl(pos);
  273. LockGuard locker(m_mutex);
  274. if (m_seekfade.state == 0)
  275. {
  276. m_seekfade.state = 1;
  277. m_seekfade.counter = 0;
  278. }
  279. m_seekfade.length = 16384;
  280. m_seekfade.requestedpos = pos;
  281. }
  282. std::pair<Range<double>,Range<double>> getCachedRangesNormalized()
  283. {
  284. if (m_afreader == nullptr)
  285. return {};
  286. return { { jmap<double>((double)m_cached_file_range.getStart(),0,(double)info.nsamples,0.0,1.0),
  287. jmap<double>((double)m_cached_file_range.getEnd(), 0, (double)info.nsamples, 0.0, 1.0) },
  288. { jmap<double>((double)m_cached_crossfade_range.getStart(),0,(double)info.nsamples,0.0,1.0),
  289. jmap<double>((double)m_cached_crossfade_range.getEnd(), 0, (double)info.nsamples, 0.0, 1.0) } };
  290. }
  291. int getNumCacheMisses() { return m_cache_misses; }
  292. void updateXFadeCache()
  293. {
  294. if (m_xfadelen>m_crossfadebuf.getNumSamples())
  295. m_crossfadebuf.setSize(info.nchannels,m_xfadelen);
  296. if (m_afreader != nullptr && m_using_memory_buffer == false)
  297. m_afreader->read(&m_crossfadebuf, 0, m_xfadelen, (int64_t)(m_activerange.getStart()*info.nsamples), true, true);
  298. if (m_afreader == nullptr && m_using_memory_buffer == true)
  299. {
  300. for (int i=0;i<info.nchannels;++i)
  301. m_crossfadebuf.copyFrom(i, 0, m_readbuf, i, (int64_t)(m_activerange.getStart()*info.nsamples), m_xfadelen);
  302. }
  303. m_cached_crossfade_range =
  304. Range<int64_t>((int64_t)(m_activerange.getStart()*info.nsamples),(int64_t)(m_activerange.getStart()*info.nsamples+m_xfadelen));
  305. }
  306. void setActiveRangeImpl(Range<double> rng)
  307. {
  308. if (rng.getEnd() < rng.getStart())
  309. rng = { 0.0,1.0 };
  310. if (rng.isEmpty())
  311. rng = { 0.0,1.0 };
  312. m_activerange = rng;
  313. m_loopcount = 0;
  314. updateXFadeCache();
  315. }
  316. void setActiveRange(Range<double> rng) override
  317. {
  318. LockGuard locker(m_mutex);
  319. /*
  320. if (rng.contains(getCurrentPositionPercent()))
  321. {
  322. setActiveRangeImpl(rng);
  323. return;
  324. }
  325. */
  326. m_seekfade.requestedrange = rng;
  327. if (m_seekfade.state == 0)
  328. {
  329. m_seekfade.counter = 0;
  330. m_seekfade.state = 1;
  331. }
  332. m_seekfade.length = 2048;
  333. }
  334. void setLoopEnabled(bool b) override
  335. {
  336. m_loop_enabled = b;
  337. m_loopcount = 0;
  338. updateXFadeCache();
  339. }
  340. void setXFadeLenSeconds(double len)
  341. {
  342. if (info.samplerate==0)
  343. return;
  344. len = jlimit(0.0,1.0,len);
  345. int temp = (int)(len*info.samplerate);
  346. if (m_xfadelen!=temp)
  347. {
  348. m_xfadelen = temp;
  349. updateXFadeCache();
  350. }
  351. }
  352. Range<int64_t> getActiveRangeFrames()
  353. {
  354. if (info.nsamples == 0)
  355. return Range<int64_t>();
  356. return Range<int64_t>((int64_t)(m_activerange.getStart()*info.nsamples), (int64_t)(m_activerange.getEnd()*info.nsamples));
  357. }
  358. void setReversePlay(bool b)
  359. {
  360. m_reverseplay = b;
  361. }
  362. bool isReversed() { return m_reverseplay; }
  363. int64_t getLoopCount() { return m_loopcount; }
  364. private:
  365. std::function<void(AInputS*)> PlayRangeEndCallback;
  366. std::unique_ptr<AudioFormatReader> m_afreader;
  367. AudioBuffer<float> m_readbuf;
  368. AudioBuffer<float> m_crossfadebuf;
  369. Range<int64_t> m_cached_file_range;
  370. Range<int64_t> m_cached_crossfade_range;
  371. int m_cache_misses = 0;
  372. int m_fade_in = 512;
  373. int m_fade_out = 512;
  374. int m_xfadelen = 0;
  375. bool m_reverseplay = false;
  376. int64_t m_loopcount = 0;
  377. bool m_using_memory_buffer = true;
  378. AudioFormatManager* m_manager = nullptr;
  379. std::recursive_mutex m_mutex;
  380. struct
  381. {
  382. int state = 0; // 0 inactive, 1 seek requested, 2 fade out, 3 fade in
  383. int counter = 0;
  384. int length = 44100;
  385. double requestedpos = 0.0;
  386. Range<double> requestedrange;
  387. } m_seekfade;
  388. };