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.

316 lines
10KB

  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. class AInputS final : public InputS
  31. {
  32. public:
  33. AInputS(AudioFormatManager* mana) : m_manager(mana)
  34. {
  35. m_readbuf.setSize(2, 65536*2);
  36. m_readbuf.clear();
  37. m_crossfadebuf.setSize(2, 44100);
  38. m_crossfadebuf.clear();
  39. PlayRangeEndCallback=[](AInputS*){};
  40. }
  41. ~AInputS() {}
  42. void setAudioBuffer(AudioBuffer<float>* buf, int samplerate, int len)
  43. {
  44. std::lock_guard<std::mutex> locker(m_mutex);
  45. m_afreader = nullptr;
  46. m_using_memory_buffer = true;
  47. m_readbuf = *buf;
  48. info.nchannels = buf->getNumChannels();
  49. info.nsamples = len;
  50. info.samplerate = samplerate;
  51. m_currentsample = 0;
  52. m_loop_enabled = true;
  53. m_crossfadebuf.setSize(info.nchannels, m_crossfadebuf.getNumSamples());
  54. m_cached_file_range = { 0,len };
  55. seek(m_activerange.getStart());
  56. updateXFadeCache();
  57. }
  58. virtual AudioBuffer<float>* getAudioBuffer() override
  59. {
  60. if (m_using_memory_buffer)
  61. return &m_readbuf;
  62. return nullptr;
  63. }
  64. bool openAudioFile(File file) override
  65. {
  66. m_silenceoutputted = 0;
  67. AudioFormatReader* reader = m_manager->createReaderFor(file);
  68. if (reader)
  69. {
  70. std::lock_guard<std::mutex> locker(m_mutex);
  71. m_using_memory_buffer = false;
  72. m_afreader = std::unique_ptr<AudioFormatReader>(reader);
  73. if (m_activerange.isEmpty())
  74. m_activerange = { 0.0,1.0 };
  75. m_currentsample = m_activerange.getStart()*info.nsamples;
  76. info.samplerate = (int)m_afreader->sampleRate;
  77. info.nchannels = m_afreader->numChannels;
  78. info.nsamples = m_afreader->lengthInSamples;
  79. if (m_readbuf.getNumChannels() < info.nchannels)
  80. {
  81. m_readbuf.setSize(info.nchannels, m_readbuf.getNumSamples());
  82. m_crossfadebuf.setSize(info.nchannels, m_crossfadebuf.getNumSamples());
  83. }
  84. updateXFadeCache();
  85. m_readbuf.clear();
  86. return true;
  87. }
  88. return false;
  89. }
  90. void close() override
  91. {
  92. m_afreader = nullptr;
  93. m_currentsample = 0;
  94. info.nchannels = 0;
  95. info.nsamples = 0;
  96. info.samplerate = 0;
  97. }
  98. int readNextBlock(AudioBuffer<float>& abuf, int nsmps, int numchans) override
  99. {
  100. std::lock_guard<std::mutex> locker(m_mutex);
  101. if (m_afreader == nullptr && m_using_memory_buffer == false)
  102. {
  103. jassert(false);
  104. return 0;
  105. }
  106. int inchans = 0;
  107. if (m_afreader)
  108. inchans = m_afreader->numChannels;
  109. else inchans = m_readbuf.getNumChannels();
  110. int64_t subsect_t0 = (int64_t)(m_activerange.getStart()*info.nsamples);
  111. int64_t subsect_t1 = (int64_t)(m_activerange.getEnd()*info.nsamples);
  112. int64_t subsectlen = subsect_t1 - subsect_t0;
  113. int xfadelen = m_xfadelen;
  114. if (xfadelen >= subsectlen)
  115. xfadelen = int(subsectlen - 2);
  116. auto getSampleLambda=[this](int64_t pos, int ch)
  117. {
  118. if (m_cached_file_range.contains(pos))
  119. return m_readbuf.getSample(ch, int(pos - m_cached_file_range.getStart()));
  120. else
  121. {
  122. Range<int64_t> activerange((int64_t)(m_activerange.getStart()*info.nsamples),
  123. (int64_t)(m_activerange.getEnd()*info.nsamples+1));
  124. Range<int64_t> possiblerange(pos, pos + m_readbuf.getNumSamples() + 0);
  125. m_cached_file_range = activerange.getIntersectionWith(possiblerange);
  126. m_afreader->read(&m_readbuf, 0, (int)m_cached_file_range.getLength(), pos, true, true);
  127. return m_readbuf.getSample(ch, int(pos - m_cached_file_range.getStart()));
  128. }
  129. };
  130. auto getCrossFadedSampleLambda=[this,&getSampleLambda](int64_t playpos, int chan, int64_t subt0, int64_t subt1, int xfadelen)
  131. {
  132. if (m_loop_enabled == false && playpos >= subt1)
  133. return 0.0f;
  134. if (playpos >= subt0 && playpos <= subt1 - xfadelen)
  135. return getSampleLambda(playpos, chan);
  136. if (playpos > (subt1 - xfadelen) && playpos<subt1)
  137. {
  138. int64_t fadeindex = playpos - subt1 + xfadelen;
  139. double fadeoutgain = 1.0 - (1.0 / (xfadelen - 0))*fadeindex;
  140. float s0 = (float)(getSampleLambda(playpos, chan)*fadeoutgain);
  141. double fadeingain = (1.0 / (xfadelen - 0))*fadeindex;
  142. int64_t playpos2 = playpos - subt1 + xfadelen;
  143. jassert(playpos2>=0 && playpos2<=xfadelen);
  144. float s1 = (float)(m_crossfadebuf.getSample(chan, (int)playpos2)*fadeingain);
  145. return s0 + s1;
  146. }
  147. ++m_silenceoutputted;
  148. return 0.0f;
  149. };
  150. float** smps = abuf.getArrayOfWritePointers();
  151. int readinc = 1;
  152. if (m_reverseplay)
  153. readinc = -1;
  154. for (int i = 0; i < nsmps; ++i)
  155. {
  156. if (inchans == 1 && numchans > 0)
  157. {
  158. float sig = getCrossFadedSampleLambda(m_currentsample, 0, subsect_t0, subsect_t1, xfadelen);
  159. for (int j = 0; j < numchans; ++j)
  160. {
  161. smps[j][i] = sig;
  162. }
  163. }
  164. else if (inchans > 1 && numchans > 1)
  165. {
  166. for (int j = 0; j < numchans; ++j)
  167. {
  168. int inchantouse = j % inchans;
  169. smps[j][i] = getCrossFadedSampleLambda(m_currentsample, inchantouse, subsect_t0, subsect_t1,xfadelen);
  170. }
  171. }
  172. m_currentsample += readinc;
  173. if (m_loop_enabled == true)
  174. {
  175. if (m_reverseplay == false && m_currentsample >= subsect_t1)
  176. {
  177. m_currentsample = subsect_t0+xfadelen;
  178. ++m_loopcount;
  179. }
  180. else if (m_reverseplay == true && m_currentsample < subsect_t0)
  181. {
  182. m_currentsample = subsect_t1 - 1;
  183. }
  184. } else
  185. {
  186. if (m_reverseplay == false && m_currentsample == subsect_t1)
  187. PlayRangeEndCallback(this);
  188. else if (m_reverseplay == true && m_currentsample == subsect_t0)
  189. PlayRangeEndCallback(this);
  190. }
  191. }
  192. return nsmps;
  193. }
  194. void seek(double pos) override //0=start,1.0=end
  195. {
  196. if (m_using_memory_buffer == true)
  197. {
  198. jassert(m_readbuf.getNumSamples() > 0 && m_afreader==nullptr);
  199. m_loopcount = 0;
  200. m_silenceoutputted = 0;
  201. m_cache_misses = 0;
  202. m_currentsample = (int64_t)(pos*m_readbuf.getNumSamples());
  203. m_currentsample = jlimit<int64_t>(0, m_readbuf.getNumSamples(), m_currentsample);
  204. m_cached_file_range = { 0,m_readbuf.getNumSamples() };
  205. return;
  206. }
  207. //jassert(m_afreader!=nullptr);
  208. if (m_afreader==nullptr)
  209. return;
  210. m_loopcount = 0;
  211. m_silenceoutputted = 0;
  212. m_cache_misses = 0;
  213. m_currentsample = (int64_t)(pos*m_afreader->lengthInSamples);
  214. m_currentsample = jlimit<int64_t>(0, m_afreader->lengthInSamples, m_currentsample);
  215. //Logger::writeToLog("Seeking to " + String(m_currentsample));
  216. //if (m_cached_file_range.contains(info.currentsample)==false)
  217. m_cached_file_range = Range<int64_t>();
  218. updateXFadeCache();
  219. //m_cached_crossfade_range = Range<int64_t>();
  220. }
  221. std::pair<Range<double>,Range<double>> getCachedRangesNormalized()
  222. {
  223. if (m_afreader == nullptr)
  224. return {};
  225. return { { jmap<double>((double)m_cached_file_range.getStart(),0,(double)info.nsamples,0.0,1.0),
  226. jmap<double>((double)m_cached_file_range.getEnd(), 0, (double)info.nsamples, 0.0, 1.0) },
  227. { jmap<double>((double)m_cached_crossfade_range.getStart(),0,(double)info.nsamples,0.0,1.0),
  228. jmap<double>((double)m_cached_crossfade_range.getEnd(), 0, (double)info.nsamples, 0.0, 1.0) } };
  229. }
  230. int getNumCacheMisses() { return m_cache_misses; }
  231. void updateXFadeCache()
  232. {
  233. if (m_xfadelen>m_crossfadebuf.getNumSamples())
  234. m_crossfadebuf.setSize(info.nchannels,m_xfadelen);
  235. if (m_afreader != nullptr && m_using_memory_buffer == false)
  236. m_afreader->read(&m_crossfadebuf, 0, m_xfadelen, (int64_t)(m_activerange.getStart()*info.nsamples), true, true);
  237. if (m_afreader == nullptr && m_using_memory_buffer == true)
  238. {
  239. for (int i=0;i<info.nchannels;++i)
  240. m_crossfadebuf.copyFrom(i, 0, m_readbuf, i, (int64_t)(m_activerange.getStart()*info.nsamples), m_xfadelen);
  241. }
  242. m_cached_crossfade_range =
  243. Range<int64_t>((int64_t)(m_activerange.getStart()*info.nsamples),(int64_t)(m_activerange.getStart()*info.nsamples+m_xfadelen));
  244. }
  245. void setActiveRange(Range<double> rng) override
  246. {
  247. if (rng.getEnd() < rng.getStart())
  248. rng = { 0.0,1.0 };
  249. if (rng.isEmpty())
  250. rng = { 0.0,1.0 };
  251. m_activerange = rng;
  252. m_loopcount = 0;
  253. updateXFadeCache();
  254. }
  255. void setLoopEnabled(bool b) override
  256. {
  257. m_loop_enabled = b;
  258. m_loopcount = 0;
  259. updateXFadeCache();
  260. }
  261. void setXFadeLenSeconds(double len)
  262. {
  263. if (info.samplerate==0)
  264. return;
  265. len = jlimit(0.0,1.0,len);
  266. int temp = (int)(len*info.samplerate);
  267. if (m_xfadelen!=temp)
  268. {
  269. m_xfadelen = temp;
  270. updateXFadeCache();
  271. }
  272. }
  273. Range<int64_t> getActiveRangeFrames()
  274. {
  275. if (info.nsamples == 0)
  276. return Range<int64_t>();
  277. return Range<int64_t>((int64_t)(m_activerange.getStart()*info.nsamples), (int64_t)(m_activerange.getEnd()*info.nsamples));
  278. }
  279. void setReversePlay(bool b)
  280. {
  281. m_reverseplay = b;
  282. }
  283. bool isReversed() { return m_reverseplay; }
  284. int64_t getLoopCount() { return m_loopcount; }
  285. private:
  286. std::function<void(AInputS*)> PlayRangeEndCallback;
  287. std::unique_ptr<AudioFormatReader> m_afreader;
  288. AudioBuffer<float> m_readbuf;
  289. AudioBuffer<float> m_crossfadebuf;
  290. Range<int64_t> m_cached_file_range;
  291. Range<int64_t> m_cached_crossfade_range;
  292. int m_cache_misses = 0;
  293. int m_fade_in = 512;
  294. int m_fade_out = 512;
  295. int m_xfadelen = 0;
  296. bool m_reverseplay = false;
  297. int64_t m_loopcount = 0;
  298. bool m_using_memory_buffer = true;
  299. AudioFormatManager* m_manager = nullptr;
  300. std::mutex m_mutex;
  301. };