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.

436 lines
12KB

  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. #include "CarlaNative.h"
  18. #include "audio_decoder/ad.h"
  19. #include <pthread.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <unistd.h>
  24. typedef struct adinfo ADInfo;
  25. typedef pthread_mutex_t Mutex;
  26. typedef pthread_t Thread;
  27. typedef struct _AudioFilePool {
  28. float* buffer[2];
  29. uint32_t startFrame;
  30. uint32_t size;
  31. } AudioFilePool;
  32. typedef struct _AudioFileInstance {
  33. HostDescriptor* host;
  34. void* filePtr;
  35. ADInfo fileNfo;
  36. uint32_t lastFrame;
  37. uint32_t maxFrame;
  38. AudioFilePool pool;
  39. bool needsRead;
  40. bool doProcess;
  41. bool doQuit;
  42. Mutex mutex;
  43. Thread thread;
  44. } AudioFileInstance;
  45. // ------------------------------------------------------------------------------------------
  46. static bool gADInitiated = false;
  47. // ------------------------------------------------------------------------------------------
  48. void zeroFloat(float* data, unsigned size)
  49. {
  50. for (unsigned i=0; i < size; ++i)
  51. *data++ = 0.0f;
  52. }
  53. void audiofile_read_poll(AudioFileInstance* const handlePtr)
  54. {
  55. if (handlePtr->fileNfo.frames == 0)
  56. {
  57. //fprintf(stderr, "R: no song loaded\n");
  58. handlePtr->needsRead = false;
  59. return;
  60. }
  61. int64_t lastFrame = handlePtr->lastFrame;
  62. if (lastFrame >= handlePtr->maxFrame)
  63. {
  64. //fprintf(stderr, "R: transport out of bounds\n");
  65. handlePtr->needsRead = false;
  66. return;
  67. }
  68. // temp data buffer
  69. const uint32_t tmpSize = handlePtr->pool.size * handlePtr->fileNfo.channels;
  70. float tmpData[tmpSize];
  71. zeroFloat(tmpData, tmpSize);
  72. {
  73. fprintf(stderr, "R: poll data - reading at %li:%02li\n", lastFrame/44100/60, (lastFrame/44100) % 60);
  74. ad_seek(handlePtr->filePtr, lastFrame);
  75. ssize_t i, j, rv = ad_read(handlePtr->filePtr, tmpData, tmpSize);
  76. {
  77. // lock, and put data asap
  78. pthread_mutex_lock(&handlePtr->mutex);
  79. //zeroFloat(handlePtr->pool.buffer[0], handlePtr->pool.size);
  80. //zeroFloat(handlePtr->pool.buffer[1], handlePtr->pool.size);
  81. for (i=0, j=0; i < handlePtr->pool.size && j < rv; j++)
  82. {
  83. if (handlePtr->fileNfo.channels == 1)
  84. {
  85. handlePtr->pool.buffer[0][i] = tmpData[j];
  86. handlePtr->pool.buffer[1][i] = tmpData[j];
  87. i++;
  88. }
  89. else
  90. {
  91. if (j % 2 == 0)
  92. {
  93. handlePtr->pool.buffer[0][i] = tmpData[j];
  94. }
  95. else
  96. {
  97. handlePtr->pool.buffer[1][i] = tmpData[j];
  98. i++;
  99. }
  100. }
  101. }
  102. for (; i < handlePtr->pool.size; i++)
  103. {
  104. handlePtr->pool.buffer[0][i] = 0.0f;
  105. handlePtr->pool.buffer[1][i] = 0.0f;
  106. }
  107. handlePtr->pool.startFrame = lastFrame;
  108. // done
  109. pthread_mutex_unlock(&handlePtr->mutex);
  110. }
  111. }
  112. handlePtr->needsRead = false;
  113. }
  114. void audiofile_load_filename(AudioFileInstance* const handlePtr, const char* const filename)
  115. {
  116. // wait for jack processing to end
  117. handlePtr->doProcess = false;
  118. pthread_mutex_lock(&handlePtr->mutex);
  119. pthread_mutex_unlock(&handlePtr->mutex);
  120. // clear old data
  121. if (handlePtr->filePtr != NULL)
  122. {
  123. ad_close(handlePtr->filePtr);
  124. handlePtr->filePtr = NULL;
  125. }
  126. ad_clear_nfo(&handlePtr->fileNfo);
  127. // open new
  128. handlePtr->filePtr = ad_open(filename, &handlePtr->fileNfo);
  129. if (handlePtr->filePtr != NULL)
  130. {
  131. ad_dump_nfo(1, &handlePtr->fileNfo);
  132. if (handlePtr->fileNfo.channels == 1 || handlePtr->fileNfo.channels == 2)
  133. {
  134. handlePtr->maxFrame = handlePtr->fileNfo.frames;
  135. audiofile_read_poll(handlePtr);
  136. handlePtr->doProcess = true;
  137. }
  138. else
  139. {
  140. ad_close(handlePtr->filePtr);
  141. handlePtr->filePtr = NULL;
  142. ad_clear_nfo(&handlePtr->fileNfo);
  143. }
  144. }
  145. }
  146. static void audiofile_thread_idle(void* ptr)
  147. {
  148. AudioFileInstance* const handlePtr = (AudioFileInstance*)ptr;
  149. while (! handlePtr->doQuit)
  150. {
  151. if (handlePtr->needsRead || handlePtr->lastFrame - handlePtr->pool.startFrame >= handlePtr->pool.size*3/4)
  152. audiofile_read_poll(handlePtr);
  153. else
  154. usleep(50*1000);
  155. }
  156. pthread_exit(0);
  157. }
  158. // ------------------------------------------------------------------------------------------
  159. static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDescriptor* host)
  160. {
  161. AudioFileInstance* const handlePtr = (AudioFileInstance*)malloc(sizeof(AudioFileInstance));
  162. if (handlePtr == NULL)
  163. return NULL;
  164. if (! gADInitiated)
  165. {
  166. ad_init();
  167. gADInitiated = true;
  168. }
  169. // init
  170. handlePtr->host = host;
  171. handlePtr->filePtr = NULL;
  172. handlePtr->lastFrame = 0;
  173. handlePtr->maxFrame = 0;
  174. handlePtr->pool.buffer[0] = NULL;
  175. handlePtr->pool.buffer[1] = NULL;
  176. handlePtr->pool.startFrame = 0;
  177. handlePtr->pool.size = 0;
  178. handlePtr->needsRead = false;
  179. handlePtr->doProcess = false;
  180. handlePtr->doQuit = false;
  181. ad_clear_nfo(&handlePtr->fileNfo);
  182. pthread_mutex_init(&handlePtr->mutex, NULL);
  183. // create audio pool
  184. handlePtr->pool.size = host->get_sample_rate(host->handle) * 6; // 6 secs
  185. handlePtr->pool.buffer[0] = (float*)malloc(sizeof(float) * handlePtr->pool.size);
  186. handlePtr->pool.buffer[1] = (float*)malloc(sizeof(float) * handlePtr->pool.size);
  187. if (handlePtr->pool.buffer[0] == NULL || handlePtr->pool.buffer[1] == NULL)
  188. {
  189. free(handlePtr);
  190. return NULL;
  191. }
  192. zeroFloat(handlePtr->pool.buffer[0], handlePtr->pool.size);
  193. zeroFloat(handlePtr->pool.buffer[1], handlePtr->pool.size);
  194. pthread_create(&handlePtr->thread, NULL, (void*)&audiofile_thread_idle, handlePtr);
  195. // load file, TESTING
  196. // wait for jack processing to end
  197. handlePtr->doProcess = false;
  198. pthread_mutex_lock(&handlePtr->mutex);
  199. pthread_mutex_unlock(&handlePtr->mutex);
  200. return handlePtr;
  201. // unused
  202. (void)_this_;
  203. }
  204. static void audiofile_cleanup(PluginHandle handle)
  205. {
  206. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  207. // wait for processing to end
  208. handlePtr->doProcess = false;
  209. handlePtr->doQuit = true;
  210. pthread_mutex_lock(&handlePtr->mutex);
  211. pthread_join(handlePtr->thread, NULL);
  212. pthread_mutex_unlock(&handlePtr->mutex);
  213. pthread_mutex_destroy(&handlePtr->mutex);
  214. if (handlePtr->filePtr != NULL)
  215. ad_close(handlePtr->filePtr);
  216. if (handlePtr->pool.buffer[0] != NULL)
  217. free(handlePtr->pool.buffer[0]);
  218. if (handlePtr->pool.buffer[1] != NULL)
  219. free(handlePtr->pool.buffer[1]);
  220. free(handlePtr);
  221. }
  222. static void audiofile_set_custom_data(PluginHandle handle, const char* key, const char* value)
  223. {
  224. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  225. if (strcmp(key, "file") == 0)
  226. audiofile_load_filename(handlePtr, value);
  227. }
  228. static void audiofile_ui_show(PluginHandle handle, bool show)
  229. {
  230. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  231. const char* const filename = handlePtr->host->ui_open_file(handlePtr->host->handle, false, "Open Audio File", "");
  232. if (filename != NULL)
  233. handlePtr->host->ui_custom_data_changed(handlePtr->host->handle, "file", filename);
  234. handlePtr->host->ui_closed(handlePtr->host->handle);
  235. }
  236. static void audiofile_process(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents)
  237. {
  238. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  239. float* out1 = outBuffer[0];
  240. float* out2 = outBuffer[1];
  241. if (! handlePtr->doProcess)
  242. {
  243. //fprintf(stderr, "P: no process\n");
  244. zeroFloat(out1, frames);
  245. zeroFloat(out2, frames);
  246. return;
  247. }
  248. const TimeInfo* const timePos = handlePtr->host->get_time_info(handlePtr->host->handle);
  249. // not playing
  250. if (! timePos->playing)
  251. {
  252. //fprintf(stderr, "P: not rolling\n");
  253. handlePtr->lastFrame = timePos->frame;
  254. zeroFloat(out1, frames);
  255. zeroFloat(out2, frames);
  256. return;
  257. }
  258. pthread_mutex_lock(&handlePtr->mutex);
  259. // out of reach
  260. if (timePos->frame + frames < handlePtr->pool.startFrame || timePos->frame >= handlePtr->maxFrame)
  261. {
  262. //fprintf(stderr, "P: non-continuous playback, out of reach %u vs %u\n", timePos->frame + frames, handlePtr->maxFrame);
  263. handlePtr->lastFrame = timePos->frame;
  264. handlePtr->needsRead = true;
  265. pthread_mutex_unlock(&handlePtr->mutex);
  266. zeroFloat(out1, frames);
  267. zeroFloat(out2, frames);
  268. return;
  269. }
  270. int64_t poolFrame = (int64_t)timePos->frame - handlePtr->pool.startFrame;
  271. int64_t poolSize = handlePtr->pool.size;
  272. for (uint32_t i=0; i < frames; i++, poolFrame++)
  273. {
  274. if (poolFrame >= 0 && poolFrame < poolSize)
  275. {
  276. out1[i] = handlePtr->pool.buffer[0][poolFrame];
  277. out2[i] = handlePtr->pool.buffer[1][poolFrame];
  278. // reset
  279. handlePtr->pool.buffer[0][poolFrame] = 0.0f;
  280. handlePtr->pool.buffer[1][poolFrame] = 0.0f;
  281. }
  282. else
  283. {
  284. out1[i] = 0.0f;
  285. out2[i] = 0.0f;
  286. }
  287. }
  288. handlePtr->lastFrame = timePos->frame;
  289. pthread_mutex_unlock(&handlePtr->mutex);
  290. return;
  291. // unused
  292. (void)inBuffer;
  293. (void)midiEventCount;
  294. (void)midiEvents;
  295. }
  296. // -----------------------------------------------------------------------
  297. static const PluginDescriptor audiofileDesc = {
  298. .category = PLUGIN_CATEGORY_UTILITY,
  299. .hints = PLUGIN_IS_RTSAFE|PLUGIN_HAS_GUI,
  300. .audioIns = 0,
  301. .audioOuts = 2,
  302. .midiIns = 0,
  303. .midiOuts = 0,
  304. .parameterIns = 0,
  305. .parameterOuts = 0,
  306. .name = "Audio File",
  307. .label = "audiofile",
  308. .maker = "falkTX",
  309. .copyright = "GNU GPL v2+",
  310. .instantiate = audiofile_instantiate,
  311. .cleanup = audiofile_cleanup,
  312. .get_parameter_count = NULL,
  313. .get_parameter_info = NULL,
  314. .get_parameter_value = NULL,
  315. .get_parameter_text = NULL,
  316. .get_midi_program_count = NULL,
  317. .get_midi_program_info = NULL,
  318. .set_parameter_value = NULL,
  319. .set_midi_program = NULL,
  320. .set_custom_data = audiofile_set_custom_data,
  321. .ui_show = audiofile_ui_show,
  322. .ui_idle = NULL,
  323. .ui_set_parameter_value = NULL,
  324. .ui_set_midi_program = NULL,
  325. .ui_set_custom_data = NULL,
  326. .activate = NULL,
  327. .deactivate = NULL,
  328. .process = audiofile_process
  329. };
  330. // -----------------------------------------------------------------------
  331. void carla_register_native_plugin_audiofile()
  332. {
  333. carla_register_native_plugin(&audiofileDesc);
  334. }
  335. // -----------------------------------------------------------------------
  336. // amagamated build
  337. #include "audio_decoder/ad_ffmpeg.c"
  338. #include "audio_decoder/ad_plugin.c"
  339. #include "audio_decoder/ad_soundfile.c"
  340. // -----------------------------------------------------------------------