@@ -1341,16 +1341,19 @@ void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr) | |||||
void CarlaEngine::transportPlay() noexcept | void CarlaEngine::transportPlay() noexcept | ||||
{ | { | ||||
pData->time.playing = true; | pData->time.playing = true; | ||||
pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||||
} | } | ||||
void CarlaEngine::transportPause() noexcept | void CarlaEngine::transportPause() noexcept | ||||
{ | { | ||||
pData->time.playing = false; | pData->time.playing = false; | ||||
pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||||
} | } | ||||
void CarlaEngine::transportRelocate(const uint64_t frame) noexcept | void CarlaEngine::transportRelocate(const uint64_t frame) noexcept | ||||
{ | { | ||||
pData->time.frame = frame; | pData->time.frame = frame; | ||||
pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||||
} | } | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -1664,6 +1667,9 @@ void CarlaEngine::sampleRateChanged(const double newSampleRate) | |||||
} | } | ||||
#endif | #endif | ||||
pData->time.sampleRate = newSampleRate; | |||||
pData->time.fillEngineTimeInfo(pData->timeInfo, 0); | |||||
for (uint i=0; i < pData->curPluginCount; ++i) | for (uint i=0; i < pData->curPluginCount; ++i) | ||||
{ | { | ||||
CarlaPlugin* const plugin(pData->plugins[i].plugin); | CarlaPlugin* const plugin(pData->plugins[i].plugin); | ||||
@@ -472,6 +472,8 @@ public: | |||||
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode); | CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode); | ||||
pData->sampleRate = fShmNonRtClientControl.readDouble(); | pData->sampleRate = fShmNonRtClientControl.readDouble(); | ||||
pData->initTime(); | |||||
if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) | if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) | ||||
return false; | return false; | ||||
@@ -57,9 +57,64 @@ void EngineInternalEvents::clear() noexcept | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// InternalTime | // InternalTime | ||||
static const float kTicksPerBeat = 1920.0f; | |||||
EngineInternalTime::EngineInternalTime() noexcept | EngineInternalTime::EngineInternalTime() noexcept | ||||
: playing(false), | : 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 | // NextAction | ||||
@@ -253,6 +308,16 @@ void CarlaEngine::ProtectedData::close() | |||||
name.clear(); | 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 | #ifndef BUILD_BRIDGE | ||||
@@ -351,13 +416,10 @@ PendingRtEventsRunner::~PendingRtEventsRunner() noexcept | |||||
{ | { | ||||
pData->doNextPluginAction(true); | 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 { | struct EngineInternalTime { | ||||
bool playing; | bool playing; | ||||
uint64_t frame; | uint64_t frame; | ||||
double bpm; | |||||
double sampleRate; | |||||
double tick; | |||||
EngineInternalTime() noexcept; | EngineInternalTime() noexcept; | ||||
void fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t newFrames) noexcept; | |||||
CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalTime) | CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalTime) | ||||
}; | }; | ||||
@@ -219,6 +224,8 @@ struct CarlaEngine::ProtectedData { | |||||
bool init(const char* const clientName); | bool init(const char* const clientName); | ||||
void close(); | void close(); | ||||
void initTime(); | |||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
void doPluginRemove() noexcept; | void doPluginRemove() noexcept; | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* Carla Plugin Host | * 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 | * This program is free software; you can redistribute it and/or | ||||
* modify it under the terms of the GNU General Public License as | * 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->bufferSize = jackbridge_get_buffer_size(fClient); | ||||
pData->sampleRate = jackbridge_get_sample_rate(fClient); | pData->sampleRate = jackbridge_get_sample_rate(fClient); | ||||
pData->initTime(); | |||||
jackbridge_set_thread_init_callback(fClient, carla_jack_thread_init_callback, nullptr); | jackbridge_set_thread_init_callback(fClient, carla_jack_thread_init_callback, nullptr); | ||||
jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback, this); | jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback, this); | ||||
@@ -1117,6 +1118,7 @@ public: | |||||
fClient = client; | fClient = client; | ||||
pData->bufferSize = jackbridge_get_buffer_size(client); | pData->bufferSize = jackbridge_get_buffer_size(client); | ||||
pData->sampleRate = jackbridge_get_sample_rate(client); | pData->sampleRate = jackbridge_get_sample_rate(client); | ||||
pData->initTime(); | |||||
jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this); | jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this); | ||||
jackbridge_set_sample_rate_callback(client, carla_jack_srate_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; | pData->timeInfo.bbt.beatsPerMinute = fTransportPos.beats_per_minute; | ||||
} | } | ||||
else | else | ||||
{ | |||||
pData->timeInfo.valid = 0x0; | pData->timeInfo.valid = 0x0; | ||||
} | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -1545,6 +1549,8 @@ protected: | |||||
{ | { | ||||
const PendingRtEventsRunner prt(this); | const PendingRtEventsRunner prt(this); | ||||
CARLA_SAFE_ASSERT_RETURN(nframes == pData->bufferSize,); | |||||
saveTransportInfo(); | saveTransportInfo(); | ||||
#ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
@@ -200,6 +200,7 @@ public: | |||||
pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); | pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); | ||||
pData->sampleRate = fDevice->getCurrentSampleRate(); | pData->sampleRate = fDevice->getCurrentSampleRate(); | ||||
pData->initTime(); | |||||
pData->graph.create(static_cast<uint32_t>(inputNames.size()), static_cast<uint32_t>(outputNames.size())); | pData->graph.create(static_cast<uint32_t>(inputNames.size()), static_cast<uint32_t>(outputNames.size())); | ||||
@@ -495,7 +496,7 @@ protected: | |||||
fMidiInEvents.mutex.unlock(); | fMidiInEvents.mutex.unlock(); | ||||
} | } | ||||
pData->graph.process(pData, inputChannelData, outputChannelData, static_cast<uint32_t>(numSamples)); | |||||
pData->graph.process(pData, inputChannelData, outputChannelData, nframes); | |||||
fMidiOutMutex.lock(); | fMidiOutMutex.lock(); | ||||
@@ -603,6 +603,7 @@ public: | |||||
pData->bufferSize = pHost->get_buffer_size(pHost->handle); | pData->bufferSize = pHost->get_buffer_size(pHost->handle); | ||||
pData->sampleRate = pHost->get_sample_rate(pHost->handle); | pData->sampleRate = pHost->get_sample_rate(pHost->handle); | ||||
pData->initTime(); | |||||
if (outChan == 0) | if (outChan == 0) | ||||
outChan = inChan; | outChan = inChan; | ||||
@@ -282,6 +282,7 @@ public: | |||||
pData->bufferSize = bufferFrames; | pData->bufferSize = bufferFrames; | ||||
pData->sampleRate = fAudio.getStreamSampleRate(); | pData->sampleRate = fAudio.getStreamSampleRate(); | ||||
pData->initTime(); | |||||
fAudioInCount = iParams.nChannels; | fAudioInCount = iParams.nChannels; | ||||
fAudioOutCount = oParams.nChannels; | fAudioOutCount = oParams.nChannels; | ||||
@@ -51,6 +51,8 @@ public: | |||||
fParameters[kParameterMeasures] = 4.0f; | fParameters[kParameterMeasures] = 4.0f; | ||||
fParameters[kParameterDefLength] = 4.0f; | fParameters[kParameterDefLength] = 4.0f; | ||||
fParameters[kParameterQuantize] = 4.0f; | fParameters[kParameterQuantize] = 4.0f; | ||||
fMaxTicks = 48.0*fTimeSigNum*fParameters[kParameterMeasures] /2; // FIXME: why /2 ? | |||||
} | } | ||||
protected: | protected: | ||||
@@ -348,9 +350,11 @@ protected: | |||||
midiEvent.data[3] = event->data[3]; | midiEvent.data[3] = event->data[3]; | ||||
midiEvent.size = event->size; | midiEvent.size = event->size; | ||||
#ifdef DEBUG | |||||
carla_stdout("Playing at %f :: %03X:%03i:%03i", | carla_stdout("Playing at %f :: %03X:%03i:%03i", | ||||
float(double(midiEvent.time)*fTicksPerFrame), | float(double(midiEvent.time)*fTicksPerFrame), | ||||
midiEvent.data[0], midiEvent.data[1], midiEvent.data[2]); | midiEvent.data[0], midiEvent.data[1], midiEvent.data[2]); | ||||
#endif | |||||
NativePluginAndUiClass::writeMidiEvent(&midiEvent); | NativePluginAndUiClass::writeMidiEvent(&midiEvent); | ||||
} | } | ||||