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.

385 lines
9.1KB

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