|
|
@@ -82,7 +82,6 @@ public: |
|
|
|
#endif |
|
|
|
fMidiEventCount(0), |
|
|
|
fTimeInfo(), |
|
|
|
fLastTimeSpeed(0.0), |
|
|
|
fIsOffline(false), |
|
|
|
fBufferSize(0), |
|
|
|
fSampleRate(sampleRate), |
|
|
@@ -97,11 +96,7 @@ public: |
|
|
|
hide = extui_hide; |
|
|
|
|
|
|
|
CarlaString resourceDir(bundlePath); |
|
|
|
#ifdef CARLA_OS_WIN |
|
|
|
resourceDir += "\\resources\\"; |
|
|
|
#else |
|
|
|
resourceDir += "/resources/"; |
|
|
|
#endif |
|
|
|
resourceDir += CARLA_OS_SEP_STR "resources" CARLA_OS_SEP_STR; |
|
|
|
|
|
|
|
fHost.handle = this; |
|
|
|
fHost.resourceDir = resourceDir.dup(); |
|
|
@@ -164,16 +159,6 @@ public: |
|
|
|
} |
|
|
|
|
|
|
|
fUridMap = uridMap; |
|
|
|
|
|
|
|
if (fDescriptor->midiIns > 0) |
|
|
|
fUI.portOffset += desc->midiIns; |
|
|
|
else if (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) |
|
|
|
fUI.portOffset += 1; |
|
|
|
|
|
|
|
fUI.portOffset += desc->midiOuts; |
|
|
|
fUI.portOffset += 1; // freewheel |
|
|
|
fUI.portOffset += desc->audioIns; |
|
|
|
fUI.portOffset += desc->audioOuts; |
|
|
|
} |
|
|
|
|
|
|
|
~NativePlugin() |
|
|
@@ -189,7 +174,7 @@ public: |
|
|
|
|
|
|
|
bool init() |
|
|
|
{ |
|
|
|
if (fUI.portOffset == 0) |
|
|
|
if (fUridMap == nullptr) |
|
|
|
{ |
|
|
|
// host is missing features |
|
|
|
return false; |
|
|
@@ -213,6 +198,26 @@ public: |
|
|
|
carla_zeroStructs(fMidiEvents, kMaxMidiEvents*2); |
|
|
|
carla_zeroStruct(fTimeInfo); |
|
|
|
|
|
|
|
// hosts may not send all values, resulting on some invalid data |
|
|
|
fTimeInfo.bbt.bar = 1; |
|
|
|
fTimeInfo.bbt.beat = 1; |
|
|
|
fTimeInfo.bbt.tick = 0; |
|
|
|
fTimeInfo.bbt.barStartTick = 0; |
|
|
|
fTimeInfo.bbt.beatsPerBar = 4; |
|
|
|
fTimeInfo.bbt.beatType = 4; |
|
|
|
fTimeInfo.bbt.ticksPerBeat = 960.0; |
|
|
|
fTimeInfo.bbt.beatsPerMinute = 120.0; |
|
|
|
|
|
|
|
if (fDescriptor->midiIns > 0) |
|
|
|
fUI.portOffset += fDescriptor->midiIns; |
|
|
|
else if (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) |
|
|
|
fUI.portOffset += 1; |
|
|
|
|
|
|
|
fUI.portOffset += fDescriptor->midiOuts; |
|
|
|
fUI.portOffset += 1; // freewheel |
|
|
|
fUI.portOffset += fDescriptor->audioIns; |
|
|
|
fUI.portOffset += fDescriptor->audioOuts; |
|
|
|
|
|
|
|
fPorts.init(fDescriptor, fHandle); |
|
|
|
fURIs.map(fUridMap); |
|
|
|
|
|
|
@@ -285,13 +290,11 @@ public: |
|
|
|
|
|
|
|
if (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) |
|
|
|
{ |
|
|
|
LV2_ATOM_SEQUENCE_FOREACH(fPorts.eventsIn[0], iter) |
|
|
|
LV2_ATOM_SEQUENCE_FOREACH(fPorts.eventsIn[0], event) |
|
|
|
{ |
|
|
|
const LV2_Atom_Event* const event((const LV2_Atom_Event*)iter); |
|
|
|
|
|
|
|
if (event == nullptr) |
|
|
|
continue; |
|
|
|
if (event->body.type != fURIs.atomBlank) |
|
|
|
if (event->body.type != fURIs.atomBlank && event->body.type != fURIs.atomObject) |
|
|
|
continue; |
|
|
|
|
|
|
|
const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body); |
|
|
@@ -299,153 +302,186 @@ public: |
|
|
|
if (obj->body.otype != fURIs.timePos) |
|
|
|
continue; |
|
|
|
|
|
|
|
LV2_Atom* bar = nullptr; |
|
|
|
LV2_Atom* barBeat = nullptr; |
|
|
|
LV2_Atom* beat = nullptr; |
|
|
|
LV2_Atom* bar = nullptr; |
|
|
|
LV2_Atom* barBeat = nullptr; |
|
|
|
LV2_Atom* beatUnit = nullptr; |
|
|
|
LV2_Atom* beatsPerBar = nullptr; |
|
|
|
LV2_Atom* beatsPerMinute = nullptr; |
|
|
|
LV2_Atom* ticksPerBeat = nullptr; |
|
|
|
LV2_Atom* frame = nullptr; |
|
|
|
LV2_Atom* speed = nullptr; |
|
|
|
LV2_Atom* ticksPerBeat = nullptr; |
|
|
|
|
|
|
|
lv2_atom_object_get(obj, |
|
|
|
fURIs.timeBar, &bar, |
|
|
|
fURIs.timeBarBeat, &barBeat, |
|
|
|
fURIs.timeBeat, &beat, |
|
|
|
fURIs.timeBeatUnit, &beatUnit, |
|
|
|
fURIs.timeBeatsPerBar, &beatsPerBar, |
|
|
|
fURIs.timeBeatsPerMinute, &beatsPerMinute, |
|
|
|
fURIs.timeTicksPerBeat, &ticksPerBeat, |
|
|
|
fURIs.timeFrame, &frame, |
|
|
|
fURIs.timeSpeed, &speed, |
|
|
|
fURIs.timeTicksPerBeat, &ticksPerBeat, |
|
|
|
nullptr); |
|
|
|
|
|
|
|
// need to handle this first as other values depend on it |
|
|
|
if (ticksPerBeat != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (ticksPerBeat->type == fURIs.atomDouble) |
|
|
|
fLastPositionData.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body; |
|
|
|
else if (ticksPerBeat->type == fURIs.atomFloat) |
|
|
|
fLastPositionData.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body; |
|
|
|
else if (ticksPerBeat->type == fURIs.atomInt) |
|
|
|
fLastPositionData.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body; |
|
|
|
else if (ticksPerBeat->type == fURIs.atomLong) |
|
|
|
fLastPositionData.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 ticksPerBeat value type"); |
|
|
|
|
|
|
|
if (fLastPositionData.ticksPerBeat > 0) |
|
|
|
fTimeInfo.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat; |
|
|
|
} |
|
|
|
|
|
|
|
// same |
|
|
|
if (speed != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (speed->type == fURIs.atomDouble) |
|
|
|
fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body; |
|
|
|
else if (speed->type == fURIs.atomFloat) |
|
|
|
fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body; |
|
|
|
else if (speed->type == fURIs.atomInt) |
|
|
|
fLastPositionData.speed = ((LV2_Atom_Int*)speed)->body; |
|
|
|
else if (speed->type == fURIs.atomLong) |
|
|
|
fLastPositionData.speed = ((LV2_Atom_Long*)speed)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 speed value type"); |
|
|
|
|
|
|
|
fTimeInfo.playing = carla_isNotZero(fLastPositionData.speed); |
|
|
|
} |
|
|
|
|
|
|
|
if (bar != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (bar->type == fURIs.atomDouble) |
|
|
|
fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Double*)bar)->body + 1.0); |
|
|
|
fLastPositionData.bar = ((LV2_Atom_Double*)bar)->body; |
|
|
|
else if (bar->type == fURIs.atomFloat) |
|
|
|
fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Float*)bar)->body + 1.0f); |
|
|
|
fLastPositionData.bar = ((LV2_Atom_Float*)bar)->body; |
|
|
|
else if (bar->type == fURIs.atomInt) |
|
|
|
fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Int*)bar)->body + 1); |
|
|
|
fLastPositionData.bar = ((LV2_Atom_Int*)bar)->body; |
|
|
|
else if (bar->type == fURIs.atomLong) |
|
|
|
fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Long*)bar)->body + 1); |
|
|
|
fLastPositionData.bar = ((LV2_Atom_Long*)bar)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 bar value type"); |
|
|
|
} |
|
|
|
|
|
|
|
if (ticksPerBeat != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (ticksPerBeat->type == fURIs.atomDouble) |
|
|
|
fTimeInfo.bbt.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body; |
|
|
|
else if (ticksPerBeat->type == fURIs.atomFloat) |
|
|
|
fTimeInfo.bbt.ticksPerBeat = static_cast<double>(((LV2_Atom_Float*)ticksPerBeat)->body); |
|
|
|
else if (ticksPerBeat->type == fURIs.atomInt) |
|
|
|
fTimeInfo.bbt.ticksPerBeat = static_cast<double>(((LV2_Atom_Int*)ticksPerBeat)->body); |
|
|
|
else if (ticksPerBeat->type == fURIs.atomLong) |
|
|
|
fTimeInfo.bbt.ticksPerBeat = static_cast<double>(((LV2_Atom_Long*)ticksPerBeat)->body); |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 ticksPerBeat value type"); |
|
|
|
if (fLastPositionData.bar >= 0) |
|
|
|
fTimeInfo.bbt.bar = fLastPositionData.bar + 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (barBeat != nullptr) |
|
|
|
{ |
|
|
|
double barBeatValue = 0.0; |
|
|
|
|
|
|
|
/**/ if (barBeat->type == fURIs.atomDouble) |
|
|
|
barBeatValue = ((LV2_Atom_Double*)barBeat)->body; |
|
|
|
fLastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body; |
|
|
|
else if (barBeat->type == fURIs.atomFloat) |
|
|
|
barBeatValue = static_cast<double>(((LV2_Atom_Float*)barBeat)->body); |
|
|
|
fLastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body; |
|
|
|
else if (barBeat->type == fURIs.atomInt) |
|
|
|
barBeatValue = static_cast<double>(((LV2_Atom_Int*)barBeat)->body); |
|
|
|
fLastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body; |
|
|
|
else if (barBeat->type == fURIs.atomLong) |
|
|
|
barBeatValue = static_cast<double>(((LV2_Atom_Long*)barBeat)->body); |
|
|
|
fLastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 barBeat value type"); |
|
|
|
|
|
|
|
const double rest = std::fmod(barBeatValue, 1.0); |
|
|
|
fTimeInfo.bbt.beat = static_cast<int32_t>(barBeatValue-rest+1.0); |
|
|
|
fTimeInfo.bbt.tick = static_cast<int32_t>(rest*fTimeInfo.bbt.ticksPerBeat+0.5); |
|
|
|
} |
|
|
|
// barBeat includes beat |
|
|
|
else if (beat != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (beat->type == fURIs.atomDouble) |
|
|
|
fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Double*)beat)->body + 1.0); |
|
|
|
else if (beat->type == fURIs.atomFloat) |
|
|
|
fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Float*)beat)->body + 1.0f); |
|
|
|
else if (beat->type == fURIs.atomInt) |
|
|
|
fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Int*)beat)->body + 1); |
|
|
|
else if (beat->type == fURIs.atomLong) |
|
|
|
fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Long*)beat)->body + 1); |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 beat value type"); |
|
|
|
if (fLastPositionData.barBeat >= 0.0f) |
|
|
|
{ |
|
|
|
const double rest = std::fmod(fLastPositionData.barBeat, 1.0); |
|
|
|
fTimeInfo.bbt.beat = fLastPositionData.barBeat-rest+1.0; |
|
|
|
fTimeInfo.bbt.tick = rest*fTimeInfo.bbt.ticksPerBeat+0.5; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (beatUnit != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (beatUnit->type == fURIs.atomDouble) |
|
|
|
fTimeInfo.bbt.beatType = static_cast<float>(((LV2_Atom_Double*)beatUnit)->body); |
|
|
|
fLastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body; |
|
|
|
else if (beatUnit->type == fURIs.atomFloat) |
|
|
|
fTimeInfo.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body; |
|
|
|
fLastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body; |
|
|
|
else if (beatUnit->type == fURIs.atomInt) |
|
|
|
fTimeInfo.bbt.beatType = static_cast<float>(((LV2_Atom_Int*)beatUnit)->body); |
|
|
|
fLastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body; |
|
|
|
else if (beatUnit->type == fURIs.atomLong) |
|
|
|
fTimeInfo.bbt.beatType = static_cast<float>(((LV2_Atom_Long*)beatUnit)->body); |
|
|
|
fLastPositionData.beatUnit = ((LV2_Atom_Long*)beatUnit)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 beatUnit value type"); |
|
|
|
|
|
|
|
if (fLastPositionData.beatUnit > 0) |
|
|
|
fTimeInfo.bbt.beatType = fLastPositionData.beatUnit; |
|
|
|
} |
|
|
|
|
|
|
|
if (beatsPerBar != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (beatsPerBar->type == fURIs.atomDouble) |
|
|
|
fTimeInfo.bbt.beatsPerBar = static_cast<float>(((LV2_Atom_Double*)beatsPerBar)->body); |
|
|
|
fLastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body; |
|
|
|
else if (beatsPerBar->type == fURIs.atomFloat) |
|
|
|
fTimeInfo.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body; |
|
|
|
fLastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body; |
|
|
|
else if (beatsPerBar->type == fURIs.atomInt) |
|
|
|
fTimeInfo.bbt.beatsPerBar = static_cast<float>(((LV2_Atom_Int*)beatsPerBar)->body); |
|
|
|
fLastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body; |
|
|
|
else if (beatsPerBar->type == fURIs.atomLong) |
|
|
|
fTimeInfo.bbt.beatsPerBar = static_cast<float>(((LV2_Atom_Long*)beatsPerBar)->body); |
|
|
|
fLastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 beatsPerBar value type"); |
|
|
|
|
|
|
|
if (fLastPositionData.beatsPerBar > 0.0f) |
|
|
|
fTimeInfo.bbt.beatsPerBar = fLastPositionData.beatsPerBar; |
|
|
|
} |
|
|
|
|
|
|
|
if (beatsPerMinute != nullptr) |
|
|
|
{ |
|
|
|
/**/ if (beatsPerMinute->type == fURIs.atomDouble) |
|
|
|
fTimeInfo.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body; |
|
|
|
fLastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body; |
|
|
|
else if (beatsPerMinute->type == fURIs.atomFloat) |
|
|
|
fTimeInfo.bbt.beatsPerMinute = static_cast<double>(((LV2_Atom_Float*)beatsPerMinute)->body); |
|
|
|
fLastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body; |
|
|
|
else if (beatsPerMinute->type == fURIs.atomInt) |
|
|
|
fTimeInfo.bbt.beatsPerMinute = static_cast<double>(((LV2_Atom_Int*)beatsPerMinute)->body); |
|
|
|
fLastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body; |
|
|
|
else if (beatsPerMinute->type == fURIs.atomLong) |
|
|
|
fTimeInfo.bbt.beatsPerMinute = static_cast<double>(((LV2_Atom_Long*)beatsPerMinute)->body); |
|
|
|
fLastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 beatsPerMinute value type"); |
|
|
|
} |
|
|
|
|
|
|
|
fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat*fTimeInfo.bbt.beatsPerBar*(fTimeInfo.bbt.bar-1); |
|
|
|
if (fLastPositionData.beatsPerMinute > 0.0f) |
|
|
|
{ |
|
|
|
fTimeInfo.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute; |
|
|
|
|
|
|
|
if (frame != nullptr && frame->type == fURIs.atomLong) |
|
|
|
fTimeInfo.frame = static_cast<uint64_t>(((LV2_Atom_Long*)frame)->body); |
|
|
|
if (carla_isNotZero(fLastPositionData.speed)) |
|
|
|
fTimeInfo.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (speed != nullptr && speed->type == fURIs.atomFloat) |
|
|
|
if (frame != nullptr) |
|
|
|
{ |
|
|
|
fLastTimeSpeed = ((LV2_Atom_Float*)speed)->body; |
|
|
|
fTimeInfo.playing = carla_isEqual(fLastTimeSpeed, 1.0); |
|
|
|
/**/ if (frame->type == fURIs.atomDouble) |
|
|
|
fLastPositionData.frame = ((LV2_Atom_Double*)frame)->body; |
|
|
|
else if (frame->type == fURIs.atomFloat) |
|
|
|
fLastPositionData.frame = ((LV2_Atom_Float*)frame)->body; |
|
|
|
else if (frame->type == fURIs.atomInt) |
|
|
|
fLastPositionData.frame = ((LV2_Atom_Int*)frame)->body; |
|
|
|
else if (frame->type == fURIs.atomLong) |
|
|
|
fLastPositionData.frame = ((LV2_Atom_Long*)frame)->body; |
|
|
|
else |
|
|
|
carla_stderr("Unknown lv2 frame value type"); |
|
|
|
|
|
|
|
if (fLastPositionData.frame >= 0) |
|
|
|
fTimeInfo.frame = fLastPositionData.frame; |
|
|
|
} |
|
|
|
|
|
|
|
fTimeInfo.bbt.valid = (beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr); |
|
|
|
fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat* |
|
|
|
fTimeInfo.bbt.beatsPerBar* |
|
|
|
(fTimeInfo.bbt.bar-1); |
|
|
|
|
|
|
|
fTimeInfo.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 && |
|
|
|
fLastPositionData.beatUnit > 0 && |
|
|
|
fLastPositionData.beatsPerBar > 0.0f); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (uint32_t i=0; i < fDescriptor->midiIns; ++i) |
|
|
|
{ |
|
|
|
LV2_ATOM_SEQUENCE_FOREACH(fPorts.eventsIn[i], iter) |
|
|
|
LV2_ATOM_SEQUENCE_FOREACH(fPorts.eventsIn[i], event) |
|
|
|
{ |
|
|
|
const LV2_Atom_Event* const event((const LV2_Atom_Event*)iter); |
|
|
|
|
|
|
|
if (event == nullptr) |
|
|
|
continue; |
|
|
|
if (event->body.type != fURIs.midiEvent) |
|
|
@@ -476,37 +512,56 @@ public: |
|
|
|
fDescriptor->process(fHandle, const_cast<float**>(fPorts.audioIns), fPorts.audioOuts, frames, fMidiEvents, fMidiEventCount); |
|
|
|
|
|
|
|
// update timePos for next callback |
|
|
|
if (carla_isNotEqual(fLastTimeSpeed, 0.0)) |
|
|
|
if (carla_isNotZero(fLastPositionData.speed)) |
|
|
|
{ |
|
|
|
const double newFrames = fLastTimeSpeed*frames; |
|
|
|
if (fLastPositionData.speed > 0.0) |
|
|
|
{ |
|
|
|
// playing forwards |
|
|
|
fLastPositionData.frame += frames; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// playing backwards |
|
|
|
fLastPositionData.frame -= frames; |
|
|
|
|
|
|
|
if (fLastPositionData.frame < 0) |
|
|
|
fLastPositionData.frame = 0; |
|
|
|
} |
|
|
|
|
|
|
|
fTimeInfo.frame += static_cast<uint64_t>(newFrames); |
|
|
|
fTimeInfo.frame = fLastPositionData.frame; |
|
|
|
|
|
|
|
if (fTimeInfo.bbt.valid) |
|
|
|
{ |
|
|
|
const double samplesPerBeat = 60.0 / fTimeInfo.bbt.beatsPerMinute * fSampleRate; |
|
|
|
const double ticksPerSample = fTimeInfo.bbt.ticksPerBeat / samplesPerBeat; |
|
|
|
|
|
|
|
double newTickPos = double(fTimeInfo.bbt.tick) + ticksPerSample*newFrames; |
|
|
|
double newBeatPos = double(fTimeInfo.bbt.beat)-1.0; |
|
|
|
double newBarPos = double(fTimeInfo.bbt.bar)-1.0; |
|
|
|
const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed; |
|
|
|
const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute; |
|
|
|
const double addedBarBeats = double(frames) / framesPerBeat; |
|
|
|
|
|
|
|
for (; newTickPos >= fTimeInfo.bbt.ticksPerBeat;) |
|
|
|
if (fLastPositionData.barBeat >= 0.0f) |
|
|
|
{ |
|
|
|
++newBeatPos; |
|
|
|
newTickPos -= fTimeInfo.bbt.ticksPerBeat; |
|
|
|
} |
|
|
|
fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+addedBarBeats, |
|
|
|
fLastPositionData.beatsPerBar); |
|
|
|
|
|
|
|
for (; newBeatPos >= fTimeInfo.bbt.beatsPerBar;) |
|
|
|
{ |
|
|
|
++newBarPos; |
|
|
|
newBeatPos -= fTimeInfo.bbt.beatsPerBar; |
|
|
|
const double rest = std::fmod(fLastPositionData.barBeat, 1.0); |
|
|
|
fTimeInfo.bbt.beat = fLastPositionData.barBeat-rest+1.0; |
|
|
|
fTimeInfo.bbt.tick = rest*fTimeInfo.bbt.ticksPerBeat+0.5; |
|
|
|
|
|
|
|
if (fLastPositionData.bar >= 0) |
|
|
|
{ |
|
|
|
fLastPositionData.bar += std::floor((fLastPositionData.barBeat+addedBarBeats)/ |
|
|
|
fLastPositionData.beatsPerBar); |
|
|
|
|
|
|
|
if (fLastPositionData.bar < 0) |
|
|
|
fLastPositionData.bar = 0; |
|
|
|
|
|
|
|
fTimeInfo.bbt.bar = fLastPositionData.bar + 1; |
|
|
|
|
|
|
|
fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat* |
|
|
|
fTimeInfo.bbt.beatsPerBar* |
|
|
|
(fTimeInfo.bbt.bar-1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fTimeInfo.bbt.bar = static_cast<int32_t>(newBarPos+1.0); |
|
|
|
fTimeInfo.bbt.beat = static_cast<int32_t>(newBeatPos+1.0); |
|
|
|
fTimeInfo.bbt.tick = static_cast<int32_t>(newTickPos); |
|
|
|
fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat*fTimeInfo.bbt.beatsPerBar*(fTimeInfo.bbt.bar-1); |
|
|
|
fTimeInfo.bbt.beatsPerMinute = std::abs(beatsPerMinute); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -988,7 +1043,6 @@ private: |
|
|
|
uint32_t fMidiEventCount; |
|
|
|
NativeMidiEvent fMidiEvents[kMaxMidiEvents*2]; |
|
|
|
NativeTimeInfo fTimeInfo; |
|
|
|
double fLastTimeSpeed; |
|
|
|
|
|
|
|
// Lv2 host data |
|
|
|
bool fIsOffline; |
|
|
@@ -997,8 +1051,31 @@ private: |
|
|
|
|
|
|
|
const LV2_URID_Map* fUridMap; |
|
|
|
|
|
|
|
struct Lv2PositionData { |
|
|
|
int64_t bar; |
|
|
|
float barBeat; |
|
|
|
uint32_t beatUnit; |
|
|
|
float beatsPerBar; |
|
|
|
float beatsPerMinute; |
|
|
|
int64_t frame; |
|
|
|
double speed; |
|
|
|
int64_t ticksPerBeat; |
|
|
|
|
|
|
|
Lv2PositionData() |
|
|
|
: bar(-1), |
|
|
|
barBeat(-1.0f), |
|
|
|
beatUnit(0), |
|
|
|
beatsPerBar(0.0f), |
|
|
|
beatsPerMinute(0.0f), |
|
|
|
frame(-1), |
|
|
|
speed(0.0), |
|
|
|
ticksPerBeat(-1) {} |
|
|
|
|
|
|
|
} fLastPositionData; |
|
|
|
|
|
|
|
struct URIDs { |
|
|
|
LV2_URID atomBlank; |
|
|
|
LV2_URID atomObject; |
|
|
|
LV2_URID atomDouble; |
|
|
|
LV2_URID atomFloat; |
|
|
|
LV2_URID atomInt; |
|
|
@@ -1019,6 +1096,7 @@ private: |
|
|
|
|
|
|
|
URIDs() |
|
|
|
: atomBlank(0), |
|
|
|
atomObject(0), |
|
|
|
atomDouble(0), |
|
|
|
atomFloat(0), |
|
|
|
atomInt(0), |
|
|
@@ -1040,6 +1118,7 @@ private: |
|
|
|
void map(const LV2_URID_Map* const uridMap) |
|
|
|
{ |
|
|
|
atomBlank = uridMap->map(uridMap->handle, LV2_ATOM__Blank); |
|
|
|
atomObject = uridMap->map(uridMap->handle, LV2_ATOM__Object); |
|
|
|
atomDouble = uridMap->map(uridMap->handle, LV2_ATOM__Double); |
|
|
|
atomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float); |
|
|
|
atomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int); |
|
|
|