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.

audiofile.c 18KB

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