Collection of tools useful for audio production
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.

303 lines
8.1KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2012 Filipe Coelho <falktx@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #ifdef CARLA_ENGINE_RTAUDIO
  18. #include "carla_engine.h"
  19. #include "carla_plugin.h"
  20. CARLA_BACKEND_START_NAMESPACE
  21. #if 0
  22. } /* adjust editor indent */
  23. #endif
  24. // -------------------------------------------------------------------------------------------------------------------
  25. // static RtAudio<->Engine calls
  26. static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
  27. {
  28. CarlaEngineRtAudio* const engine = (CarlaEngineRtAudio*)userData;
  29. engine->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
  30. return 0;
  31. }
  32. // -------------------------------------------------------------------------------------------------------------------
  33. // Carla Engine (RtAudio)
  34. CarlaEngineRtAudio::CarlaEngineRtAudio(RtAudio::Api api)
  35. : CarlaEngine(),
  36. adac(api)
  37. {
  38. qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()");
  39. procThread = nullptr;
  40. }
  41. CarlaEngineRtAudio::~CarlaEngineRtAudio()
  42. {
  43. qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
  44. }
  45. bool CarlaEngineRtAudio::init(const char* const clientName)
  46. {
  47. qDebug("CarlaEngineRtAudio::init(%s)", clientName);
  48. procThread = nullptr;
  49. if (adac.getDeviceCount() < 1)
  50. {
  51. setLastError("No audio devices available");
  52. return false;
  53. }
  54. sampleRate = 48000;
  55. unsigned int rtBufferFrames = 512;
  56. RtAudio::StreamParameters iParams, oParams;
  57. //iParams.deviceId = 3;
  58. //oParams.deviceId = 2;
  59. iParams.nChannels = 2;
  60. oParams.nChannels = 2;
  61. RtAudio::StreamOptions options;
  62. options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
  63. options.streamName = clientName;
  64. options.priority = 85;
  65. try {
  66. adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &rtBufferFrames, carla_rtaudio_process_callback, this, &options);
  67. }
  68. catch (RtError& e)
  69. {
  70. setLastError(e.what());
  71. return false;
  72. }
  73. bufferSize = rtBufferFrames;
  74. name = strdup(clientName);
  75. qDebug("RtAudio bufferSize = %i", bufferSize);
  76. try {
  77. adac.startStream();
  78. }
  79. catch (RtError& e)
  80. {
  81. setLastError(e.what());
  82. return false;
  83. }
  84. CarlaEngine::init(name);
  85. return true;
  86. }
  87. bool CarlaEngineRtAudio::close()
  88. {
  89. qDebug("CarlaEngineRtAudio::close()");
  90. CarlaEngine::close();
  91. if (name)
  92. {
  93. free((void*)name);
  94. name = nullptr;
  95. }
  96. if (adac.isStreamRunning())
  97. adac.stopStream();
  98. if (adac.isStreamOpen())
  99. adac.closeStream();
  100. return true;
  101. }
  102. bool CarlaEngineRtAudio::isOnAudioThread()
  103. {
  104. return (QThread::currentThread() == procThread);
  105. }
  106. bool CarlaEngineRtAudio::isOffline()
  107. {
  108. return false;
  109. }
  110. bool CarlaEngineRtAudio::isRunning()
  111. {
  112. return adac.isStreamRunning();
  113. }
  114. CarlaEngineClient* CarlaEngineRtAudio::addClient(CarlaPlugin* const plugin)
  115. {
  116. CarlaEngineClientNativeHandle handle = {
  117. #ifdef CARLA_ENGINE_JACK
  118. nullptr
  119. #endif
  120. };
  121. return new CarlaEngineClient(handle);
  122. Q_UNUSED(plugin);
  123. }
  124. // -------------------------------------------------------------------------------------------------------------------
  125. void CarlaEngineRtAudio::handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
  126. {
  127. if (procThread == nullptr)
  128. procThread = QThread::currentThread();
  129. // get buffers from RtAudio
  130. float* insPtr = (float*)inputBuffer;
  131. float* outsPtr = (float*)outputBuffer;
  132. // assert buffers
  133. assert(insPtr);
  134. assert(outsPtr);
  135. // create temporary audio buffers
  136. float ains_tmp_buf1[nframes];
  137. float ains_tmp_buf2[nframes];
  138. float aouts_tmp_buf1[nframes];
  139. float aouts_tmp_buf2[nframes];
  140. float* ains_tmp[2] = { ains_tmp_buf1, ains_tmp_buf2 };
  141. float* aouts_tmp[2] = { aouts_tmp_buf1, aouts_tmp_buf2 };
  142. // initialize audio input
  143. for (unsigned int i=0; i < nframes*2; i++)
  144. {
  145. if (i % 2)
  146. ains_tmp_buf2[i/2] = insPtr[i];
  147. else
  148. ains_tmp_buf1[i/2] = insPtr[i];
  149. }
  150. // initialize control input
  151. memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
  152. {
  153. // TODO
  154. }
  155. // initialize midi input
  156. memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  157. {
  158. // TODO
  159. }
  160. // initialize outputs (zero)
  161. memset(aouts_tmp_buf1, 0, sizeof(float)*nframes);
  162. memset(aouts_tmp_buf2, 0, sizeof(float)*nframes);
  163. memset(rackControlEventsOut, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
  164. memset(rackMidiEventsOut, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  165. bool processed = false;
  166. // process plugins
  167. for (unsigned short i=0; i < MAX_PLUGINS; i++)
  168. {
  169. CarlaPlugin* const plugin = getPlugin(i);
  170. if (plugin && plugin->enabled())
  171. {
  172. if (processed)
  173. {
  174. // initialize inputs (from previous outputs)
  175. memcpy(ains_tmp_buf1, aouts_tmp_buf1, sizeof(float)*nframes);
  176. memcpy(ains_tmp_buf2, aouts_tmp_buf2, sizeof(float)*nframes);
  177. memcpy(rackMidiEventsIn, rackMidiEventsOut, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  178. // initialize outputs (zero)
  179. memset(aouts_tmp_buf1, 0, sizeof(float)*nframes);
  180. memset(aouts_tmp_buf2, 0, sizeof(float)*nframes);
  181. memset(rackMidiEventsOut, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  182. }
  183. // process
  184. plugin->engineProcessLock();
  185. plugin->initBuffers();
  186. if (carlaOptions.proccess_hp)
  187. {
  188. float* ains_buffer2[2];
  189. float* aouts_buffer2[2];
  190. for (uint32_t j=0; j < nframes; j += 8)
  191. {
  192. ains_buffer2[0] = ains_tmp_buf1 + j;
  193. ains_buffer2[1] = ains_tmp_buf2 + j;
  194. aouts_buffer2[0] = aouts_tmp_buf1 + j;
  195. aouts_buffer2[1] = aouts_tmp_buf2 + j;
  196. plugin->process(ains_buffer2, aouts_buffer2, 8, j);
  197. }
  198. }
  199. else
  200. plugin->process(ains_tmp, aouts_tmp, nframes);
  201. plugin->engineProcessUnlock();
  202. // if plugin has no audio inputs, add previous buffers
  203. if (plugin->audioInCount() == 0)
  204. {
  205. for (uint32_t j=0; j < nframes; j++)
  206. {
  207. aouts_tmp_buf1[j] += ains_tmp_buf1[j];
  208. aouts_tmp_buf2[j] += ains_tmp_buf2[j];
  209. }
  210. }
  211. processed = true;
  212. }
  213. }
  214. // if no plugins in the rack, copy inputs over outputs
  215. if (! processed)
  216. {
  217. memcpy(aouts_tmp_buf1, ains_tmp_buf1, sizeof(float)*nframes);
  218. memcpy(aouts_tmp_buf2, ains_tmp_buf2, sizeof(float)*nframes);
  219. memcpy(rackMidiEventsOut, rackMidiEventsIn, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  220. }
  221. // output audio
  222. for (unsigned int i=0; i < nframes*2; i++)
  223. {
  224. if (i % 2)
  225. outsPtr[i] = aouts_tmp_buf2[i/2];
  226. else
  227. outsPtr[i] = aouts_tmp_buf1[i/2];
  228. }
  229. // output control
  230. {
  231. // TODO
  232. }
  233. // output midi
  234. {
  235. // TODO
  236. }
  237. Q_UNUSED(streamTime);
  238. Q_UNUSED(status);
  239. }
  240. CARLA_BACKEND_END_NAMESPACE
  241. #endif // CARLA_ENGINE_RTAUDIO