|
- /*
- * Carla Backend
- * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a full copy of the GNU General Public License see the COPYING file
- */
-
- #ifdef CARLA_ENGINE_RTAUDIO
-
- #include "carla_engine.hpp"
- #include "carla_plugin.hpp"
-
- CARLA_BACKEND_START_NAMESPACE
-
- // -----------------------------------------
-
- class CarlaEngineRtAudio : public CarlaEngine
- {
- public:
- CarlaEngineRtAudio(RtAudio::Api api)
- : CarlaEngine(),
- audio(api)
- {
- qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()");
-
- type = CarlaEngineTypeRtAudio;
-
- midiIn = nullptr;
- midiOut = nullptr;
-
- // just to make sure
- options.forceStereo = true;
- processMode = PROCESS_MODE_CONTINUOUS_RACK;
- }
-
- ~CarlaEngineRtAudio()
- {
- qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
- }
-
- // -------------------------------------
-
- bool init(const char* const clientName)
- {
- qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName);
-
- if (audio.getDeviceCount() < 1)
- {
- setLastError("No audio devices available for this driver");
- return false;
- }
-
- bufferSize = options.preferredBufferSize;
- sampleRate = options.preferredSampleRate;
-
- RtAudio::StreamParameters iParams, oParams;
- //iParams.deviceId = 3;
- //oParams.deviceId = 2;
- iParams.nChannels = 2;
- oParams.nChannels = 2;
-
- RtAudio::StreamOptions options;
- options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
- options.streamName = clientName;
- options.priority = 85;
-
- try {
- audio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &bufferSize, carla_rtaudio_process_callback, this, &options);
- }
- catch (RtError& e)
- {
- setLastError(e.what());
- return false;
- }
-
- try {
- audio.startStream();
- }
- catch (RtError& e)
- {
- setLastError(e.what());
- return false;
- }
-
- midiIn = new MidiInAlsa(clientName, 512);
- midiIn->openVirtualPort("control-in");
- midiIn->openVirtualPort("midi-in");
-
- midiOut = new MidiOutAlsa(clientName);
- midiOut->openVirtualPort("control-out");
- midiOut->openVirtualPort("midi-out");
-
- name = getFixedClientName(clientName);
- CarlaEngine::init(name);
- return true;
- }
-
- bool close()
- {
- qDebug("CarlaEngineRtAudio::close()");
- CarlaEngine::close();
-
- if (name)
- {
- free((void*)name);
- name = nullptr;
- }
-
- if (audio.isStreamRunning())
- audio.stopStream();
-
- if (audio.isStreamOpen())
- audio.closeStream();
-
- if (midiIn)
- {
- midiIn->cancelCallback();
- midiIn->closePort();
- delete midiIn;
- midiIn = nullptr;
- }
-
- if (midiOut)
- {
- midiOut->closePort();
- delete midiOut;
- midiOut = nullptr;
- }
-
- return true;
- }
-
- bool isOffline()
- {
- return false;
- }
-
- bool isRunning()
- {
- return audio.isStreamRunning();
- }
-
- CarlaEngineClient* addClient(CarlaPlugin* const plugin)
- {
- CarlaEngineClientNativeHandle handle;
- handle.type = CarlaEngineTypeRtAudio;
-
- return new CarlaEngineClient(handle);
- Q_UNUSED(plugin);
- }
-
- // -------------------------------------
-
- protected:
- void handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
- {
- if (maxPluginNumber() == 0)
- return;
-
- // get buffers from RtAudio
- float* insPtr = (float*)inputBuffer;
- float* outsPtr = (float*)outputBuffer;
-
- // assert buffers
- CARLA_ASSERT(insPtr);
- CARLA_ASSERT(outsPtr);
-
- // create temporary audio buffers
- float inBuf1[nframes];
- float inBuf2[nframes];
- float outBuf1[nframes];
- float outBuf2[nframes];
-
- // initialize audio input
- for (unsigned int i=0; i < nframes*2; i++)
- {
- if (i % 2)
- inBuf2[i/2] = insPtr[i];
- else
- inBuf1[i/2] = insPtr[i];
- }
-
- // create (real) audio buffers
- float* inBuf[2] = { inBuf1, inBuf2 };
- float* outBuf[2] = { outBuf1, outBuf2 };
-
- // initialize control input
- memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
- {
- // TODO
- }
-
- // initialize midi input
- memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
- {
- // TODO
- }
-
- processRack(inBuf, outBuf, nframes);
-
- // output audio
- for (unsigned int i=0; i < nframes*2; i++)
- {
- if (i % 2)
- outsPtr[i] = outBuf2[i/2];
- else
- outsPtr[i] = outBuf1[i/2];
- }
-
- // output control
- {
- // TODO
- }
-
- // output midi
- {
- // TODO
- }
-
- Q_UNUSED(streamTime);
- Q_UNUSED(status);
- }
-
- // -------------------------------------
-
- private:
- RtAudio audio;
- MidiInApi* midiIn;
- MidiOutApi* midiOut;
-
- static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
- {
- CarlaEngineRtAudio* const _this_ = (CarlaEngineRtAudio*)userData;
- _this_->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
- return 0;
- }
- };
-
- // -----------------------------------------
-
- CarlaEngine* CarlaEngine::newRtAudio(RtAudio::Api api)
- {
- return new CarlaEngineRtAudio(api);
- }
-
- // -----------------------------------------
-
- CARLA_BACKEND_END_NAMESPACE
-
- #endif // CARLA_ENGINE_RTAUDIO
|