commit 9b49fd363e67d4e7efbc54852cf0cf24312571ce
parent 1db760336079f0bf9968d21f9497f905acbed346
Author: falkTX <falktx@falktx.com>
Date: Fri, 24 Sep 2021 20:06:58 +0100
VST3: implement time position; enable metronome vst3 build
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
5 files changed, 90 insertions(+), 18 deletions(-)
diff --git a/distrho/src/DistrhoDefines.h b/distrho/src/DistrhoDefines.h
@@ -109,7 +109,7 @@
#define DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_CONTINUE(msg, cond) if (! (cond)) { static bool _p; if (!_p) { _p = true; d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); } continue; }
#define DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_RETURN(msg, cond, ret) if (! (cond)) { static bool _p; if (!_p) { _p = true; d_custom_safe_assert(msg, #cond, __FILE__, __LINE__); } return ret; }
-#define DISTRHO_SAFE_ASSERT_INT_BREAK(cond, value) if (! (cond)) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast<int>(value); break; }
+#define DISTRHO_SAFE_ASSERT_INT_BREAK(cond, value) if (! (cond)) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast<int>(value)); break; }
#define DISTRHO_SAFE_ASSERT_INT_CONTINUE(cond, value) if (! (cond)) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast<int>(value)); continue; }
#define DISTRHO_SAFE_ASSERT_INT_RETURN(cond, value, ret) if (! (cond)) { d_safe_assert_int(#cond, __FILE__, __LINE__, static_cast<int>(value)); return ret; }
@@ -117,7 +117,7 @@
#define DISTRHO_SAFE_ASSERT_INT2_CONTINUE(cond, v1, v2) if (! (cond)) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast<int>(v1), static_cast<int>(v2)); continue; }
#define DISTRHO_SAFE_ASSERT_INT2_RETURN(cond, v1, v2, ret) if (! (cond)) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast<int>(v1), static_cast<int>(v2)); return ret; }
-#define DISTRHO_SAFE_ASSERT_UINT_BREAK(cond, value) if (! (cond)) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast<uint>(value); break; }
+#define DISTRHO_SAFE_ASSERT_UINT_BREAK(cond, value) if (! (cond)) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast<uint>(value)); break; }
#define DISTRHO_SAFE_ASSERT_UINT_CONTINUE(cond, value) if (! (cond)) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast<uint>(value)); continue; }
#define DISTRHO_SAFE_ASSERT_UINT_RETURN(cond, value, ret) if (! (cond)) { d_safe_assert_uint(#cond, __FILE__, __LINE__, static_cast<uint>(value)); return ret; }
diff --git a/distrho/src/DistrhoPluginVST2.cpp b/distrho/src/DistrhoPluginVST2.cpp
@@ -1114,7 +1114,7 @@ public:
fTimePosition.playing = (vstTimeInfo->flags & kVstTransportPlaying);
fTimePosition.bbt.valid = ((vstTimeInfo->flags & kVstTempoValid) != 0 || (vstTimeInfo->flags & kVstTimeSigValid) != 0);
- // ticksPerBeat is not possible with VST
+ // ticksPerBeat is not possible with VST2
fTimePosition.bbt.ticksPerBeat = 1920.0;
if (vstTimeInfo->flags & kVstTempoValid)
diff --git a/distrho/src/DistrhoPluginVST3.cpp b/distrho/src/DistrhoPluginVST3.cpp
@@ -677,25 +677,25 @@ public:
// ----------------------------------------------------------------------------------------------------------------
// v3_bstream interface calls (for state support)
- v3_result read(void* buffer, int32_t num_bytes, int32_t* bytes_read)
+ v3_result read(void* /*buffer*/, int32_t /*num_bytes*/, int32_t* /*bytes_read*/)
{
// TODO
return V3_NOT_IMPLEMENTED;
}
- v3_result write(void* buffer, int32_t num_bytes, int32_t* bytes_written)
+ v3_result write(void* /*buffer*/, int32_t /*num_bytes*/, int32_t* /*bytes_written*/)
{
// TODO
return V3_NOT_IMPLEMENTED;
}
- v3_result seek(int64_t pos, int32_t seek_mode, int64_t* result)
+ v3_result seek(int64_t /*pos*/, int32_t /*seek_mode*/, int64_t* /*result*/)
{
// TODO
return V3_NOT_IMPLEMENTED;
}
- v3_result tell(int64_t* pos)
+ v3_result tell(int64_t* /*pos*/)
{
// TODO
return V3_NOT_IMPLEMENTED;
@@ -771,25 +771,91 @@ public:
}
#if DISTRHO_PLUGIN_WANT_TIMEPOS
- // TODO
+ // TODO implement v3_process_context_requirements as query_interface of something..
+ if (v3_process_context* const ctx = data->ctx)
+ {
+ fTimePosition.playing = ctx->state & V3_PROCESS_CTX_PLAYING;
+ fTimePosition.bbt.valid = ctx->state & (V3_PROCESS_CTX_TEMPO_VALID|V3_PROCESS_CTX_TIME_SIG_VALID);
+
+ // ticksPerBeat is not possible with VST2
+ fTimePosition.bbt.ticksPerBeat = 1920.0;
+
+ if (ctx->state & V3_PROCESS_CTX_CONT_TIME_VALID)
+ fTimePosition.frame = ctx->continuous_time_in_samples;
+ else
+ fTimePosition.frame = ctx->project_time_in_samples;
+
+ if (ctx->state & V3_PROCESS_CTX_TEMPO_VALID)
+ fTimePosition.bbt.beatsPerMinute = ctx->bpm;
+ else
+ fTimePosition.bbt.beatsPerMinute = 120.0;
+
+ if (ctx->state & (V3_PROCESS_CTX_PROJECT_TIME_VALID|V3_PROCESS_CTX_TIME_SIG_VALID))
+ {
+ const double ppqPos = std::abs(ctx->project_time_quarters);
+ const int ppqPerBar = ctx->time_sig_numerator * 4 / ctx->time_sig_denom;
+ const double barBeats = (std::fmod(ppqPos, ppqPerBar) / ppqPerBar) * ctx->time_sig_numerator;
+ const double rest = std::fmod(barBeats, 1.0);
+
+ fTimePosition.bbt.bar = static_cast<int32_t>(ppqPos) / ppqPerBar + 1;
+ fTimePosition.bbt.beat = static_cast<int32_t>(barBeats - rest + 0.5) + 1;
+ fTimePosition.bbt.tick = rest * fTimePosition.bbt.ticksPerBeat;
+ fTimePosition.bbt.beatsPerBar = ctx->time_sig_numerator;
+ fTimePosition.bbt.beatType = ctx->time_sig_denom;
+
+ if (ctx->project_time_quarters < 0.0)
+ {
+ --fTimePosition.bbt.bar;
+ fTimePosition.bbt.beat = ctx->time_sig_numerator - fTimePosition.bbt.beat + 1;
+ fTimePosition.bbt.tick = fTimePosition.bbt.ticksPerBeat - fTimePosition.bbt.tick - 1;
+ }
+ }
+ else
+ {
+ fTimePosition.bbt.bar = 1;
+ fTimePosition.bbt.beat = 1;
+ fTimePosition.bbt.tick = 0.0;
+ fTimePosition.bbt.beatsPerBar = 4.0f;
+ fTimePosition.bbt.beatType = 4.0f;
+ }
+
+ fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*
+ fTimePosition.bbt.beatsPerBar*
+ (fTimePosition.bbt.bar-1);
+
+ fPlugin.setTimePosition(fTimePosition);
+
+ }
#endif
- const float* inputs[DISTRHO_PLUGIN_NUM_INPUTS];
- /* */ float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS];
+ const float* inputs[DISTRHO_PLUGIN_NUM_INPUTS != 0 ? DISTRHO_PLUGIN_NUM_INPUTS : 1];
+ /* */ float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS != 0 ? DISTRHO_PLUGIN_NUM_OUTPUTS : 1];
{
int32_t i = 0;
- for (; i < data->inputs->num_channels; ++i)
- inputs[i] = data->inputs->channel_buffers_32[i];
- for (; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
+ if (data->inputs != nullptr)
+ {
+ for (; i < data->inputs->num_channels; ++i)
+ {
+ DISTRHO_SAFE_ASSERT_INT_BREAK(i < DISTRHO_PLUGIN_NUM_INPUTS, i);
+ inputs[i] = data->inputs->channel_buffers_32[i];
+ }
+ }
+ for (; i < std::max(1, DISTRHO_PLUGIN_NUM_INPUTS); ++i)
inputs[i] = nullptr; // TODO use dummy buffer
}
{
int32_t i = 0;
- for (; i < data->outputs->num_channels; ++i)
- outputs[i] = data->outputs->channel_buffers_32[i];
- for (; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
+ if (data->outputs != nullptr)
+ {
+ for (; i < data->outputs->num_channels; ++i)
+ {
+ DISTRHO_SAFE_ASSERT_INT_BREAK(i < DISTRHO_PLUGIN_NUM_OUTPUTS, i);
+ outputs[i] = data->outputs->channel_buffers_32[i];
+ }
+ }
+ for (; i < std::max(1, DISTRHO_PLUGIN_NUM_OUTPUTS); ++i)
outputs[i] = nullptr; // TODO use dummy buffer
}
@@ -966,6 +1032,11 @@ private:
v3_component_handler* fComponentHandler;
void* fComponentHandlerArg;
+ // Temporary data
+#if DISTRHO_PLUGIN_WANT_TIMEPOS
+ TimePosition fTimePosition;
+#endif
+
bool requestParameterValueChange(const uint32_t index, const float value)
{
DISTRHO_SAFE_ASSERT_RETURN(fComponentHandler != nullptr, false);
diff --git a/distrho/src/travesty/audio_processor.h b/distrho/src/travesty/audio_processor.h
@@ -153,7 +153,7 @@ struct v3_process_context {
int64_t project_time_in_samples; // with loop
int64_t system_time_ns;
- int64_t continuous_time_in_samples; // without loop? unclear
+ int64_t continuous_time_in_samples; // without loop
double project_time_quarters;
double bar_position_quarters;
diff --git a/examples/Metronome/Makefile b/examples/Metronome/Makefile
@@ -25,7 +25,8 @@ include ../../Makefile.plugins.mk
TARGETS += jack
TARGETS += lv2_dsp
-TARGETS += vst
+TARGETS += vst2
+TARGETS += vst3
all: $(TARGETS)