Audio plugin host https://kx.studio/carla
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.

audio-base.hpp 9.1KB

11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef AUDIO_BASE_HPP_INCLUDED
  18. #define AUDIO_BASE_HPP_INCLUDED
  19. #include "CarlaMutex.hpp"
  20. #include "JuceHeader.h"
  21. extern "C" {
  22. #include "audio_decoder/ad.h"
  23. }
  24. typedef struct adinfo ADInfo;
  25. struct AudioFilePool {
  26. float* buffer[2];
  27. uint32_t startFrame;
  28. uint32_t size;
  29. #ifdef CARLA_PROPER_CPP11_SUPPORT
  30. AudioFilePool()
  31. : buffer{nullptr},
  32. startFrame(0),
  33. size(0) {}
  34. #else
  35. AudioFilePool()
  36. : startFrame(0),
  37. size(0)
  38. {
  39. buffer[0] = buffer[1] = nullptr;
  40. }
  41. #endif
  42. ~AudioFilePool()
  43. {
  44. CARLA_ASSERT(buffer[0] == nullptr);
  45. CARLA_ASSERT(buffer[1] == nullptr);
  46. CARLA_ASSERT(startFrame == 0);
  47. CARLA_ASSERT(size == 0);
  48. }
  49. void create(const uint32_t sampleRate)
  50. {
  51. CARLA_ASSERT(buffer[0] == nullptr);
  52. CARLA_ASSERT(buffer[1] == nullptr);
  53. CARLA_ASSERT(startFrame == 0);
  54. CARLA_ASSERT(size == 0);
  55. size = sampleRate * 2;
  56. buffer[0] = new float[size];
  57. buffer[1] = new float[size];
  58. reset();
  59. }
  60. void destroy()
  61. {
  62. CARLA_ASSERT(buffer[0] != nullptr);
  63. CARLA_ASSERT(buffer[1] != nullptr);
  64. CARLA_ASSERT(size != 0);
  65. if (buffer[0] != nullptr)
  66. {
  67. delete[] buffer[0];
  68. buffer[0] = nullptr;
  69. }
  70. if (buffer[1] != nullptr)
  71. {
  72. delete[] buffer[1];
  73. buffer[1] = nullptr;
  74. }
  75. startFrame = 0;
  76. size = 0;
  77. }
  78. void reset()
  79. {
  80. CARLA_ASSERT(size != 0);
  81. startFrame = 0;
  82. carla_zeroFloat(buffer[0], size);
  83. carla_zeroFloat(buffer[1], size);
  84. }
  85. };
  86. class AbstractAudioPlayer
  87. {
  88. public:
  89. virtual ~AbstractAudioPlayer() {}
  90. virtual uint32_t getLastFrame() const = 0;
  91. };
  92. class AudioFileThread : public juce::Thread
  93. {
  94. public:
  95. AudioFileThread(AbstractAudioPlayer* const player, const double sampleRate)
  96. : juce::Thread("AudioFileThread"),
  97. kPlayer(player),
  98. fNeedsRead(false),
  99. fFilePtr(nullptr)
  100. {
  101. CARLA_ASSERT(kPlayer != nullptr);
  102. static bool adInitiated = false;
  103. if (! adInitiated)
  104. {
  105. ad_init();
  106. adInitiated = true;
  107. }
  108. ad_clear_nfo(&fFileNfo);
  109. fPool.create(sampleRate);
  110. }
  111. ~AudioFileThread() override
  112. {
  113. CARLA_ASSERT(! isThreadRunning());
  114. if (fFilePtr != nullptr)
  115. ad_close(fFilePtr);
  116. fPool.destroy();
  117. }
  118. void startNow()
  119. {
  120. fNeedsRead = true;
  121. startThread(2);
  122. }
  123. void stopNow()
  124. {
  125. fNeedsRead = false;
  126. stopThread(1000);
  127. const CarlaMutex::ScopedLocker sl(fMutex);
  128. fPool.reset();
  129. }
  130. uint32_t getMaxFrame() const
  131. {
  132. return fFileNfo.frames > 0 ? fFileNfo.frames : 0;
  133. }
  134. void setNeedsRead()
  135. {
  136. fNeedsRead = true;
  137. }
  138. bool loadFilename(const char* const filename)
  139. {
  140. CARLA_ASSERT(! isThreadRunning());
  141. CARLA_ASSERT(filename != nullptr);
  142. fPool.startFrame = 0;
  143. // clear old data
  144. if (fFilePtr != nullptr)
  145. {
  146. ad_close(fFilePtr);
  147. fFilePtr = nullptr;
  148. }
  149. ad_clear_nfo(&fFileNfo);
  150. // open new
  151. fFilePtr = ad_open(filename, &fFileNfo);
  152. if (fFilePtr == nullptr)
  153. return false;
  154. ad_dump_nfo(99, &fFileNfo);
  155. if (fFileNfo.frames == 0)
  156. carla_stderr("L: filename \"%s\" has 0 frames", filename);
  157. if ((fFileNfo.channels == 1 || fFileNfo.channels == 2) && fFileNfo.frames > 0)
  158. {
  159. // valid
  160. readPoll();
  161. return true;
  162. }
  163. else
  164. {
  165. // invalid
  166. ad_clear_nfo(&fFileNfo);
  167. ad_close(fFilePtr);
  168. fFilePtr = nullptr;
  169. return false;
  170. }
  171. }
  172. void tryPutData(AudioFilePool& pool)
  173. {
  174. CARLA_ASSERT(pool.size == fPool.size);
  175. if (pool.size != fPool.size)
  176. return;
  177. if (! fMutex.tryLock())
  178. return;
  179. //if (pool.startFrame != fPool.startFrame || pool.buffer[0] != fPool.buffer[0] || pool.buffer[1] != fPool.buffer[1])
  180. {
  181. pool.startFrame = fPool.startFrame;
  182. carla_copyFloat(pool.buffer[0], fPool.buffer[0], fPool.size);
  183. carla_copyFloat(pool.buffer[1], fPool.buffer[1], fPool.size);
  184. }
  185. fMutex.unlock();
  186. }
  187. void readPoll()
  188. {
  189. if (fFileNfo.frames <= 0 || fFilePtr == nullptr)
  190. {
  191. carla_stderr("R: no song loaded");
  192. fNeedsRead = false;
  193. return;
  194. }
  195. int64_t lastFrame = kPlayer->getLastFrame();
  196. int64_t readFrame = lastFrame;
  197. int64_t maxFrame = fFileNfo.frames;
  198. if (lastFrame >= maxFrame)
  199. {
  200. #if 0
  201. if (false)
  202. //if (handlePtr->loopMode)
  203. {
  204. carla_stderr("R: DEBUG read loop, lastFrame:%i, maxFrame:%i", lastFrame, maxFrame);
  205. if (maxFrame >= static_cast<int64_t>(fPool.size))
  206. {
  207. readFrame %= maxFrame;
  208. }
  209. else
  210. {
  211. readFrame = 0;
  212. lastFrame -= lastFrame % maxFrame;
  213. }
  214. }
  215. else
  216. #endif
  217. {
  218. carla_stderr("R: transport out of bounds");
  219. fNeedsRead = false;
  220. return;
  221. }
  222. }
  223. // temp data buffer
  224. const size_t tmpSize = fPool.size * fFileNfo.channels;
  225. float tmpData[tmpSize];
  226. carla_zeroFloat(tmpData, tmpSize);
  227. {
  228. carla_stderr("R: poll data - reading at %li:%02li", readFrame/44100/60, (readFrame/44100) % 60);
  229. ad_seek(fFilePtr, readFrame);
  230. ssize_t i, j, rv = ad_read(fFilePtr, tmpData, tmpSize);
  231. i = j = 0;
  232. // lock, and put data asap
  233. const CarlaMutex::ScopedLocker sl(fMutex);
  234. for (; i < fPool.size && j < rv; ++j)
  235. {
  236. if (fFileNfo.channels == 1)
  237. {
  238. fPool.buffer[0][i] = tmpData[j];
  239. fPool.buffer[1][i] = tmpData[j];
  240. i++;
  241. }
  242. else
  243. {
  244. if (j % 2 == 0)
  245. {
  246. fPool.buffer[0][i] = tmpData[j];
  247. }
  248. else
  249. {
  250. fPool.buffer[1][i] = tmpData[j];
  251. i++;
  252. }
  253. }
  254. }
  255. #if 0
  256. if (false)
  257. //if (handlePtr->loopMode && i < fPool.size)
  258. {
  259. while (i < fPool.size)
  260. {
  261. for (j=0; i < fPool.size && j < rv; ++j)
  262. {
  263. if (fFileNfo.channels == 1)
  264. {
  265. fPool.buffer[0][i] = tmpData[j];
  266. fPool.buffer[1][i] = tmpData[j];
  267. i++;
  268. }
  269. else
  270. {
  271. if (j % 2 == 0)
  272. {
  273. fPool.buffer[0][i] = tmpData[j];
  274. }
  275. else
  276. {
  277. fPool.buffer[1][i] = tmpData[j];
  278. i++;
  279. }
  280. }
  281. }
  282. }
  283. }
  284. else
  285. #endif
  286. {
  287. for (; i < fPool.size; ++i)
  288. {
  289. fPool.buffer[0][i] = 0.0f;
  290. fPool.buffer[1][i] = 0.0f;
  291. }
  292. }
  293. fPool.startFrame = lastFrame;
  294. }
  295. fNeedsRead = false;
  296. }
  297. protected:
  298. void run() override
  299. {
  300. while (! threadShouldExit())
  301. {
  302. const uint32_t lastFrame(kPlayer->getLastFrame());
  303. if (fNeedsRead || lastFrame < fPool.startFrame || (lastFrame - fPool.startFrame >= fPool.size*3/4 && lastFrame < fFileNfo.frames))
  304. readPoll();
  305. else
  306. carla_msleep(50);
  307. }
  308. }
  309. private:
  310. AbstractAudioPlayer* const kPlayer;
  311. bool fNeedsRead;
  312. void* fFilePtr;
  313. ADInfo fFileNfo;
  314. AudioFilePool fPool;
  315. CarlaMutex fMutex;
  316. };
  317. #endif // AUDIO_BASE_HPP_INCLUDED