DPF

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

commit b11b6a4332d1887ba3f5b8842418d5d8e015dcb1
parent bcf84559a524a8100922804f040bf600fb2d894e
Author: falkTX <falktx@falktx.com>
Date:   Fri, 12 Jul 2019 11:45:14 +0200

Merge branch 'master' into develop

Diffstat:
MMakefile.base.mk | 2++
Adistrho/DistrhoPluginUtils.hpp | 161+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdistrho/DistrhoUtils.hpp | 40++++++++++++++++++++++++++++++++++++++++
Mdistrho/src/DistrhoDefines.h | 18+++++++++++++++++-
4 files changed, 220 insertions(+), 1 deletion(-)

diff --git a/Makefile.base.mk b/Makefile.base.mk @@ -217,9 +217,11 @@ DGL_SYSTEM_LIBS += -lgdi32 endif ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) +ifeq ($(HAVE_X11),true) DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11) DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11) endif +endif # --------------------------------------------------------------------------------------------------------------------- # Set Cairo specific stuff diff --git a/distrho/DistrhoPluginUtils.hpp b/distrho/DistrhoPluginUtils.hpp @@ -0,0 +1,161 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_PLUGIN_UTILS_HPP_INCLUDED +#define DISTRHO_PLUGIN_UTILS_HPP_INCLUDED + +#include "DistrhoPlugin.hpp" + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------------------------------------------- + +/** + Handy class to help keep audio buffer in sync with incoming MIDI events. + To use it, create a local variable (on the stack) and call nextEvent() until it returns false. + @code + for (AudioMidiSyncHelper amsh(outputs, frames, midiEvents, midiEventCount); amsh.nextEvent();) + { + float* const outL = amsh.outputs[0]; + float* const outR = amsh.outputs[1]; + + for (uint32_t i=0; i<amsh.midiEventCount; ++i) + { + const MidiEvent& ev(amsh.midiEvents[i]); + // ... do something with the midi event + } + + renderSynth(outL, outR, amsh.frames); + } + @endcode + + Some important notes when using this class: + 1. MidiEvent::frame retains its original value, but it is useless, do not use it. + 2. The class variables names are be the same as the default ones in the run function. + Keep that in mind and try to avoid typos. :) + */ +class AudioMidiSyncHelper { +public: + /** Parameters from the run function, adjusted for event sync */ + float** outputs; + uint32_t frames; + const MidiEvent* midiEvents; + uint32_t midiEventCount; + + /** + Constructor, using values from the run function. + */ + AudioMidiSyncHelper(float** const o, uint32_t f, const MidiEvent* m, uint32_t mc) + : outputs(o), + frames(0), + midiEvents(m), + midiEventCount(0), + remainingFrames(f), + remainingMidiEventCount(mc), + totalFramesUsed(0) {} + + /** + Process a batch of events untill no more are available. + You must not read any more values from this class after this function returns false. + */ + bool nextEvent() + { + // nothing else to do + if (remainingFrames == 0) + return false; + + // initial setup, need to find first MIDI event + if (totalFramesUsed == 0) + { + // no MIDI events at all in this process cycle + if (remainingMidiEventCount == 0) + { + frames = remainingFrames; + remainingFrames = 0; + totalFramesUsed += frames; + return true; + } + + // render audio until first midi event, if needed + if (const uint32_t firstEventFrame = midiEvents[0].frame) + { + frames = midiEvents[0].frame; + remainingFrames -= frames; + totalFramesUsed += frames; + return true; + } + } + else + { + for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) + outputs[i] += frames; + } + + // no more MIDI events available + if (remainingMidiEventCount == 0) + { + frames = remainingFrames; + midiEvents = nullptr; + midiEventCount = 0; + remainingFrames = 0; + totalFramesUsed += frames; + return true; + } + + // if there were midi events before, increment pointer + if (midiEventCount != 0) + midiEvents += midiEventCount; + + const uint32_t firstEventFrame = midiEvents[0].frame; + DISTRHO_SAFE_ASSERT_RETURN((firstEventFrame - frames) < remainingFrames, false); + + midiEventCount = 1; + while (midiEventCount < remainingMidiEventCount) + { + if (midiEvents[midiEventCount].frame == firstEventFrame) + ++midiEventCount; + else + break; + } + + if (totalFramesUsed != 0) + { + for (uint32_t i=0; i < midiEventCount; ++i) + { + DISTRHO_SAFE_ASSERT_UINT2_BREAK(midiEvents[i].frame - totalFramesUsed == 0, + midiEvents[i].frame, totalFramesUsed); + } + } + + frames = remainingFrames - firstEventFrame; + remainingFrames -= frames; + remainingMidiEventCount -= midiEventCount; + totalFramesUsed += frames; + return true; + } + +private: + /** @internal */ + uint32_t remainingFrames; + uint32_t remainingMidiEventCount; + uint32_t totalFramesUsed; +}; + +// ----------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_PLUGIN_UTILS_HPP_INCLUDED diff --git a/distrho/DistrhoUtils.hpp b/distrho/DistrhoUtils.hpp @@ -157,6 +157,46 @@ void d_safe_assert(const char* const assertion, const char* const file, const in } /* + * Print a safe assertion error message, with 1 extra signed integer value. + */ +static inline +void d_safe_assert_int(const char* const assertion, const char* const file, + const int line, const int value) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value); +} + +/* + * Print a safe assertion error message, with 1 extra unsigned integer value. + */ +static inline +void d_safe_assert_uint(const char* const assertion, const char* const file, + const int line, const uint value) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value); +} + +/* + * Print a safe assertion error message, with 2 extra signed integer values. + */ +static inline +void d_safe_assert_int2(const char* const assertion, const char* const file, + const int line, const int v1, const int v2) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2); +} + +/* + * Print a safe assertion error message, with 2 extra unsigned integer values. + */ +static inline +void d_safe_assert_uint2(const char* const assertion, const char* const file, + const int line, const uint v1, const uint v2) noexcept +{ + d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2); +} + +/* * Print a safe exception error message. */ static inline diff --git a/distrho/src/DistrhoDefines.h b/distrho/src/DistrhoDefines.h @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> + * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this @@ -81,6 +81,22 @@ #define DISTRHO_SAFE_ASSERT_CONTINUE(cond) if (! (cond)) { d_safe_assert(#cond, __FILE__, __LINE__); continue; } #define DISTRHO_SAFE_ASSERT_RETURN(cond, ret) if (! (cond)) { d_safe_assert(#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_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; } + +#define DISTRHO_SAFE_ASSERT_INT2_BREAK(cond, v1, v2) if (! (cond)) { d_safe_assert_int2(#cond, __FILE__, __LINE__, static_cast<int>(v1), static_cast<int>(v2)); break; } +#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_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; } + +#define DISTRHO_SAFE_ASSERT_UINT2_BREAK(cond, v1, v2) if (! (cond)) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast<uint>(v1), static_cast<uint>(v2)); break; } +#define DISTRHO_SAFE_ASSERT_UINT2_CONTINUE(cond, v1, v2) if (! (cond)) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast<uint>(v1), static_cast<uint>(v2)); continue; } +#define DISTRHO_SAFE_ASSERT_UINT2_RETURN(cond, v1, v2, ret) if (! (cond)) { d_safe_assert_uint2(#cond, __FILE__, __LINE__, static_cast<uint>(v1), static_cast<uint>(v2)); return ret; } + /* Define DISTRHO_SAFE_EXCEPTION */ #define DISTRHO_SAFE_EXCEPTION(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); } #define DISTRHO_SAFE_EXCEPTION_BREAK(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); break; }