commit 4e067e7ae3ed4367eebad1c6ac0997ab6c0f8d9a
parent a02cdf7ace1bb95d6b6e5ad34a5363f3c5ffd931
Author: falkTX <falktx@gmail.com>
Date: Sat, 13 Jun 2015 02:58:28 +0200
Rework LV2 time position, seems to work nicely now
Diffstat:
1 file changed, 163 insertions(+), 95 deletions(-)
diff --git a/distrho/src/DistrhoPluginLV2.cpp b/distrho/src/DistrhoPluginLV2.cpp
@@ -40,10 +40,6 @@
# error DISTRHO_PLUGIN_URI undefined!
#endif
-#if DISTRHO_PLUGIN_WANT_TIMEPOS
-# warning LV2 TimePos still TODO
-#endif
-
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
@@ -61,9 +57,6 @@ public:
fLastControlValues(nullptr),
fSampleRate(sampleRate),
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT
-# if DISTRHO_PLUGIN_WANT_TIMEPOS
- fLastTimeSpeed(0.0),
-# endif
fURIDs(uridMap),
#endif
fUridMap(uridMap),
@@ -133,8 +126,7 @@ public:
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
- // hosts may not send all values, resulting on some invalid ones
- fTimePosition.bbt.valid = false;
+ // hosts may not send all values, resulting on some invalid data
fTimePosition.bbt.bar = 1;
fTimePosition.bbt.beat = 1;
fTimePosition.bbt.tick = 0;
@@ -311,142 +303,178 @@ public:
LV2_Atom* bar = nullptr;
LV2_Atom* barBeat = nullptr;
- LV2_Atom* beat = 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,
fURIDs.timeBar, &bar,
fURIDs.timeBarBeat, &barBeat,
- fURIDs.timeBeat, &beat,
fURIDs.timeBeatUnit, &beatUnit,
fURIDs.timeBeatsPerBar, &beatsPerBar,
fURIDs.timeBeatsPerMinute, &beatsPerMinute,
- fURIDs.timeTicksPerBeat, &ticksPerBeat,
fURIDs.timeFrame, &frame,
fURIDs.timeSpeed, &speed,
+ fURIDs.timeTicksPerBeat, &ticksPerBeat,
nullptr);
+ // need to handle this first as other values depend on it
+ if (ticksPerBeat != nullptr)
+ {
+ /**/ if (ticksPerBeat->type == fURIDs.atomDouble)
+ fLastPositionData.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body;
+ else if (ticksPerBeat->type == fURIDs.atomFloat)
+ fLastPositionData.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body;
+ else if (ticksPerBeat->type == fURIDs.atomInt)
+ fLastPositionData.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body;
+ else if (ticksPerBeat->type == fURIDs.atomLong)
+ fLastPositionData.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body;
+ else
+ d_stderr("Unknown lv2 ticksPerBeat value type");
+
+ if (fLastPositionData.ticksPerBeat > 0)
+ fTimePosition.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat;
+ }
+
+ // same
+ if (speed != nullptr)
+ {
+ /**/ if (speed->type == fURIDs.atomDouble)
+ fLastPositionData.speed = ((LV2_Atom_Double*)speed)->body;
+ else if (speed->type == fURIDs.atomFloat)
+ fLastPositionData.speed = ((LV2_Atom_Float*)speed)->body;
+ else if (speed->type == fURIDs.atomInt)
+ fLastPositionData.speed = ((LV2_Atom_Int*)speed)->body;
+ else if (speed->type == fURIDs.atomLong)
+ fLastPositionData.speed = ((LV2_Atom_Long*)speed)->body;
+ else
+ d_stderr("Unknown lv2 speed value type");
+
+ fTimePosition.playing = d_isNotZero(fLastPositionData.speed);
+ }
+
if (bar != nullptr)
{
/**/ if (bar->type == fURIDs.atomDouble)
- fTimePosition.bbt.bar = ((LV2_Atom_Double*)bar)->body + 1.0;
+ fLastPositionData.bar = ((LV2_Atom_Double*)bar)->body;
else if (bar->type == fURIDs.atomFloat)
- fTimePosition.bbt.bar = ((LV2_Atom_Float*)bar)->body + 1.0f;
+ fLastPositionData.bar = ((LV2_Atom_Float*)bar)->body;
else if (bar->type == fURIDs.atomInt)
- fTimePosition.bbt.bar = ((LV2_Atom_Int*)bar)->body + 1;
+ fLastPositionData.bar = ((LV2_Atom_Int*)bar)->body;
else if (bar->type == fURIDs.atomLong)
- fTimePosition.bbt.bar = ((LV2_Atom_Long*)bar)->body + 1;
+ fLastPositionData.bar = ((LV2_Atom_Long*)bar)->body;
else
d_stderr("Unknown lv2 bar value type");
- }
- if (ticksPerBeat != nullptr)
- {
- /**/ if (ticksPerBeat->type == fURIDs.atomDouble)
- fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body;
- else if (ticksPerBeat->type == fURIDs.atomFloat)
- fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body;
- else if (ticksPerBeat->type == fURIDs.atomInt)
- fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body;
- else if (ticksPerBeat->type == fURIDs.atomLong)
- fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body;
- else
- d_stderr("Unknown lv2 ticksPerBeat value type");
+ if (fLastPositionData.bar >= 0)
+ fTimePosition.bbt.bar = fLastPositionData.bar + 1;
}
if (barBeat != nullptr)
{
- double barBeatValue = 0.0;
-
/**/ if (barBeat->type == fURIDs.atomDouble)
- barBeatValue = ((LV2_Atom_Double*)barBeat)->body;
+ fLastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body;
else if (barBeat->type == fURIDs.atomFloat)
- barBeatValue = ((LV2_Atom_Float*)barBeat)->body;
+ fLastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body;
else if (barBeat->type == fURIDs.atomInt)
- barBeatValue = ((LV2_Atom_Int*)barBeat)->body;
+ fLastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body;
else if (barBeat->type == fURIDs.atomLong)
- barBeatValue = ((LV2_Atom_Long*)barBeat)->body;
+ fLastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body;
else
d_stderr("Unknown lv2 barBeat value type");
- const double rest = std::fmod(barBeatValue, 1.0);
- fTimePosition.bbt.beat = barBeatValue-rest+1.0;
- fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
- }
- // barBeat includes beat
- else if (beat != nullptr)
- {
- /**/ if (beat->type == fURIDs.atomDouble)
- fTimePosition.bbt.beat = ((LV2_Atom_Double*)beat)->body + 1.0;
- else if (beat->type == fURIDs.atomFloat)
- fTimePosition.bbt.beat = ((LV2_Atom_Float*)beat)->body + 1.0f;
- else if (beat->type == fURIDs.atomInt)
- fTimePosition.bbt.beat = ((LV2_Atom_Int*)beat)->body + 1;
- else if (beat->type == fURIDs.atomLong)
- fTimePosition.bbt.beat = ((LV2_Atom_Long*)beat)->body + 1;
- else
- d_stderr("Unknown lv2 beat value type");
+ if (fLastPositionData.barBeat >= 0.0f)
+ {
+ const double rest = std::fmod(fLastPositionData.barBeat, 1.0);
+ fTimePosition.bbt.beat = fLastPositionData.barBeat-rest+1.0;
+ fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
+ }
}
if (beatUnit != nullptr)
{
/**/ if (beatUnit->type == fURIDs.atomDouble)
- fTimePosition.bbt.beatType = ((LV2_Atom_Double*)beatUnit)->body;
+ fLastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomFloat)
- fTimePosition.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body;
+ fLastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomInt)
- fTimePosition.bbt.beatType = ((LV2_Atom_Int*)beatUnit)->body;
+ fLastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body;
else if (beatUnit->type == fURIDs.atomLong)
- fTimePosition.bbt.beatType = ((LV2_Atom_Long*)beatUnit)->body;
+ fLastPositionData.beatUnit = ((LV2_Atom_Long*)beatUnit)->body;
else
d_stderr("Unknown lv2 beatUnit value type");
+
+ if (fLastPositionData.beatUnit > 0)
+ fTimePosition.bbt.beatType = fLastPositionData.beatUnit;
}
if (beatsPerBar != nullptr)
{
/**/ if (beatsPerBar->type == fURIDs.atomDouble)
- fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
+ fLastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomFloat)
- fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
+ fLastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomInt)
- fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
+ fLastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
else if (beatsPerBar->type == fURIDs.atomLong)
- fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
+ fLastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
else
d_stderr("Unknown lv2 beatsPerBar value type");
+
+ if (fLastPositionData.beatsPerBar > 0.0f)
+ fTimePosition.bbt.beatsPerBar = fLastPositionData.beatsPerBar;
}
if (beatsPerMinute != nullptr)
{
/**/ if (beatsPerMinute->type == fURIDs.atomDouble)
- fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
+ fLastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomFloat)
- fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
+ fLastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomInt)
- fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
+ fLastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
else if (beatsPerMinute->type == fURIDs.atomLong)
- fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
+ fLastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
else
d_stderr("Unknown lv2 beatsPerMinute value type");
- }
- fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1);
+ if (fLastPositionData.beatsPerMinute > 0.0f)
+ {
+ fTimePosition.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute;
- if (frame != nullptr && frame->type == fURIDs.atomLong)
- fTimePosition.frame = ((LV2_Atom_Long*)frame)->body;
+ if (d_isNotZero(fLastPositionData.speed))
+ fTimePosition.bbt.beatsPerMinute *= std::abs(fLastPositionData.speed);
+ }
+ }
- if (speed != nullptr && speed->type == fURIDs.atomFloat)
+ if (frame != nullptr)
{
- fLastTimeSpeed = ((LV2_Atom_Float*)speed)->body;
- fTimePosition.playing = (fLastTimeSpeed == 1.0);
+ /**/ if (frame->type == fURIDs.atomDouble)
+ fLastPositionData.frame = ((LV2_Atom_Double*)frame)->body;
+ else if (frame->type == fURIDs.atomFloat)
+ fLastPositionData.frame = ((LV2_Atom_Float*)frame)->body;
+ else if (frame->type == fURIDs.atomInt)
+ fLastPositionData.frame = ((LV2_Atom_Int*)frame)->body;
+ else if (frame->type == fURIDs.atomLong)
+ fLastPositionData.frame = ((LV2_Atom_Long*)frame)->body;
+ else
+ d_stderr("Unknown lv2 frame value type");
+
+ if (fLastPositionData.frame >= 0)
+ fTimePosition.frame = fLastPositionData.frame;
}
- fTimePosition.bbt.valid = (beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr);
+ fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
+ fTimePosition.bbt.beatsPerBar*
+ (fTimePosition.bbt.bar-1);
+
+ fTimePosition.bbt.valid = (fLastPositionData.beatsPerMinute > 0.0 &&
+ fLastPositionData.beatUnit > 0 &&
+ fLastPositionData.beatsPerBar > 0.0f);
+
continue;
}
# endif
@@ -485,37 +513,56 @@ public:
# if DISTRHO_PLUGIN_WANT_TIMEPOS
// update timePos for next callback
- if (fLastTimeSpeed != 0.0)
+ if (d_isNotZero(fLastPositionData.speed))
{
- const double newFrames = fLastTimeSpeed*sampleCount;
+ if (fLastPositionData.speed > 0.0)
+ {
+ // playing forwards
+ fLastPositionData.frame += sampleCount;
+ }
+ else
+ {
+ // playing backwards
+ fLastPositionData.frame -= sampleCount;
+
+ if (fLastPositionData.frame < 0)
+ fLastPositionData.frame = 0;
+ }
- fTimePosition.frame += newFrames;
+ fTimePosition.frame = fLastPositionData.frame;
if (fTimePosition.bbt.valid)
{
- const double samplesPerBeat = 60.0 / fTimePosition.bbt.beatsPerMinute * fSampleRate;
- const double ticksPerSample = fTimePosition.bbt.ticksPerBeat / samplesPerBeat;
+ const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed;
+ const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute;
+ const double addedBarBeats = double(sampleCount) / framesPerBeat;
- double newTickPos = double(fTimePosition.bbt.tick) + ticksPerSample*newFrames;
- double newBeatPos = double(fTimePosition.bbt.beat)-1.0;
- double newBarPos = double(fTimePosition.bbt.bar)-1.0;
-
- for (; newTickPos >= fTimePosition.bbt.ticksPerBeat;)
+ if (fLastPositionData.bar >= 0)
{
- ++newBeatPos;
- newTickPos -= fTimePosition.bbt.ticksPerBeat;
+ fLastPositionData.bar += std::floor((fLastPositionData.barBeat+addedBarBeats)/
+ fLastPositionData.beatsPerBar);
+
+ if (fLastPositionData.bar < 0)
+ fLastPositionData.bar = 0;
+
+ fTimePosition.bbt.bar = fLastPositionData.bar + 1;
+
+ fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
+ fTimePosition.bbt.beatsPerBar*
+ (fTimePosition.bbt.bar-1);
}
- for (; newBeatPos >= fTimePosition.bbt.beatsPerBar;)
+ if (fLastPositionData.barBeat >= 0.0f)
{
- ++newBarPos;
- newBeatPos -= fTimePosition.bbt.beatsPerBar;
+ fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+addedBarBeats,
+ fTimePosition.bbt.beatsPerBar);
+
+ const double rest = std::fmod(fLastPositionData.barBeat, 1.0);
+ fTimePosition.bbt.beat = fLastPositionData.barBeat-rest+1.0;
+ fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5;
}
- fTimePosition.bbt.bar = newBarPos+1.0;
- fTimePosition.bbt.beat = newBeatPos+1.0;
- fTimePosition.bbt.tick = newTickPos;
- fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1);
+ fTimePosition.bbt.beatsPerMinute = std::abs(beatsPerMinute);
}
}
# endif
@@ -788,7 +835,30 @@ private:
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition fTimePosition;
- double fLastTimeSpeed;
+
+ struct Lv2PositionData {
+ int64_t bar;
+ float barBeat;
+ double beat;
+ uint32_t beatUnit;
+ float beatsPerBar;
+ float beatsPerMinute;
+ int64_t frame;
+ double speed;
+ int64_t ticksPerBeat;
+
+ Lv2PositionData()
+ : bar(-1),
+ barBeat(-1.0f),
+ beat(-1.0),
+ beatUnit(0),
+ beatsPerBar(0.0f),
+ beatsPerMinute(0.0f),
+ frame(-1),
+ speed(0.0),
+ ticksPerBeat(-1) {}
+
+ } fLastPositionData;
#endif
// LV2 URIDs
@@ -807,7 +877,6 @@ private:
LV2_URID timePosition;
LV2_URID timeBar;
LV2_URID timeBarBeat;
- LV2_URID timeBeat;
LV2_URID timeBeatUnit;
LV2_URID timeBeatsPerBar;
LV2_URID timeBeatsPerMinute;
@@ -829,7 +898,6 @@ private:
timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)),
timeBar(uridMap->map(uridMap->handle, LV2_TIME__bar)),
timeBarBeat(uridMap->map(uridMap->handle, LV2_TIME__barBeat)),
- timeBeat(uridMap->map(uridMap->handle, LV2_TIME__beat)),
timeBeatUnit(uridMap->map(uridMap->handle, LV2_TIME__beatUnit)),
timeBeatsPerBar(uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar)),
timeBeatsPerMinute(uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute)),