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 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2013-2019 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 GPL.txt file
  16. */
  17. #ifndef AUDIO_BASE_HPP_INCLUDED
  18. #define AUDIO_BASE_HPP_INCLUDED
  19. #include "CarlaThread.hpp"
  20. #include "CarlaMathUtils.hpp"
  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 numFrames;
  28. volatile uint64_t startFrame;
  29. #ifdef CARLA_PROPER_CPP11_SUPPORT
  30. AudioFilePool() noexcept
  31. : buffer{nullptr},
  32. numFrames(0),
  33. startFrame(0) {}
  34. #else
  35. AudioFilePool() noexcept
  36. : numFrames(0),
  37. startFrame(0)
  38. {
  39. buffer[0] = buffer[1] = nullptr;
  40. }
  41. #endif
  42. ~AudioFilePool()
  43. {
  44. destroy();
  45. }
  46. void create(const uint32_t desiredNumFrames)
  47. {
  48. CARLA_ASSERT(buffer[0] == nullptr);
  49. CARLA_ASSERT(buffer[1] == nullptr);
  50. CARLA_ASSERT(startFrame == 0);
  51. CARLA_ASSERT(numFrames == 0);
  52. numFrames = desiredNumFrames;
  53. buffer[0] = new float[numFrames];
  54. buffer[1] = new float[numFrames];
  55. reset();
  56. }
  57. void destroy() noexcept
  58. {
  59. if (buffer[0] != nullptr)
  60. {
  61. delete[] buffer[0];
  62. buffer[0] = nullptr;
  63. }
  64. if (buffer[1] != nullptr)
  65. {
  66. delete[] buffer[1];
  67. buffer[1] = nullptr;
  68. }
  69. startFrame = 0;
  70. numFrames = 0;
  71. }
  72. void reset() noexcept
  73. {
  74. startFrame = 0;
  75. if (numFrames != 0)
  76. {
  77. carla_zeroFloats(buffer[0], numFrames);
  78. carla_zeroFloats(buffer[1], numFrames);
  79. }
  80. }
  81. CARLA_DECLARE_NON_COPY_STRUCT(AudioFilePool)
  82. };
  83. class AbstractAudioPlayer
  84. {
  85. public:
  86. virtual ~AbstractAudioPlayer() {}
  87. virtual uint64_t getLastFrame() const = 0;
  88. };
  89. class AudioFileThread : public CarlaThread
  90. {
  91. public:
  92. AudioFileThread(AbstractAudioPlayer* const player)
  93. : CarlaThread("AudioFileThread"),
  94. kPlayer(player),
  95. fEntireFileLoaded(false),
  96. fLoopingMode(true),
  97. fNeedsRead(false),
  98. fQuitNow(true),
  99. fFilePtr(nullptr),
  100. fFileNfo(),
  101. fNumFileFrames(0),
  102. fPollTempData(nullptr),
  103. fPollTempSize(0),
  104. fPool(),
  105. fMutex()
  106. {
  107. CARLA_ASSERT(kPlayer != nullptr);
  108. static bool adInitiated = false;
  109. if (! adInitiated)
  110. {
  111. ad_init();
  112. adInitiated = true;
  113. }
  114. ad_clear_nfo(&fFileNfo);
  115. }
  116. ~AudioFileThread() override
  117. {
  118. CARLA_ASSERT(fQuitNow);
  119. CARLA_ASSERT(! isThreadRunning());
  120. cleanup();
  121. }
  122. void cleanup()
  123. {
  124. fEntireFileLoaded = false;
  125. if (fFilePtr != nullptr)
  126. {
  127. ad_close(fFilePtr);
  128. fFilePtr = nullptr;
  129. }
  130. if (fPollTempData != nullptr)
  131. {
  132. delete[] fPollTempData;
  133. fPollTempData = nullptr;
  134. fPollTempSize = 0;
  135. }
  136. fPool.destroy();
  137. }
  138. void startNow()
  139. {
  140. if (fPollTempData == nullptr)
  141. return;
  142. fNeedsRead = true;
  143. fQuitNow = false;
  144. startThread();
  145. }
  146. void stopNow()
  147. {
  148. fNeedsRead = false;
  149. fQuitNow = true;
  150. stopThread(1000);
  151. const CarlaMutexLocker cml(fMutex);
  152. fPool.reset();
  153. }
  154. bool isEntireFileLoaded() const noexcept
  155. {
  156. return fEntireFileLoaded;
  157. }
  158. uint32_t getMaxFrame() const noexcept
  159. {
  160. return fNumFileFrames;
  161. }
  162. uint64_t getPoolStartFrame() const noexcept
  163. {
  164. return fPool.startFrame;
  165. }
  166. uint32_t getPoolNumFrames() const noexcept
  167. {
  168. return fPool.numFrames;
  169. }
  170. void setLoopingMode(const bool on) noexcept
  171. {
  172. fLoopingMode = on;
  173. }
  174. void setNeedsRead() noexcept
  175. {
  176. fNeedsRead = true;
  177. }
  178. bool loadFilename(const char* const filename, const uint32_t sampleRate)
  179. {
  180. CARLA_SAFE_ASSERT_RETURN(! isThreadRunning(), false);
  181. CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);
  182. cleanup();
  183. ad_clear_nfo(&fFileNfo);
  184. // open new
  185. fFilePtr = ad_open(filename, &fFileNfo);
  186. if (fFilePtr == nullptr)
  187. return false;
  188. ad_dump_nfo(99, &fFileNfo);
  189. // Fix for misinformation using libsndfile
  190. if (fFileNfo.frames % fFileNfo.channels)
  191. --fFileNfo.frames;
  192. if (fFileNfo.frames <= 0)
  193. carla_stderr("L: filename \"%s\" has 0 frames", filename);
  194. if ((fFileNfo.channels == 1 || fFileNfo.channels == 2) && fFileNfo.frames > 0)
  195. {
  196. // valid
  197. const uint32_t fileNumFrames = static_cast<uint32_t>(fFileNfo.frames);
  198. const uint32_t poolNumFrames = sampleRate * 5;
  199. if (fileNumFrames <= poolNumFrames)
  200. {
  201. // entire file fits in a small pool, lets read it now
  202. fPool.create(fileNumFrames);
  203. readEntireFileIntoPool();
  204. ad_close(fFilePtr);
  205. fFilePtr = nullptr;
  206. }
  207. else
  208. {
  209. // file is too big for our audio pool, we need an extra buffer
  210. fPool.create(poolNumFrames);
  211. const size_t pollTempSize = poolNumFrames * fFileNfo.channels;
  212. try {
  213. fPollTempData = new float[pollTempSize];
  214. } catch (...) {
  215. ad_close(fFilePtr);
  216. fFilePtr = nullptr;
  217. return false;
  218. }
  219. fPollTempSize = pollTempSize;
  220. }
  221. fNumFileFrames = fileNumFrames;
  222. readPoll();
  223. return true;
  224. }
  225. else
  226. {
  227. // invalid
  228. ad_clear_nfo(&fFileNfo);
  229. ad_close(fFilePtr);
  230. fFilePtr = nullptr;
  231. return false;
  232. }
  233. }
  234. void putAllData(AudioFilePool& pool)
  235. {
  236. CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames,);
  237. const CarlaMutexLocker cml(fMutex);
  238. pool.startFrame = fPool.startFrame;
  239. carla_copyFloats(pool.buffer[0], fPool.buffer[0], fPool.numFrames);
  240. carla_copyFloats(pool.buffer[1], fPool.buffer[1], fPool.numFrames);
  241. }
  242. bool tryPutData(AudioFilePool& pool, const uint64_t framePos, const uint32_t frames)
  243. {
  244. CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames, false);
  245. if (framePos >= fPool.numFrames)
  246. return false;
  247. const CarlaMutexLocker cml(fMutex);
  248. /*
  249. const CarlaMutexTryLocker cmtl(fMutex);
  250. if (! cmtl.wasLocked())
  251. return false;
  252. */
  253. pool.startFrame = fPool.startFrame;
  254. carla_copyFloats(pool.buffer[0] + framePos, fPool.buffer[0] + framePos, frames);
  255. carla_copyFloats(pool.buffer[1] + framePos, fPool.buffer[1] + framePos, frames);
  256. return true;
  257. }
  258. void readEntireFileIntoPool()
  259. {
  260. CARLA_SAFE_ASSERT_RETURN(fPool.numFrames > 0,);
  261. const uint numChannels = fFileNfo.channels;
  262. const size_t bufferSize = fPool.numFrames * numChannels;
  263. float* const buffer = (float*)std::malloc(bufferSize*sizeof(float));
  264. CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
  265. carla_zeroFloats(buffer, bufferSize);
  266. ad_seek(fFilePtr, 0);
  267. ssize_t rv = ad_read(fFilePtr, buffer, bufferSize);
  268. CARLA_SAFE_ASSERT_INT2_RETURN(rv == static_cast<ssize_t>(bufferSize),
  269. static_cast<int>(rv),
  270. static_cast<int>(bufferSize),
  271. std::free(buffer));
  272. {
  273. // lock, and put data asap
  274. const CarlaMutexLocker cml(fMutex);
  275. for (ssize_t i=0, j=0; j < rv; ++j)
  276. {
  277. if (numChannels == 1)
  278. {
  279. fPool.buffer[0][i] = buffer[j];
  280. fPool.buffer[1][i] = buffer[j];
  281. ++i;
  282. }
  283. else
  284. {
  285. if (j % 2 == 0)
  286. {
  287. fPool.buffer[0][i] = buffer[j];
  288. }
  289. else
  290. {
  291. fPool.buffer[1][i] = buffer[j];
  292. ++i;
  293. }
  294. }
  295. }
  296. }
  297. std::free(buffer);
  298. fEntireFileLoaded = true;
  299. }
  300. void readPoll()
  301. {
  302. if (fNumFileFrames == 0 || fFileNfo.channels == 0 || fFilePtr == nullptr)
  303. {
  304. carla_debug("R: no song loaded");
  305. fNeedsRead = false;
  306. return;
  307. }
  308. if (fPollTempData == nullptr)
  309. {
  310. carla_debug("R: nothing to poll");
  311. fNeedsRead = false;
  312. return;
  313. }
  314. uint64_t lastFrame = kPlayer->getLastFrame();
  315. int64_t readFrameCheck;
  316. if (lastFrame >= fNumFileFrames)
  317. {
  318. if (fLoopingMode)
  319. {
  320. const uint64_t readFrameCheckLoop = lastFrame % fNumFileFrames;
  321. CARLA_SAFE_ASSERT_RETURN(readFrameCheckLoop < INT32_MAX,);
  322. carla_debug("R: transport out of bounds for loop");
  323. readFrameCheck = static_cast<int64_t>(readFrameCheckLoop);
  324. }
  325. else
  326. {
  327. carla_debug("R: transport out of bounds");
  328. fNeedsRead = false;
  329. return;
  330. }
  331. }
  332. else
  333. {
  334. CARLA_SAFE_ASSERT_RETURN(lastFrame < INT32_MAX,);
  335. readFrameCheck = static_cast<int64_t>(lastFrame);
  336. }
  337. const int64_t readFrame = readFrameCheck;
  338. // temp data buffer
  339. carla_zeroFloats(fPollTempData, fPollTempSize);
  340. {
  341. #if 0
  342. const int32_t sampleRate = 44100;
  343. carla_debug("R: poll data - reading at frame %li, time %li:%02li, lastFrame %li",
  344. readFrame, readFrame/sampleRate/60, (readFrame/sampleRate) % 60, lastFrame);
  345. #endif
  346. ad_seek(fFilePtr, readFrame);
  347. size_t i = 0;
  348. ssize_t j = 0;
  349. ssize_t rv = ad_read(fFilePtr, fPollTempData, fPollTempSize);
  350. if (rv < 0)
  351. {
  352. carla_stderr("R: ad_read failed");
  353. fNeedsRead = false;
  354. return;
  355. }
  356. const size_t urv = static_cast<size_t>(rv);
  357. // see if we can read more
  358. if (readFrame + rv >= static_cast<ssize_t>(fFileNfo.frames) && urv < fPollTempSize)
  359. {
  360. carla_debug("R: from start");
  361. ad_seek(fFilePtr, 0);
  362. rv += ad_read(fFilePtr, fPollTempData+urv, fPollTempSize-urv);
  363. }
  364. // lock, and put data asap
  365. const CarlaMutexLocker cml(fMutex);
  366. do {
  367. for (; i < fPool.numFrames && j < rv; ++j)
  368. {
  369. if (fFileNfo.channels == 1)
  370. {
  371. fPool.buffer[0][i] = fPollTempData[j];
  372. fPool.buffer[1][i] = fPollTempData[j];
  373. i++;
  374. }
  375. else
  376. {
  377. if (j % 2 == 0)
  378. {
  379. fPool.buffer[0][i] = fPollTempData[j];
  380. }
  381. else
  382. {
  383. fPool.buffer[1][i] = fPollTempData[j];
  384. i++;
  385. }
  386. }
  387. }
  388. if (i >= fPool.numFrames)
  389. break;
  390. if (rv == fFileNfo.frames)
  391. {
  392. // full file read
  393. j = 0;
  394. carla_debug("R: full file was read, filling buffers again");
  395. }
  396. else
  397. {
  398. carla_debug("read break, not enough space");
  399. carla_zeroFloats(fPool.buffer[0] + i, fPool.numFrames - i);
  400. carla_zeroFloats(fPool.buffer[1] + i, fPool.numFrames - i);
  401. break;
  402. }
  403. } while (i < fPool.numFrames);
  404. fPool.startFrame = lastFrame;
  405. }
  406. fNeedsRead = false;
  407. }
  408. protected:
  409. void run() override
  410. {
  411. const uint64_t numFramesNearEnd = fPool.numFrames*3/4;
  412. uint64_t lastFrame;
  413. while (! fQuitNow)
  414. {
  415. lastFrame = kPlayer->getLastFrame();
  416. if (fNeedsRead || lastFrame < fPool.startFrame || lastFrame - fPool.startFrame >= numFramesNearEnd)
  417. readPoll();
  418. carla_msleep(50);
  419. }
  420. }
  421. private:
  422. AbstractAudioPlayer* const kPlayer;
  423. bool fEntireFileLoaded;
  424. bool fLoopingMode;
  425. volatile bool fNeedsRead;
  426. volatile bool fQuitNow;
  427. void* fFilePtr;
  428. ADInfo fFileNfo;
  429. uint32_t fNumFileFrames;
  430. float* fPollTempData;
  431. size_t fPollTempSize;
  432. AudioFilePool fPool;
  433. CarlaMutex fMutex;
  434. CARLA_DECLARE_NON_COPY_STRUCT(AudioFileThread)
  435. };
  436. #endif // AUDIO_BASE_HPP_INCLUDED