@@ -312,10 +312,7 @@ public: | |||
fURIDs.timeSpeed, &speed, | |||
nullptr); | |||
// Not possible with LV2: | |||
// -> barStartTick | |||
// -> ticksPerBeat | |||
fTimePosition.bbt.barStartTick = 0.0; | |||
// ticksPerBeat is not possible with LV2 | |||
fTimePosition.bbt.ticksPerBeat = 960.0; | |||
if (bar != nullptr) | |||
@@ -337,27 +334,19 @@ public: | |||
double barBeatValue = 0.0; | |||
/**/ if (barBeat->type == fURIDs.atomDouble) | |||
barBeatValue = ((LV2_Atom_Double*)barBeat)->body + 1.0; | |||
barBeatValue = ((LV2_Atom_Double*)barBeat)->body; | |||
else if (barBeat->type == fURIDs.atomFloat) | |||
barBeatValue = ((LV2_Atom_Float*)barBeat)->body + 1.0f; | |||
barBeatValue = ((LV2_Atom_Float*)barBeat)->body; | |||
else if (barBeat->type == fURIDs.atomInt) | |||
barBeatValue = ((LV2_Atom_Int*)barBeat)->body + 1; | |||
barBeatValue = ((LV2_Atom_Int*)barBeat)->body; | |||
else if (barBeat->type == fURIDs.atomLong) | |||
barBeatValue = ((LV2_Atom_Long*)barBeat)->body + 1; | |||
barBeatValue = ((LV2_Atom_Long*)barBeat)->body; | |||
else | |||
d_stderr("Unknown lv2 barBeat value type"); | |||
if (barBeatValue != 0.0) | |||
{ | |||
const double beat = std::floor(barBeatValue); | |||
fTimePosition.bbt.beat = beat; | |||
fTimePosition.bbt.tick = (barBeatValue-beat)*fTimePosition.bbt.ticksPerBeat; | |||
} | |||
else | |||
{ | |||
fTimePosition.bbt.beat = 0; | |||
fTimePosition.bbt.tick = 0; | |||
} | |||
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) | |||
@@ -416,6 +405,8 @@ public: | |||
d_stderr("Unknown lv2 beatsPerMinute value type"); | |||
} | |||
fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1); | |||
if (frame != nullptr && frame->type == fURIDs.atomLong) | |||
fTimePosition.frame = ((LV2_Atom_Long*)frame)->body; | |||
@@ -494,6 +485,7 @@ public: | |||
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); | |||
} | |||
} | |||
# endif | |||
@@ -57,10 +57,6 @@ struct ERect { | |||
# include "vst/aeffectx.h" | |||
#endif | |||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
# warning VST TimePos still TODO (only basic BBT working) | |||
#endif | |||
START_NAMESPACE_DISTRHO | |||
typedef std::map<const d_string,d_string> StringMap; | |||
@@ -624,23 +620,51 @@ public: | |||
void vst_processReplacing(const float** const inputs, float** const outputs, const int32_t sampleFrames) | |||
{ | |||
#if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
static const int kWantVstTimeFlags(kVstTransportPlaying|kVstTempoValid|kVstTimeSigValid); | |||
static const int kWantVstTimeFlags(kVstTransportPlaying|kVstPpqPosValid|kVstTempoValid|kVstBarsValid|kVstTimeSigValid); | |||
if (const VstTimeInfo* const vstTimeInfo = (const VstTimeInfo*)fAudioMaster(fEffect, audioMasterGetTime, 0, kWantVstTimeFlags, nullptr, 0.0f)) | |||
{ | |||
fTimePosition.playing = (vstTimeInfo->flags & kVstTransportPlaying); | |||
fTimePosition.frame = vstTimeInfo->samplePos; | |||
fTimePosition.frame = vstTimeInfo->samplePos; | |||
fTimePosition.playing = (vstTimeInfo->flags & kVstTransportPlaying); | |||
fTimePosition.bbt.valid = ((vstTimeInfo->flags & kVstTempoValid) != 0 || (vstTimeInfo->flags & kVstTimeSigValid) != 0); | |||
if (vstTimeInfo->flags & kVstTempoValid) | |||
// ticksPerBeat is not possible with VST | |||
fTimePosition.bbt.ticksPerBeat = 960.0; | |||
if (vstTimeInfo->flags & kVstPpqPosValid) | |||
{ | |||
fTimePosition.bbt.beatsPerMinute = vstTimeInfo->tempo; | |||
const int ppqPerBar = vstTimeInfo->timeSigNumerator * 4 / vstTimeInfo->timeSigDenominator; | |||
const double barBeats = (std::fmod(vstTimeInfo->ppqPos, ppqPerBar) / ppqPerBar) * vstTimeInfo->timeSigDenominator; | |||
const double rest = std::fmod(barBeats, 1.0); | |||
fTimePosition.bbt.bar = int(vstTimeInfo->ppqPos)/ppqPerBar + 1; | |||
fTimePosition.bbt.beat = barBeats-rest+1; | |||
fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5; | |||
} | |||
else | |||
{ | |||
fTimePosition.bbt.bar = 1; | |||
fTimePosition.bbt.beat = 1; | |||
fTimePosition.bbt.tick = 0; | |||
} | |||
fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1); | |||
if (vstTimeInfo->flags & kVstTimeSigValid) | |||
{ | |||
fTimePosition.bbt.beatsPerBar = vstTimeInfo->timeSigNumerator; | |||
fTimePosition.bbt.beatType = vstTimeInfo->timeSigDenominator; | |||
} | |||
else | |||
{ | |||
fTimePosition.bbt.beatsPerBar = 4.0f; | |||
fTimePosition.bbt.beatType = 4.0f; | |||
} | |||
if (vstTimeInfo->flags & kVstTempoValid) | |||
fTimePosition.bbt.beatsPerMinute = vstTimeInfo->tempo; | |||
else | |||
fTimePosition.bbt.beatsPerMinute = 120.0; | |||
fPlugin.setTimePosition(fTimePosition); | |||
} | |||
@@ -2,7 +2,7 @@ | |||
* aeffectx.h - simple header to allow VeSTige compilation and eventually work | |||
* | |||
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net> | |||
* | |||
* | |||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
@@ -113,12 +113,11 @@ | |||
#define kEffectMagic (CCONST( 'V', 's', 't', 'P' )) | |||
#define kVstLangEnglish 1 | |||
#define kVstMidiType 1 | |||
#define kVstTempoValid (1 << 10) | |||
#define kVstTransportPlaying (1 << 1) | |||
struct RemoteVstPlugin; | |||
#define kVstTransportPlaying (1 << 1) | |||
#define kVstNanosValid (1 << 8) | |||
#define kVstPpqPosValid (1 << 9) | |||
#define kVstTempoValid (1 << 10) | |||
@@ -250,29 +249,26 @@ struct _AEffect | |||
typedef struct _AEffect AEffect; | |||
struct _VstTimeInfo | |||
typedef struct _VstTimeInfo | |||
{ | |||
// 00 | |||
double samplePos; | |||
// 08 | |||
double sampleRate; | |||
// unconfirmed 10 18 | |||
char empty1[8 + 8]; | |||
// 20? | |||
double tempo; | |||
// unconfirmed 28 30 38 | |||
char empty2[8 + 8 + 8]; | |||
// 40? | |||
int timeSigNumerator; | |||
// 44? | |||
int timeSigDenominator; | |||
// unconfirmed 48 4c 50 | |||
char empty3[4 + 4 + 4]; | |||
// 54 | |||
int flags; | |||
}; | |||
/* info from online documentation of VST provided by Steinberg */ | |||
double samplePos; | |||
double sampleRate; | |||
double nanoSeconds; | |||
double ppqPos; | |||
double tempo; | |||
double barStartPos; | |||
double cycleStartPos; | |||
double cycleEndPos; | |||
int32_t timeSigNumerator; | |||
int32_t timeSigDenominator; | |||
int32_t smpteOffset; | |||
int32_t smpteFrameRate; | |||
int32_t samplesToNextClock; | |||
int32_t flags; | |||
typedef struct _VstTimeInfo VstTimeInfo; | |||
} VstTimeInfo; | |||
typedef intptr_t (* audioMasterCallback) (AEffect *, int32_t, int32_t, intptr_t, void *, float); | |||