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.

376 lines
8.7KB

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