commit b11b6a4332d1887ba3f5b8842418d5d8e015dcb1
parent bcf84559a524a8100922804f040bf600fb2d894e
Author: falkTX <falktx@falktx.com>
Date: Fri, 12 Jul 2019 11:45:14 +0200
Merge branch 'master' into develop
Diffstat:
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; }