| @@ -1341,16 +1341,19 @@ void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) | |||
| void CarlaEngine::transportPlay() noexcept | |||
| { | |||
| pData->time.playing = true; | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||
| } | |||
| void CarlaEngine::transportPause() noexcept | |||
| { | |||
| pData->time.playing = false; | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||
| } | |||
| void CarlaEngine::transportRelocate(const uint64_t frame) noexcept | |||
| { | |||
| pData->time.frame = frame; | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1664,6 +1667,9 @@ void CarlaEngine::sampleRateChanged(const double newSampleRate) | |||
| } | |||
| #endif | |||
| pData->time.sampleRate = newSampleRate; | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||
| for (uint i=0; i < pData->curPluginCount; ++i) | |||
| { | |||
| CarlaPlugin* const plugin(pData->plugins[i].plugin); | |||
| @@ -472,6 +472,8 @@ public: | |||
| CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode); | |||
| pData->sampleRate = fShmNonRtClientControl.readDouble(); | |||
| pData->initTime(); | |||
| if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) | |||
| return false; | |||
| @@ -57,9 +57,64 @@ void EngineInternalEvents::clear() noexcept | |||
| // ----------------------------------------------------------------------- | |||
| // InternalTime | |||
| static const float kTicksPerBeat = 1920.0f; | |||
| EngineInternalTime::EngineInternalTime() noexcept | |||
| : playing(false), | |||
| frame(0) {} | |||
| frame(0), | |||
| bpm(120.0), | |||
| sampleRate(0.0), | |||
| tick(0.0) {} | |||
| void EngineInternalTime::fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t newFrames) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),); | |||
| info.playing = playing; | |||
| info.frame = frame; | |||
| info.usecs = 0; | |||
| if (newFrames == 0) | |||
| { | |||
| info.valid = EngineTimeInfo::kValidBBT; | |||
| info.bbt.beatsPerBar = 4.0f; | |||
| info.bbt.beatType = 4.0f; | |||
| info.bbt.ticksPerBeat = kTicksPerBeat; | |||
| info.bbt.beatsPerMinute = bpm; | |||
| double abs_beat, abs_tick; | |||
| { | |||
| const double min = frame / (sampleRate * 60.0); | |||
| abs_tick = min * bpm * kTicksPerBeat; | |||
| abs_beat = abs_tick / kTicksPerBeat; | |||
| } | |||
| info.bbt.bar = abs_beat / info.bbt.beatsPerBar; | |||
| info.bbt.beat = abs_beat - (info.bbt.bar * info.bbt.beatsPerBar) + 1; | |||
| tick = abs_tick - (abs_beat * kTicksPerBeat); | |||
| info.bbt.barStartTick = info.bbt.bar * info.bbt.beatsPerBar * kTicksPerBeat; | |||
| info.bbt.bar++; | |||
| } | |||
| else | |||
| { | |||
| tick += newFrames * kTicksPerBeat * bpm / (sampleRate * 60); | |||
| while (tick >= kTicksPerBeat) | |||
| { | |||
| tick -= kTicksPerBeat; | |||
| if (++info.bbt.beat > info.bbt.beatsPerBar) | |||
| { | |||
| info.bbt.beat = 1; | |||
| ++info.bbt.bar; | |||
| info.bbt.barStartTick += info.bbt.beatsPerBar * kTicksPerBeat; | |||
| } | |||
| } | |||
| } | |||
| info.bbt.tick = (int)(tick + 0.5); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // NextAction | |||
| @@ -253,6 +308,16 @@ void CarlaEngine::ProtectedData::close() | |||
| name.clear(); | |||
| } | |||
| void CarlaEngine::ProtectedData::initTime() | |||
| { | |||
| time.playing = false; | |||
| time.frame = 0; | |||
| time.bpm = 120.0; | |||
| time.sampleRate = sampleRate; | |||
| time.tick = 0.0; | |||
| time.fillEngineTimeInfo(timeInfo, 0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| #ifndef BUILD_BRIDGE | |||
| @@ -351,13 +416,10 @@ PendingRtEventsRunner::~PendingRtEventsRunner() noexcept | |||
| { | |||
| pData->doNextPluginAction(true); | |||
| if (pData->time.playing) | |||
| pData->time.frame += pData->bufferSize; | |||
| if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) | |||
| if (pData->time.playing && pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) | |||
| { | |||
| pData->timeInfo.playing = pData->time.playing; | |||
| pData->timeInfo.frame = pData->time.frame; | |||
| pData->time.frame += pData->bufferSize; | |||
| pData->time.fillEngineTimeInfo(pData->timeInfo, pData->bufferSize); | |||
| } | |||
| } | |||
| @@ -112,9 +112,14 @@ private: | |||
| struct EngineInternalTime { | |||
| bool playing; | |||
| uint64_t frame; | |||
| double bpm; | |||
| double sampleRate; | |||
| double tick; | |||
| EngineInternalTime() noexcept; | |||
| void fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t newFrames) noexcept; | |||
| CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalTime) | |||
| }; | |||
| @@ -219,6 +224,8 @@ struct CarlaEngine::ProtectedData { | |||
| bool init(const char* const clientName); | |||
| void close(); | |||
| void initTime(); | |||
| // ------------------------------------------------------------------- | |||
| void doPluginRemove() noexcept; | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Host | |||
| * Copyright (C) 2011-2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2017 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 | |||
| @@ -953,6 +953,7 @@ public: | |||
| pData->bufferSize = jackbridge_get_buffer_size(fClient); | |||
| pData->sampleRate = jackbridge_get_sample_rate(fClient); | |||
| pData->initTime(); | |||
| jackbridge_set_thread_init_callback(fClient, carla_jack_thread_init_callback, nullptr); | |||
| jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback, this); | |||
| @@ -1117,6 +1118,7 @@ public: | |||
| fClient = client; | |||
| pData->bufferSize = jackbridge_get_buffer_size(client); | |||
| pData->sampleRate = jackbridge_get_sample_rate(client); | |||
| pData->initTime(); | |||
| jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this); | |||
| jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this); | |||
| @@ -1532,7 +1534,9 @@ protected: | |||
| pData->timeInfo.bbt.beatsPerMinute = fTransportPos.beats_per_minute; | |||
| } | |||
| else | |||
| { | |||
| pData->timeInfo.valid = 0x0; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| @@ -1545,6 +1549,8 @@ protected: | |||
| { | |||
| const PendingRtEventsRunner prt(this); | |||
| CARLA_SAFE_ASSERT_RETURN(nframes == pData->bufferSize,); | |||
| saveTransportInfo(); | |||
| #ifdef BUILD_BRIDGE | |||
| @@ -200,6 +200,7 @@ public: | |||
| pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); | |||
| pData->sampleRate = fDevice->getCurrentSampleRate(); | |||
| pData->initTime(); | |||
| pData->graph.create(static_cast<uint32_t>(inputNames.size()), static_cast<uint32_t>(outputNames.size())); | |||
| @@ -495,7 +496,7 @@ protected: | |||
| fMidiInEvents.mutex.unlock(); | |||
| } | |||
| pData->graph.process(pData, inputChannelData, outputChannelData, static_cast<uint32_t>(numSamples)); | |||
| pData->graph.process(pData, inputChannelData, outputChannelData, nframes); | |||
| fMidiOutMutex.lock(); | |||
| @@ -603,6 +603,7 @@ public: | |||
| pData->bufferSize = pHost->get_buffer_size(pHost->handle); | |||
| pData->sampleRate = pHost->get_sample_rate(pHost->handle); | |||
| pData->initTime(); | |||
| if (outChan == 0) | |||
| outChan = inChan; | |||
| @@ -282,6 +282,7 @@ public: | |||
| pData->bufferSize = bufferFrames; | |||
| pData->sampleRate = fAudio.getStreamSampleRate(); | |||
| pData->initTime(); | |||
| fAudioInCount = iParams.nChannels; | |||
| fAudioOutCount = oParams.nChannels; | |||
| @@ -51,6 +51,8 @@ public: | |||
| fParameters[kParameterMeasures] = 4.0f; | |||
| fParameters[kParameterDefLength] = 4.0f; | |||
| fParameters[kParameterQuantize] = 4.0f; | |||
| fMaxTicks = 48.0*fTimeSigNum*fParameters[kParameterMeasures] /2; // FIXME: why /2 ? | |||
| } | |||
| protected: | |||
| @@ -348,9 +350,11 @@ protected: | |||
| midiEvent.data[3] = event->data[3]; | |||
| midiEvent.size = event->size; | |||
| #ifdef DEBUG | |||
| carla_stdout("Playing at %f :: %03X:%03i:%03i", | |||
| float(double(midiEvent.time)*fTicksPerFrame), | |||
| midiEvent.data[0], midiEvent.data[1], midiEvent.data[2]); | |||
| #endif | |||
| NativePluginAndUiClass::writeMidiEvent(&midiEvent); | |||
| } | |||