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.

652 lines
17KB

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