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.

261 lines
6.5KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2012 Filipe Coelho <falktx@falktx.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.hpp"
  19. #include "carla_plugin.hpp"
  20. CARLA_BACKEND_START_NAMESPACE
  21. // -----------------------------------------
  22. class CarlaEngineRtAudio : public CarlaEngine
  23. {
  24. public:
  25. CarlaEngineRtAudio(RtAudio::Api api)
  26. : CarlaEngine(),
  27. audio(api)
  28. {
  29. qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()");
  30. type = CarlaEngineTypeRtAudio;
  31. midiIn = nullptr;
  32. midiOut = nullptr;
  33. // just to make sure
  34. options.forceStereo = true;
  35. processMode = PROCESS_MODE_CONTINUOUS_RACK;
  36. }
  37. ~CarlaEngineRtAudio()
  38. {
  39. qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
  40. }
  41. // -------------------------------------
  42. bool init(const char* const clientName)
  43. {
  44. qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName);
  45. if (audio.getDeviceCount() < 1)
  46. {
  47. setLastError("No audio devices available for this driver");
  48. return false;
  49. }
  50. bufferSize = options.preferredBufferSize;
  51. sampleRate = options.preferredSampleRate;
  52. RtAudio::StreamParameters iParams, oParams;
  53. //iParams.deviceId = 3;
  54. //oParams.deviceId = 2;
  55. iParams.nChannels = 2;
  56. oParams.nChannels = 2;
  57. RtAudio::StreamOptions options;
  58. options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
  59. options.streamName = clientName;
  60. options.priority = 85;
  61. try {
  62. audio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &bufferSize, carla_rtaudio_process_callback, this, &options);
  63. }
  64. catch (RtError& e)
  65. {
  66. setLastError(e.what());
  67. return false;
  68. }
  69. try {
  70. audio.startStream();
  71. }
  72. catch (RtError& e)
  73. {
  74. setLastError(e.what());
  75. return false;
  76. }
  77. midiIn = new MidiInAlsa(clientName, 512);
  78. midiIn->openVirtualPort("control-in");
  79. midiIn->openVirtualPort("midi-in");
  80. midiOut = new MidiOutAlsa(clientName);
  81. midiOut->openVirtualPort("control-out");
  82. midiOut->openVirtualPort("midi-out");
  83. name = getFixedClientName(clientName);
  84. CarlaEngine::init(name);
  85. return true;
  86. }
  87. bool close()
  88. {
  89. qDebug("CarlaEngineRtAudio::close()");
  90. CarlaEngine::close();
  91. if (name)
  92. {
  93. free((void*)name);
  94. name = nullptr;
  95. }
  96. if (audio.isStreamRunning())
  97. audio.stopStream();
  98. if (audio.isStreamOpen())
  99. audio.closeStream();
  100. if (midiIn)
  101. {
  102. midiIn->cancelCallback();
  103. midiIn->closePort();
  104. delete midiIn;
  105. midiIn = nullptr;
  106. }
  107. if (midiOut)
  108. {
  109. midiOut->closePort();
  110. delete midiOut;
  111. midiOut = nullptr;
  112. }
  113. return true;
  114. }
  115. bool isOffline()
  116. {
  117. return false;
  118. }
  119. bool isRunning()
  120. {
  121. return audio.isStreamRunning();
  122. }
  123. CarlaEngineClient* addClient(CarlaPlugin* const plugin)
  124. {
  125. CarlaEngineClientNativeHandle handle;
  126. handle.type = CarlaEngineTypeRtAudio;
  127. return new CarlaEngineClient(handle);
  128. Q_UNUSED(plugin);
  129. }
  130. // -------------------------------------
  131. protected:
  132. void handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
  133. {
  134. if (maxPluginNumber() == 0)
  135. return;
  136. // get buffers from RtAudio
  137. float* insPtr = (float*)inputBuffer;
  138. float* outsPtr = (float*)outputBuffer;
  139. // assert buffers
  140. CARLA_ASSERT(insPtr);
  141. CARLA_ASSERT(outsPtr);
  142. // create temporary audio buffers
  143. float inBuf1[nframes];
  144. float inBuf2[nframes];
  145. float outBuf1[nframes];
  146. float outBuf2[nframes];
  147. // initialize audio input
  148. for (unsigned int i=0; i < nframes*2; i++)
  149. {
  150. if (i % 2)
  151. inBuf2[i/2] = insPtr[i];
  152. else
  153. inBuf1[i/2] = insPtr[i];
  154. }
  155. // create (real) audio buffers
  156. float* inBuf[2] = { inBuf1, inBuf2 };
  157. float* outBuf[2] = { outBuf1, outBuf2 };
  158. // initialize control input
  159. memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
  160. {
  161. // TODO
  162. }
  163. // initialize midi input
  164. memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
  165. {
  166. // TODO
  167. }
  168. processRack(inBuf, outBuf, nframes);
  169. // output audio
  170. for (unsigned int i=0; i < nframes*2; i++)
  171. {
  172. if (i % 2)
  173. outsPtr[i] = outBuf2[i/2];
  174. else
  175. outsPtr[i] = outBuf1[i/2];
  176. }
  177. // output control
  178. {
  179. // TODO
  180. }
  181. // output midi
  182. {
  183. // TODO
  184. }
  185. Q_UNUSED(streamTime);
  186. Q_UNUSED(status);
  187. }
  188. // -------------------------------------
  189. private:
  190. RtAudio audio;
  191. MidiInApi* midiIn;
  192. MidiOutApi* midiOut;
  193. static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
  194. {
  195. CarlaEngineRtAudio* const _this_ = (CarlaEngineRtAudio*)userData;
  196. _this_->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
  197. return 0;
  198. }
  199. };
  200. // -----------------------------------------
  201. CarlaEngine* CarlaEngine::newRtAudio(RtAudio::Api api)
  202. {
  203. return new CarlaEngineRtAudio(api);
  204. }
  205. // -----------------------------------------
  206. CARLA_BACKEND_END_NAMESPACE
  207. #endif // CARLA_ENGINE_RTAUDIO