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.

599 lines
16KB

  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. #define PROGRAM_COUNT 16
  25. #ifdef _WIN32
  26. # define OS_SEP '\\'
  27. #else
  28. # define OS_SEP '/'
  29. #endif
  30. typedef struct adinfo ADInfo;
  31. typedef pthread_mutex_t Mutex;
  32. typedef pthread_t Thread;
  33. typedef struct _AudioFilePool {
  34. float* buffer[2];
  35. uint32_t startFrame;
  36. uint32_t size;
  37. } AudioFilePool;
  38. typedef struct _AudioFilePrograms {
  39. uint32_t current;
  40. const char* fullNames[PROGRAM_COUNT];
  41. const char* shortNames[PROGRAM_COUNT];
  42. } AudioFilePrograms;
  43. typedef struct _AudioFileInstance {
  44. HostDescriptor* host;
  45. void* filePtr;
  46. ADInfo fileNfo;
  47. uint32_t lastFrame;
  48. uint32_t maxFrame;
  49. AudioFilePool pool;
  50. AudioFilePrograms programs;
  51. bool loopMode;
  52. bool needsRead;
  53. bool doProcess;
  54. bool doQuit;
  55. Mutex mutex;
  56. Thread thread;
  57. } AudioFileInstance;
  58. // ------------------------------------------------------------------------------------------
  59. void zeroFloat(float* data, unsigned size)
  60. {
  61. for (unsigned i=0; i < size; ++i)
  62. *data++ = 0.0f;
  63. }
  64. void audiofile_read_poll(AudioFileInstance* const handlePtr)
  65. {
  66. if (handlePtr->fileNfo.frames == 0)
  67. {
  68. //fprintf(stderr, "R: no song loaded\n");
  69. handlePtr->needsRead = false;
  70. return;
  71. }
  72. const int64_t lastFrame = handlePtr->lastFrame;
  73. if (lastFrame >= handlePtr->maxFrame)
  74. {
  75. fprintf(stderr, "R: transport out of bounds\n");
  76. handlePtr->needsRead = false;
  77. return;
  78. }
  79. // temp data buffer
  80. const uint32_t tmpSize = handlePtr->pool.size * handlePtr->fileNfo.channels;
  81. float tmpData[tmpSize];
  82. zeroFloat(tmpData, tmpSize);
  83. {
  84. fprintf(stderr, "R: poll data - reading at %li:%02li\n", lastFrame/44100/60, (lastFrame/44100) % 60);
  85. ad_seek(handlePtr->filePtr, lastFrame);
  86. ssize_t i, j, rv = ad_read(handlePtr->filePtr, tmpData, tmpSize);
  87. i = j = 0;
  88. // lock, and put data asap
  89. pthread_mutex_lock(&handlePtr->mutex);
  90. for (; i < handlePtr->pool.size && j < rv; j++)
  91. {
  92. if (handlePtr->fileNfo.channels == 1)
  93. {
  94. handlePtr->pool.buffer[0][i] = tmpData[j];
  95. handlePtr->pool.buffer[1][i] = tmpData[j];
  96. i++;
  97. }
  98. else
  99. {
  100. if (j % 2 == 0)
  101. {
  102. handlePtr->pool.buffer[0][i] = tmpData[j];
  103. }
  104. else
  105. {
  106. handlePtr->pool.buffer[1][i] = tmpData[j];
  107. i++;
  108. }
  109. }
  110. }
  111. for (; i < handlePtr->pool.size; i++)
  112. {
  113. handlePtr->pool.buffer[0][i] = 0.0f;
  114. handlePtr->pool.buffer[1][i] = 0.0f;
  115. }
  116. handlePtr->pool.startFrame = lastFrame;
  117. // done
  118. pthread_mutex_unlock(&handlePtr->mutex);
  119. }
  120. handlePtr->needsRead = false;
  121. }
  122. void audiofile_load_filename(AudioFileInstance* const handlePtr, const char* const filename)
  123. {
  124. // wait for jack processing to end
  125. handlePtr->doProcess = false;
  126. pthread_mutex_lock(&handlePtr->mutex);
  127. pthread_mutex_unlock(&handlePtr->mutex);
  128. // clear old data
  129. if (handlePtr->filePtr != NULL)
  130. {
  131. ad_close(handlePtr->filePtr);
  132. handlePtr->filePtr = NULL;
  133. }
  134. ad_clear_nfo(&handlePtr->fileNfo);
  135. if (filename == NULL)
  136. return;
  137. // open new
  138. handlePtr->filePtr = ad_open(filename, &handlePtr->fileNfo);
  139. if (handlePtr->filePtr != NULL)
  140. {
  141. ad_dump_nfo(99, &handlePtr->fileNfo);
  142. if (handlePtr->fileNfo.channels == 1 || handlePtr->fileNfo.channels == 2)
  143. {
  144. handlePtr->maxFrame = handlePtr->fileNfo.frames;
  145. audiofile_read_poll(handlePtr);
  146. handlePtr->doProcess = true;
  147. }
  148. else
  149. {
  150. ad_close(handlePtr->filePtr);
  151. handlePtr->filePtr = NULL;
  152. ad_clear_nfo(&handlePtr->fileNfo);
  153. }
  154. }
  155. }
  156. static void audiofile_thread_idle(void* ptr)
  157. {
  158. AudioFileInstance* const handlePtr = (AudioFileInstance*)ptr;
  159. while (! handlePtr->doQuit)
  160. {
  161. if (handlePtr->needsRead || handlePtr->lastFrame - handlePtr->pool.startFrame >= handlePtr->pool.size*3/4)
  162. audiofile_read_poll(handlePtr);
  163. else
  164. usleep(50*1000);
  165. }
  166. pthread_exit(NULL);
  167. }
  168. // ------------------------------------------------------------------------------------------
  169. static bool gADInitiated = false;
  170. // ------------------------------------------------------------------------------------------
  171. static PluginHandle audiofile_instantiate(const PluginDescriptor* _this_, HostDescriptor* host)
  172. {
  173. AudioFileInstance* const handlePtr = (AudioFileInstance*)malloc(sizeof(AudioFileInstance));
  174. if (handlePtr == NULL)
  175. return NULL;
  176. if (! gADInitiated)
  177. {
  178. ad_init();
  179. gADInitiated = true;
  180. }
  181. // init
  182. handlePtr->host = host;
  183. handlePtr->filePtr = NULL;
  184. handlePtr->lastFrame = 0;
  185. handlePtr->maxFrame = 0;
  186. handlePtr->pool.buffer[0] = NULL;
  187. handlePtr->pool.buffer[1] = NULL;
  188. handlePtr->pool.startFrame = 0;
  189. handlePtr->pool.size = 0;
  190. handlePtr->programs.current = 0;
  191. handlePtr->loopMode = true;
  192. handlePtr->needsRead = false;
  193. handlePtr->doProcess = false;
  194. handlePtr->doQuit = false;
  195. ad_clear_nfo(&handlePtr->fileNfo);
  196. pthread_mutex_init(&handlePtr->mutex, NULL);
  197. for (uint32_t i=0; i < PROGRAM_COUNT; i++)
  198. {
  199. handlePtr->programs.fullNames[i] = NULL;
  200. handlePtr->programs.shortNames[i] = NULL;
  201. }
  202. // create audio pool
  203. handlePtr->pool.size = host->get_sample_rate(host->handle) * 6; // 6 secs
  204. handlePtr->pool.buffer[0] = (float*)malloc(sizeof(float) * handlePtr->pool.size);
  205. if (handlePtr->pool.buffer[0] == NULL)
  206. {
  207. free(handlePtr);
  208. return NULL;
  209. }
  210. handlePtr->pool.buffer[1] = (float*)malloc(sizeof(float) * handlePtr->pool.size);
  211. if (handlePtr->pool.buffer[1] == NULL)
  212. {
  213. free(handlePtr->pool.buffer[0]);
  214. free(handlePtr);
  215. return NULL;
  216. }
  217. zeroFloat(handlePtr->pool.buffer[0], handlePtr->pool.size);
  218. zeroFloat(handlePtr->pool.buffer[1], handlePtr->pool.size);
  219. pthread_create(&handlePtr->thread, NULL, (void*)&audiofile_thread_idle, handlePtr);
  220. return handlePtr;
  221. // unused
  222. (void)_this_;
  223. }
  224. static void audiofile_cleanup(PluginHandle handle)
  225. {
  226. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  227. // wait for processing to end
  228. handlePtr->doProcess = false;
  229. handlePtr->doQuit = true;
  230. pthread_mutex_lock(&handlePtr->mutex);
  231. pthread_join(handlePtr->thread, NULL);
  232. pthread_mutex_unlock(&handlePtr->mutex);
  233. pthread_mutex_destroy(&handlePtr->mutex);
  234. if (handlePtr->filePtr != NULL)
  235. ad_close(handlePtr->filePtr);
  236. if (handlePtr->pool.buffer[0] != NULL)
  237. free(handlePtr->pool.buffer[0]);
  238. if (handlePtr->pool.buffer[1] != NULL)
  239. free(handlePtr->pool.buffer[1]);
  240. for (uint32_t i=0; i < PROGRAM_COUNT; i++)
  241. {
  242. if (handlePtr->programs.fullNames[i] != NULL)
  243. free((void*)handlePtr->programs.fullNames[i]);
  244. if (handlePtr->programs.shortNames[i] != NULL)
  245. free((void*)handlePtr->programs.shortNames[i]);
  246. }
  247. free(handlePtr);
  248. }
  249. static uint32_t audiofile_get_parameter_count(PluginHandle handle)
  250. {
  251. return 1;
  252. // unused
  253. (void)handle;
  254. }
  255. static const Parameter* audiofile_get_parameter_info(PluginHandle handle, uint32_t index)
  256. {
  257. if (index != 0)
  258. return NULL;
  259. static Parameter param;
  260. param.name = "Loop Mode";
  261. param.unit = NULL;
  262. param.hints = PARAMETER_IS_ENABLED|PARAMETER_IS_BOOLEAN;
  263. param.ranges.def = 1.0f;
  264. param.ranges.min = 0.0f;
  265. param.ranges.max = 1.0f;
  266. param.ranges.step = 1.0f;
  267. param.ranges.stepSmall = 1.0f;
  268. param.ranges.stepLarge = 1.0f;
  269. param.scalePointCount = 0;
  270. param.scalePoints = NULL;
  271. return &param;
  272. // unused
  273. (void)handle;
  274. }
  275. static float audiofile_get_parameter_value(PluginHandle handle, uint32_t index)
  276. {
  277. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  278. if (index != 0)
  279. return 0.0f;
  280. return handlePtr->loopMode ? 1.0f : 0.0f;
  281. // unused
  282. (void)handle;
  283. }
  284. static uint32_t audiofile_get_program_count(PluginHandle handle)
  285. {
  286. return PROGRAM_COUNT;
  287. }
  288. const MidiProgram* audiofile_get_program_info(PluginHandle handle, uint32_t index)
  289. {
  290. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  291. if (index >= PROGRAM_COUNT)
  292. return NULL;
  293. static MidiProgram midiProgram;
  294. midiProgram.bank = 0;
  295. midiProgram.program = index;
  296. midiProgram.name = handlePtr->programs.shortNames[index];
  297. if (midiProgram.name == NULL)
  298. midiProgram.name = "";
  299. return &midiProgram;
  300. }
  301. static void audiofile_set_parameter_value(PluginHandle handle, uint32_t index, float value)
  302. {
  303. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  304. if (index != 0)
  305. return;
  306. handlePtr->loopMode = (value > 0.5f);
  307. }
  308. static void audiofile_set_program(PluginHandle handle, uint32_t bank, uint32_t program)
  309. {
  310. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  311. if (bank != 0 || program >= PROGRAM_COUNT)
  312. return;
  313. if (handlePtr->programs.current != program)
  314. {
  315. audiofile_load_filename(handlePtr, handlePtr->programs.fullNames[program]);
  316. handlePtr->programs.current = program;
  317. }
  318. }
  319. static void audiofile_set_custom_data(PluginHandle handle, const char* key, const char* value)
  320. {
  321. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  322. if (strncmp(key, "file", 4) != 0)
  323. return;
  324. if (key[4] < '0' || key[4] > '9')
  325. return;
  326. if (key[5] < '0' || key[5] > '9')
  327. return;
  328. uint8_t tens = key[4]-'0';
  329. uint8_t nums = key[5]-'0';
  330. uint32_t program = tens*10 + nums;
  331. if (program >= PROGRAM_COUNT)
  332. return;
  333. if (handlePtr->programs.fullNames[program] != NULL)
  334. free((void*)handlePtr->programs.fullNames[program]);
  335. if (handlePtr->programs.shortNames[program] != NULL)
  336. free((void*)handlePtr->programs.shortNames[program]);
  337. handlePtr->programs.fullNames[program] = strdup(value);
  338. {
  339. const char* shortName1 = strrchr(value, OS_SEP)+1;
  340. //const char* shortName2 = strchr(shortName1, '.');
  341. handlePtr->programs.shortNames[program] = strdup(shortName1);
  342. }
  343. if (handlePtr->programs.current == program)
  344. audiofile_load_filename(handlePtr, value);
  345. }
  346. static void audiofile_ui_show(PluginHandle handle, bool show)
  347. {
  348. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  349. if (! show)
  350. return;
  351. const char* const filename = handlePtr->host->ui_open_file(handlePtr->host->handle, false, "Open Audio File", "");
  352. if (filename != NULL)
  353. {
  354. char fileStr[4+2+1] = { 'f', 'i', 'l', 'e', 0, 0, 0 };
  355. fileStr[4] = '0' + (handlePtr->programs.current / 10);
  356. fileStr[5] = '0' + (handlePtr->programs.current % 10);
  357. handlePtr->host->ui_custom_data_changed(handlePtr->host->handle, fileStr, filename);
  358. }
  359. handlePtr->host->ui_closed(handlePtr->host->handle);
  360. }
  361. static void audiofile_process(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents)
  362. {
  363. AudioFileInstance* const handlePtr = (AudioFileInstance*)handle;
  364. float* out1 = outBuffer[0];
  365. float* out2 = outBuffer[1];
  366. if (! handlePtr->doProcess)
  367. {
  368. //fprintf(stderr, "P: no process\n");
  369. zeroFloat(out1, frames);
  370. zeroFloat(out2, frames);
  371. return;
  372. }
  373. const TimeInfo* const timePos = handlePtr->host->get_time_info(handlePtr->host->handle);
  374. // not playing
  375. if (! timePos->playing)
  376. {
  377. //fprintf(stderr, "P: not rolling\n");
  378. handlePtr->lastFrame = timePos->frame;
  379. zeroFloat(out1, frames);
  380. zeroFloat(out2, frames);
  381. return;
  382. }
  383. pthread_mutex_lock(&handlePtr->mutex);
  384. // out of reach
  385. if (timePos->frame + frames < handlePtr->pool.startFrame || timePos->frame >= handlePtr->maxFrame)
  386. {
  387. //fprintf(stderr, "P: non-continuous playback, out of reach %u vs %u\n", timePos->frame + frames, handlePtr->maxFrame);
  388. handlePtr->lastFrame = timePos->frame;
  389. handlePtr->needsRead = true;
  390. pthread_mutex_unlock(&handlePtr->mutex);
  391. zeroFloat(out1, frames);
  392. zeroFloat(out2, frames);
  393. return;
  394. }
  395. int64_t poolFrame = (int64_t)timePos->frame - handlePtr->pool.startFrame;
  396. int64_t poolSize = handlePtr->pool.size;
  397. for (uint32_t i=0; i < frames; i++, poolFrame++)
  398. {
  399. if (poolFrame >= 0 && poolFrame < poolSize)
  400. {
  401. out1[i] = handlePtr->pool.buffer[0][poolFrame];
  402. out2[i] = handlePtr->pool.buffer[1][poolFrame];
  403. // reset
  404. handlePtr->pool.buffer[0][poolFrame] = 0.0f;
  405. handlePtr->pool.buffer[1][poolFrame] = 0.0f;
  406. }
  407. else
  408. {
  409. out1[i] = 0.0f;
  410. out2[i] = 0.0f;
  411. }
  412. }
  413. handlePtr->lastFrame = timePos->frame;
  414. pthread_mutex_unlock(&handlePtr->mutex);
  415. return;
  416. // unused
  417. (void)inBuffer;
  418. (void)midiEventCount;
  419. (void)midiEvents;
  420. }
  421. // -----------------------------------------------------------------------
  422. static const PluginDescriptor audiofileDesc = {
  423. .category = PLUGIN_CATEGORY_UTILITY,
  424. .hints = PLUGIN_IS_RTSAFE|PLUGIN_HAS_GUI,
  425. .audioIns = 0,
  426. .audioOuts = 2,
  427. .midiIns = 0,
  428. .midiOuts = 0,
  429. .parameterIns = 1,
  430. .parameterOuts = 0,
  431. .name = "Audio File",
  432. .label = "audiofile",
  433. .maker = "falkTX",
  434. .copyright = "GNU GPL v2+",
  435. .instantiate = audiofile_instantiate,
  436. .cleanup = audiofile_cleanup,
  437. .get_parameter_count = audiofile_get_parameter_count,
  438. .get_parameter_info = audiofile_get_parameter_info,
  439. .get_parameter_value = audiofile_get_parameter_value,
  440. .get_parameter_text = NULL,
  441. .get_midi_program_count = audiofile_get_program_count,
  442. .get_midi_program_info = audiofile_get_program_info,
  443. .set_parameter_value = audiofile_set_parameter_value,
  444. .set_midi_program = audiofile_set_program,
  445. .set_custom_data = audiofile_set_custom_data,
  446. .ui_show = audiofile_ui_show,
  447. .ui_idle = NULL,
  448. .ui_set_parameter_value = NULL,
  449. .ui_set_midi_program = NULL,
  450. .ui_set_custom_data = NULL,
  451. .activate = NULL,
  452. .deactivate = NULL,
  453. .process = audiofile_process
  454. };
  455. // -----------------------------------------------------------------------
  456. void carla_register_native_plugin_audiofile()
  457. {
  458. carla_register_native_plugin(&audiofileDesc);
  459. }
  460. // -----------------------------------------------------------------------
  461. // amalgamated build
  462. #include "audio_decoder/ad_ffmpeg.c"
  463. #include "audio_decoder/ad_plugin.c"
  464. #include "audio_decoder/ad_soundfile.c"
  465. // -----------------------------------------------------------------------