| @@ -37,6 +37,10 @@ ifeq ($(HAVE_DGL),true) | |||
| STANDALONE_LIBS += $(MODULEDIR)/dgl.a | |||
| endif | |||
| ifeq ($(HAVE_HYLIA),true) | |||
| STANDALONE_LIBS += $(MODULEDIR)/hylia.a | |||
| endif | |||
| ifeq ($(MACOS_OR_WIN32),true) | |||
| STANDALONE_LIBS += $(MODULEDIR)/juce_audio_devices.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/juce_audio_processors.a | |||
| @@ -64,7 +64,23 @@ EngineInternalTime::EngineInternalTime() noexcept | |||
| frame(0), | |||
| bpm(120.0), | |||
| sampleRate(0.0), | |||
| #ifdef BUILD_BRIDGE | |||
| tick(0.0) {} | |||
| #else | |||
| tick(0.0), | |||
| hylia(nullptr), | |||
| hylia_enabled(0) | |||
| { | |||
| carla_zeroStruct(hylia_time); | |||
| } | |||
| #endif | |||
| EngineInternalTime::~EngineInternalTime() noexcept | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| hylia_cleanup(hylia); | |||
| #endif | |||
| } | |||
| void EngineInternalTime::fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t newFrames) noexcept | |||
| { | |||
| @@ -84,6 +100,19 @@ void EngineInternalTime::fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t | |||
| double abs_beat, abs_tick; | |||
| #ifndef BUILD_BRIDGE | |||
| if (hylia_enabled > 0 && hylia_time.bpm > 0.0) | |||
| { | |||
| const double beats = hylia_time.beats; | |||
| if (beats < 0.0) | |||
| return; | |||
| abs_beat = std::floor(beats); | |||
| abs_tick = beats * kTicksPerBeat; | |||
| } | |||
| else | |||
| #endif | |||
| { | |||
| const double min = frame / (sampleRate * 60.0); | |||
| abs_tick = min * bpm * kTicksPerBeat; | |||
| @@ -316,6 +345,14 @@ void CarlaEngine::ProtectedData::initTime() | |||
| time.sampleRate = sampleRate; | |||
| time.tick = 0.0; | |||
| time.fillEngineTimeInfo(timeInfo, 0); | |||
| #ifndef BUILD_BRIDGE | |||
| CARLA_SAFE_ASSERT_RETURN(time.hylia == nullptr,); | |||
| time.hylia = hylia_create(120.0, bufferSize, sampleRate); | |||
| //time.hylia_enabled = 1; | |||
| //hylia_enable(time.hylia, true, 120.0); | |||
| #endif | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -409,8 +446,27 @@ void CarlaEngine::ProtectedData::doNextPluginAction(const bool unlock) noexcept | |||
| // ----------------------------------------------------------------------- | |||
| // PendingRtEventsRunner | |||
| PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine) noexcept | |||
| : pData(engine->pData) {} | |||
| PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t bufSize) noexcept | |||
| : pData(engine->pData), | |||
| bufferSize(bufSize) | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| if (pData->time.hylia_enabled > 0) | |||
| { | |||
| hylia_process(pData->time.hylia, bufferSize, &pData->time.hylia_time); | |||
| const double new_bpm = pData->time.hylia_time.bpm; | |||
| if (new_bpm > 0.0 && (pData->time.bpm != new_bpm || ++pData->time.hylia_enabled > 50)) | |||
| { | |||
| pData->time.bpm = new_bpm; | |||
| pData->time.hylia_enabled = 1; | |||
| if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||
| } | |||
| } | |||
| #endif | |||
| } | |||
| PendingRtEventsRunner::~PendingRtEventsRunner() noexcept | |||
| { | |||
| @@ -418,8 +474,8 @@ PendingRtEventsRunner::~PendingRtEventsRunner() noexcept | |||
| if (pData->time.playing && pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) | |||
| { | |||
| pData->time.frame += pData->bufferSize; | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, pData->bufferSize); | |||
| pData->time.frame += bufferSize; | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, bufferSize); | |||
| } | |||
| } | |||
| @@ -22,6 +22,8 @@ | |||
| #include "CarlaEngineThread.hpp" | |||
| #include "CarlaEngineUtils.hpp" | |||
| #include "hylia/hylia.h" | |||
| // FIXME only use CARLA_PREVENT_HEAP_ALLOCATION for structs | |||
| // maybe separate macro | |||
| @@ -116,7 +118,14 @@ struct EngineInternalTime { | |||
| double sampleRate; | |||
| double tick; | |||
| #ifndef BUILD_BRIDGE | |||
| hylia_t* hylia; | |||
| int hylia_enabled; | |||
| hylia_time_info_t hylia_time; | |||
| #endif | |||
| EngineInternalTime() noexcept; | |||
| ~EngineInternalTime() noexcept; | |||
| void fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t newFrames) noexcept; | |||
| @@ -245,11 +254,12 @@ struct CarlaEngine::ProtectedData { | |||
| class PendingRtEventsRunner | |||
| { | |||
| public: | |||
| PendingRtEventsRunner(CarlaEngine* const engine) noexcept; | |||
| PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t bufferSize) noexcept; | |||
| ~PendingRtEventsRunner() noexcept; | |||
| private: | |||
| CarlaEngine::ProtectedData* const pData; | |||
| const uint32_t bufferSize; | |||
| CARLA_PREVENT_HEAP_ALLOCATION | |||
| CARLA_DECLARE_NON_COPY_CLASS(PendingRtEventsRunner) | |||
| @@ -1547,7 +1547,7 @@ protected: | |||
| void handleJackProcessCallback(const uint32_t nframes) | |||
| { | |||
| const PendingRtEventsRunner prt(this); | |||
| const PendingRtEventsRunner prt(this, nframes); | |||
| CARLA_SAFE_ASSERT_RETURN(nframes == pData->bufferSize,); | |||
| @@ -1911,7 +1911,7 @@ protected: | |||
| signalThreadShouldExit(); | |||
| #endif | |||
| const PendingRtEventsRunner prt(this); | |||
| const PendingRtEventsRunner prt(this, pData->bufferSize); | |||
| for (uint i=0; i < pData->curPluginCount; ++i) | |||
| { | |||
| @@ -442,9 +442,10 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| protected: | |||
| void audioDeviceIOCallback(const float** inputChannelData, int numInputChannels, float** outputChannelData, int numOutputChannels, int numSamples) override | |||
| void audioDeviceIOCallback(const float** inputChannelData, int numInputChannels, float** outputChannelData, | |||
| int numOutputChannels, int numSamples) override | |||
| { | |||
| const PendingRtEventsRunner prt(this); | |||
| const PendingRtEventsRunner prt(this, numSamples); | |||
| // assert juce buffers | |||
| CARLA_SAFE_ASSERT_RETURN(numInputChannels >= 0,); | |||
| @@ -1329,7 +1329,7 @@ protected: | |||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, | |||
| const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) | |||
| { | |||
| const PendingRtEventsRunner prt(this); | |||
| const PendingRtEventsRunner prt(this, frames); | |||
| // --------------------------------------------------------------- | |||
| // Time Info | |||
| @@ -553,7 +553,7 @@ public: | |||
| protected: | |||
| void handleAudioProcessCallback(void* outputBuffer, void* inputBuffer, uint nframes, double streamTime, RtAudioStreamStatus status) | |||
| { | |||
| const PendingRtEventsRunner prt(this); | |||
| const PendingRtEventsRunner prt(this, nframes); | |||
| // get buffers from RtAudio | |||
| const float* const insPtr = (const float*)inputBuffer; | |||
| @@ -694,6 +694,8 @@ protected: | |||
| } | |||
| } | |||
| fMidiOutMutex.unlock(); | |||
| if (fAudioInterleaved) | |||
| { | |||
| for (uint i=0; i < nframes; ++i) | |||
| @@ -701,8 +703,6 @@ protected: | |||
| outsPtr[i*fAudioOutCount+j] = outBuf[j][i]; | |||
| } | |||
| fMidiOutMutex.unlock(); | |||
| return; // unused | |||
| (void)streamTime; (void)status; | |||
| } | |||
| @@ -41,6 +41,10 @@ ifeq ($(HAVE_DGL),true) | |||
| LIBS += $(MODULEDIR)/dgl.a | |||
| endif | |||
| ifeq ($(HAVE_HYLIA),true) | |||
| LIBS += $(MODULEDIR)/hylia.a | |||
| endif | |||
| ifeq ($(MACOS_OR_WIN32),true) | |||
| LIBS += $(MODULEDIR)/juce_audio_processors.a | |||
| LIBS += $(MODULEDIR)/juce_data_structures.a | |||