| @@ -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); | |||