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.

439 lines
11KB

  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. // RtAudio Engine client
  25. class CarlaEngineRtAudioClient : public CarlaEngineClient
  26. {
  27. public:
  28. CarlaEngineRtAudioClient(const CarlaEngineType engineType, const ProcessMode processMode)
  29. : CarlaEngineClient(engineType, processMode)
  30. {
  31. }
  32. ~CarlaEngineRtAudioClient()
  33. {
  34. }
  35. const CarlaEngineBasePort* addPort(const CarlaEnginePortType portType, const char* const name, const bool isInput)
  36. {
  37. qDebug("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s)", portType, name, bool2str(isInput));
  38. switch (portType)
  39. {
  40. case CarlaEnginePortTypeNull:
  41. break;
  42. case CarlaEnginePortTypeAudio:
  43. return new CarlaEngineAudioPort(isInput, processMode);
  44. case CarlaEnginePortTypeControl:
  45. return new CarlaEngineControlPort(isInput, processMode);
  46. case CarlaEnginePortTypeMIDI:
  47. return new CarlaEngineMidiPort(isInput, processMode);
  48. }
  49. qCritical("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput));
  50. return nullptr;
  51. }
  52. };
  53. // -------------------------------------------------------------------------------------------------------------------
  54. // RtAudio Engine
  55. class CarlaEngineRtAudio : public CarlaEngine
  56. {
  57. public:
  58. CarlaEngineRtAudio(RtAudio::Api api)
  59. : CarlaEngine(),
  60. audio(api)
  61. {
  62. qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()");
  63. midiIn = nullptr;
  64. midiOut = nullptr;
  65. m_audioInterleaved = false;
  66. m_inBuf1 = nullptr;
  67. m_inBuf2 = nullptr;
  68. m_outBuf1 = nullptr;
  69. m_outBuf2 = nullptr;
  70. // just to make sure
  71. options.forceStereo = true;
  72. options.processMode = PROCESS_MODE_CONTINUOUS_RACK;
  73. }
  74. ~CarlaEngineRtAudio()
  75. {
  76. qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
  77. }
  78. // -------------------------------------
  79. bool init(const char* const clientName)
  80. {
  81. qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName);
  82. if (audio.getDeviceCount() < 1)
  83. {
  84. setLastError("No audio devices available for this driver");
  85. return false;
  86. }
  87. bufferSize = options.preferredBufferSize;
  88. sampleRate = options.preferredSampleRate;
  89. RtAudio::StreamParameters iParams, oParams;
  90. iParams.deviceId = audio.getDefaultInputDevice();
  91. oParams.deviceId = audio.getDefaultOutputDevice();
  92. iParams.nChannels = 2;
  93. oParams.nChannels = 2;
  94. RtAudio::StreamOptions rtOptions;
  95. rtOptions.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_HOG_DEVICE | RTAUDIO_SCHEDULE_REALTIME;
  96. rtOptions.numberOfBuffers = 2;
  97. rtOptions.streamName = clientName;
  98. rtOptions.priority = 85;
  99. if (audio.getCurrentApi() != RtAudio::LINUX_PULSE)
  100. {
  101. rtOptions.flags |= RTAUDIO_NONINTERLEAVED;
  102. m_audioInterleaved = false;
  103. if (audio.getCurrentApi() == RtAudio::LINUX_ALSA)
  104. rtOptions.flags |= RTAUDIO_ALSA_USE_DEFAULT;
  105. }
  106. else
  107. m_audioInterleaved = true;
  108. try {
  109. audio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &bufferSize, carla_rtaudio_process_callback, this, &rtOptions);
  110. }
  111. catch (RtError& e)
  112. {
  113. setLastError(e.what());
  114. return false;
  115. }
  116. try {
  117. audio.startStream();
  118. }
  119. catch (RtError& e)
  120. {
  121. setLastError(e.what());
  122. return false;
  123. }
  124. sampleRate = audio.getStreamSampleRate();
  125. m_inBuf1 = new float [bufferSize];
  126. m_inBuf2 = new float [bufferSize];
  127. m_outBuf1 = new float [bufferSize];
  128. m_outBuf2 = new float [bufferSize];
  129. //midiIn = new MidiInAlsa(clientName, 512);
  130. //midiIn->openVirtualPort("control-in");
  131. //midiIn->openVirtualPort("midi-in");
  132. //midiOut = new MidiOutAlsa(clientName);
  133. //midiOut->openVirtualPort("control-out");
  134. //midiOut->openVirtualPort("midi-out");
  135. name = clientName;
  136. name.toBasic();
  137. CarlaEngine::init(name);
  138. return true;
  139. }
  140. bool close()
  141. {
  142. qDebug("CarlaEngineRtAudio::close()");
  143. CarlaEngine::close();
  144. if (audio.isStreamRunning())
  145. audio.stopStream();
  146. if (audio.isStreamOpen())
  147. audio.closeStream();
  148. #if 0
  149. if (midiIn)
  150. {
  151. midiIn->cancelCallback();
  152. midiIn->closePort();
  153. delete midiIn;
  154. midiIn = nullptr;
  155. }
  156. if (midiOut)
  157. {
  158. midiOut->closePort();
  159. delete midiOut;
  160. midiOut = nullptr;
  161. }
  162. #endif
  163. if (m_inBuf1)
  164. {
  165. delete[] m_inBuf1;
  166. m_inBuf1 = nullptr;
  167. }
  168. if (m_inBuf2)
  169. {
  170. delete[] m_inBuf2;
  171. m_inBuf2 = nullptr;
  172. }
  173. if (m_outBuf1)
  174. {
  175. delete[] m_outBuf1;
  176. m_outBuf1 = nullptr;
  177. }
  178. if (m_outBuf2)
  179. {
  180. delete[] m_outBuf2;
  181. m_outBuf2 = nullptr;
  182. }
  183. return true;
  184. }
  185. bool isOffline() const
  186. {
  187. return false;
  188. }
  189. bool isRunning() const
  190. {
  191. return audio.isStreamRunning();
  192. }
  193. CarlaEngineType type() const
  194. {
  195. return CarlaEngineTypeRtAudio;
  196. }
  197. CarlaEngineClient* addClient(CarlaPlugin* const)
  198. {
  199. return new CarlaEngineRtAudioClient(CarlaEngineTypeRtAudio, options.processMode);
  200. }
  201. // -------------------------------------
  202. protected:
  203. void handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
  204. {
  205. if (maxPluginNumber() == 0)
  206. return;
  207. // get buffers from RtAudio
  208. float* insPtr = (float*)inputBuffer;
  209. float* outsPtr = (float*)outputBuffer;
  210. // assert buffers
  211. CARLA_ASSERT(insPtr);
  212. CARLA_ASSERT(outsPtr);
  213. // initialize audio input
  214. if (m_audioInterleaved)
  215. {
  216. for (unsigned int i=0; i < nframes*2; i++)
  217. {
  218. if (i % 2)
  219. m_inBuf2[i/2] = insPtr[i];
  220. else
  221. m_inBuf1[i/2] = insPtr[i];
  222. }
  223. }
  224. else
  225. {
  226. for (unsigned int i=0; i < nframes; i++)
  227. m_inBuf1[i] = insPtr[i];
  228. for (unsigned int i=0, j=nframes; i < nframes; i++, j++)
  229. m_inBuf2[i] = insPtr[j];
  230. }
  231. // create audio buffers
  232. float* inBuf[2] = { m_inBuf1, m_inBuf2 };
  233. float* outBuf[2] = { m_outBuf1, m_outBuf2 };
  234. // initialize control input
  235. memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_CONTROL_EVENTS);
  236. {
  237. // TODO
  238. }
  239. // initialize midi input
  240. memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_MIDI_EVENTS);
  241. {
  242. // TODO
  243. }
  244. processRack(inBuf, outBuf, nframes);
  245. // output audio
  246. if (m_audioInterleaved)
  247. {
  248. for (unsigned int i=0; i < nframes*2; i++)
  249. {
  250. if (i % 2)
  251. outsPtr[i] = m_outBuf2[i/2];
  252. else
  253. outsPtr[i] = m_outBuf1[i/2];
  254. }
  255. }
  256. else
  257. {
  258. for (unsigned int i=0; i < nframes; i++)
  259. outsPtr[i] = m_outBuf1[i];
  260. for (unsigned int i=0, j=nframes; i < nframes; i++, j++)
  261. outsPtr[j] = m_outBuf2[i];
  262. }
  263. // output control
  264. {
  265. // TODO
  266. }
  267. // output midi
  268. {
  269. // TODO
  270. }
  271. Q_UNUSED(streamTime);
  272. Q_UNUSED(status);
  273. }
  274. // -------------------------------------
  275. private:
  276. RtAudio audio;
  277. MidiInApi* midiIn;
  278. MidiOutApi* midiOut;
  279. bool m_audioInterleaved;
  280. float* m_inBuf1;
  281. float* m_inBuf2;
  282. float* m_outBuf1;
  283. float* m_outBuf2;
  284. static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
  285. {
  286. CarlaEngineRtAudio* const _this_ = (CarlaEngineRtAudio*)userData;
  287. _this_->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
  288. return 0;
  289. }
  290. };
  291. // -----------------------------------------
  292. CarlaEngine* CarlaEngine::newRtAudio(RtAudioApi api)
  293. {
  294. RtAudio::Api rtApi = RtAudio::UNSPECIFIED;
  295. switch (api)
  296. {
  297. case RTAUDIO_DUMMY:
  298. rtApi = RtAudio::RTAUDIO_DUMMY;
  299. break;
  300. case RTAUDIO_LINUX_ALSA:
  301. rtApi = RtAudio::LINUX_ALSA;
  302. break;
  303. case RTAUDIO_LINUX_PULSE:
  304. rtApi = RtAudio::LINUX_PULSE;
  305. break;
  306. case RTAUDIO_LINUX_OSS:
  307. rtApi = RtAudio::LINUX_OSS;
  308. break;
  309. case RTAUDIO_UNIX_JACK:
  310. rtApi = RtAudio::UNIX_JACK;
  311. break;
  312. case RTAUDIO_MACOSX_CORE:
  313. rtApi = RtAudio::MACOSX_CORE;
  314. break;
  315. case RTAUDIO_WINDOWS_ASIO:
  316. rtApi = RtAudio::WINDOWS_ASIO;
  317. break;
  318. case RTAUDIO_WINDOWS_DS:
  319. rtApi = RtAudio::WINDOWS_DS;
  320. break;
  321. }
  322. return new CarlaEngineRtAudio(rtApi);
  323. }
  324. unsigned int CarlaEngine::getRtAudioApiCount()
  325. {
  326. std::vector<RtAudio::Api> apis;
  327. RtAudio::getCompiledApi(apis);
  328. return apis.size();
  329. }
  330. const char* CarlaEngine::getRtAudioApiName(unsigned int index)
  331. {
  332. std::vector<RtAudio::Api> apis;
  333. RtAudio::getCompiledApi(apis);
  334. if (index < apis.size())
  335. {
  336. const RtAudio::Api& api(apis[index]);
  337. switch (api)
  338. {
  339. case RtAudio::UNSPECIFIED:
  340. return "Unspecified";
  341. case RtAudio::LINUX_ALSA:
  342. return "ALSA";
  343. case RtAudio::LINUX_PULSE:
  344. return "PulseAudio";
  345. case RtAudio::LINUX_OSS:
  346. return "OSS";
  347. case RtAudio::UNIX_JACK:
  348. return "JACK (RtAudio)";
  349. case RtAudio::MACOSX_CORE:
  350. return "CoreAudio";
  351. case RtAudio::WINDOWS_ASIO:
  352. return "ASIO";
  353. case RtAudio::WINDOWS_DS:
  354. return "DirectSound";
  355. case RtAudio::RTAUDIO_DUMMY:
  356. return "Dummy";
  357. }
  358. }
  359. return nullptr;
  360. }
  361. CARLA_BACKEND_END_NAMESPACE
  362. #endif // CARLA_ENGINE_RTAUDIO