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.

264 lines
6.5KB

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