| 
							- /*
 -  * 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.h"
 - #include "carla_plugin.h"
 - 
 - CARLA_BACKEND_START_NAMESPACE
 - 
 - // -------------------------------------------------------------------------------------------------------------------
 - // static RtAudio<->Engine calls
 - 
 - static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
 - {
 -     CarlaEngineRtAudio* const engine = (CarlaEngineRtAudio*)userData;
 -     engine->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
 -     return 0;
 - }
 - 
 - // -------------------------------------------------------------------------------------------------------------------
 - // Carla Engine (RtAudio)
 - 
 - CarlaEngineRtAudio::CarlaEngineRtAudio(RtAudio::Api api)
 -     : CarlaEngine(),
 -       adac(api)
 - {
 -     qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()");
 - 
 -     type = CarlaEngineTypeRtAudio;
 - }
 - 
 - CarlaEngineRtAudio::~CarlaEngineRtAudio()
 - {
 -     qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
 - }
 - 
 - bool CarlaEngineRtAudio::init(const char* const clientName)
 - {
 -     qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName);
 - 
 -     if (adac.getDeviceCount() < 1)
 -     {
 -         setLastError("No audio devices available");
 -         return false;
 -     }
 - 
 -     sampleRate = 48000;
 -     unsigned int rtBufferFrames = 512;
 - 
 -     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 {
 -         adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &rtBufferFrames, carla_rtaudio_process_callback, this, &options);
 -     }
 -     catch (RtError& e)
 -     {
 -         setLastError(e.what());
 -         return false;
 -     }
 - 
 -     bufferSize = rtBufferFrames;
 - 
 -     // set client name, fixed for OSC usage
 -     // FIXME - put this in shared?
 -     char* fixedName = strdup(clientName);
 -     for (size_t i=0; i < strlen(fixedName); i++)
 -     {
 -         if (! (std::isalpha(fixedName[i]) || std::isdigit(fixedName[i])))
 -             fixedName[i] = '_';
 -     }
 -     name = strdup(fixedName);
 -     free((void*)fixedName);
 - 
 -     qDebug("RtAudio bufferSize = %i", bufferSize);
 - 
 -     try {
 -         adac.startStream();
 -     }
 -     catch (RtError& e)
 -     {
 -         setLastError(e.what());
 -         return false;
 -     }
 - 
 -     CarlaEngine::init(name);
 - 
 -     return true;
 - }
 - 
 - bool CarlaEngineRtAudio::close()
 - {
 -     qDebug("CarlaEngineRtAudio::close()");
 -     CarlaEngine::close();
 - 
 -     if (name)
 -     {
 -         free((void*)name);
 -         name = nullptr;
 -     }
 - 
 -     if (adac.isStreamRunning())
 -         adac.stopStream();
 - 
 -     if (adac.isStreamOpen())
 -         adac.closeStream();
 - 
 -     return true;
 - }
 - 
 - bool CarlaEngineRtAudio::isOffline()
 - {
 -     return false;
 - }
 - 
 - bool CarlaEngineRtAudio::isRunning()
 - {
 -     return adac.isStreamRunning();
 - }
 - 
 - CarlaEngineClient* CarlaEngineRtAudio::addClient(CarlaPlugin* const plugin)
 - {
 -     CarlaEngineClientNativeHandle handle;
 - 
 - //    unsigned int rtBufferFrames = getBufferSize();
 - 
 - //    RtAudio::StreamParameters iParams, oParams;
 - //    iParams.nChannels = plugin->audioInCount();
 - //    oParams.nChannels = plugin->audioOutCount();
 - //    RtAudio::StreamOptions options;
 - //    options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
 - //    options.streamName = plugin->name();
 - //    options.priority = 85;
 - 
 - //    try {
 - //        adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, getSampleRate(), &rtBufferFrames, carla_rtaudio_process_callback, this, &options);
 - //    }
 - //    catch (RtError& e)
 - //    {
 - //        setLastError(e.what());
 - //        return false;
 - //    }
 - 
 -     return new CarlaEngineClient(CarlaEngineTypeRtAudio, handle);
 -     Q_UNUSED(plugin);
 - }
 - 
 - // -------------------------------------------------------------------------------------------------------------------
 - 
 - void CarlaEngineRtAudio::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
 -     Q_ASSERT(insPtr);
 -     Q_ASSERT(outsPtr);
 - 
 -     // create temporary audio buffers
 -     float ains_tmp_buf1[nframes];
 -     float ains_tmp_buf2[nframes];
 -     float aouts_tmp_buf1[nframes];
 -     float aouts_tmp_buf2[nframes];
 - 
 -     float* ains_tmp[2]  = { ains_tmp_buf1, ains_tmp_buf2 };
 -     float* aouts_tmp[2] = { aouts_tmp_buf1, aouts_tmp_buf2 };
 - 
 -     // initialize audio input
 -     for (unsigned int i=0; i < nframes*2; i++)
 -     {
 -         if (i % 2)
 -             ains_tmp_buf2[i/2] = insPtr[i];
 -         else
 -             ains_tmp_buf1[i/2] = insPtr[i];
 -     }
 - 
 -     // 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
 -     }
 - 
 -     // initialize outputs (zero)
 -     memset(aouts_tmp_buf1, 0, sizeof(float)*nframes);
 -     memset(aouts_tmp_buf2, 0, sizeof(float)*nframes);
 -     memset(rackControlEventsOut, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
 -     memset(rackMidiEventsOut, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
 - 
 -     bool processed = false;
 - 
 -     // process plugins
 -     for (unsigned short i=0, max=maxPluginNumber(); i < max; i++)
 -     {
 -         CarlaPlugin* const plugin = getPluginUnchecked(i);
 - 
 -         if (plugin && plugin->enabled())
 -         {
 -             if (processed)
 -             {
 -                 // initialize inputs (from previous outputs)
 -                 memcpy(ains_tmp_buf1, aouts_tmp_buf1, sizeof(float)*nframes);
 -                 memcpy(ains_tmp_buf2, aouts_tmp_buf2, sizeof(float)*nframes);
 -                 memcpy(rackMidiEventsIn, rackMidiEventsOut, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
 - 
 -                 // initialize outputs (zero)
 -                 memset(aouts_tmp_buf1, 0, sizeof(float)*nframes);
 -                 memset(aouts_tmp_buf2, 0, sizeof(float)*nframes);
 -                 memset(rackMidiEventsOut, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
 -             }
 - 
 -             // process
 -             plugin->engineProcessLock();
 - 
 -             plugin->initBuffers();
 - 
 -             if (carlaOptions.processHighPrecision)
 -             {
 -                 float* ains_buffer2[2];
 -                 float* aouts_buffer2[2];
 - 
 -                 for (uint32_t j=0; j < nframes; j += 8)
 -                 {
 -                     ains_buffer2[0] = ains_tmp_buf1 + j;
 -                     ains_buffer2[1] = ains_tmp_buf2 + j;
 - 
 -                     aouts_buffer2[0] = aouts_tmp_buf1 + j;
 -                     aouts_buffer2[1] = aouts_tmp_buf2 + j;
 - 
 -                     plugin->process(ains_buffer2, aouts_buffer2, 8, j);
 -                 }
 -             }
 -             else
 -                 plugin->process(ains_tmp, aouts_tmp, nframes);
 - 
 -             plugin->engineProcessUnlock();
 - 
 -             // if plugin has no audio inputs, add previous buffers
 -             if (plugin->audioInCount() == 0)
 -             {
 -                 for (uint32_t j=0; j < nframes; j++)
 -                 {
 -                     aouts_tmp_buf1[j] += ains_tmp_buf1[j];
 -                     aouts_tmp_buf2[j] += ains_tmp_buf2[j];
 -                 }
 -             }
 - 
 -             processed = true;
 -         }
 -     }
 - 
 -     // if no plugins in the rack, copy inputs over outputs
 -     if (! processed)
 -     {
 -         memcpy(aouts_tmp_buf1, ains_tmp_buf1, sizeof(float)*nframes);
 -         memcpy(aouts_tmp_buf2, ains_tmp_buf2, sizeof(float)*nframes);
 -         memcpy(rackMidiEventsOut, rackMidiEventsIn, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
 -     }
 - 
 -     // output audio
 -     for (unsigned int i=0; i < nframes*2; i++)
 -     {
 -         if (i % 2)
 -             outsPtr[i] = aouts_tmp_buf2[i/2];
 -         else
 -             outsPtr[i] = aouts_tmp_buf1[i/2];
 -     }
 - 
 -     // output control
 -     {
 -         // TODO
 -     }
 - 
 -     // output midi
 -     {
 -         // TODO
 -     }
 - 
 -     Q_UNUSED(streamTime);
 -     Q_UNUSED(status);
 - }
 - 
 - CARLA_BACKEND_END_NAMESPACE
 - 
 - #endif // CARLA_ENGINE_RTAUDIO
 
 
  |