DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

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:
Mdistrho/src/DistrhoDefines.h | 4++--
Mdistrho/src/DistrhoPluginVST2.cpp | 2+-
Mdistrho/src/DistrhoPluginVST3.cpp | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mdistrho/src/travesty/audio_processor.h | 2+-
Mexamples/Metronome/Makefile | 3++-
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)