From 92f0ae409356eb76db1191f706b806e525554a56 Mon Sep 17 00:00:00 2001 From: Jim Tupper Date: Tue, 30 Oct 2018 22:24:52 +0000 Subject: [PATCH] Adding audio interface 16 temporary --- Makefile | 5 +- dep/Makefile | 37 - res/AudioInterface16.svg | 10517 +++++++++++++++++++++++++++++++++++++ res/CVMoment.svg | 4894 +++++++++++++++++ res/CVSlider0to10.svg | 4891 +++++++++++++++++ src/AudioInterface16.cpp | 314 ++ src/GVerbModule.cpp | 12 +- src/GVerbWidget.cpp | 15 +- src/GVerbWidget.hpp | 1 + src/LoadCounter.cpp | 66 + 10 files changed, 20705 insertions(+), 47 deletions(-) delete mode 100644 dep/Makefile create mode 100644 res/AudioInterface16.svg create mode 100644 res/CVMoment.svg create mode 100644 res/CVSlider0to10.svg create mode 100644 src/AudioInterface16.cpp create mode 100644 src/LoadCounter.cpp diff --git a/Makefile b/Makefile index 18bbdc9..19739b6 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,13 @@ VERSION = 0.6.2 # FLAGS will be passed to both the C and C++ compiler #FLAGS += -Idep/openmpt-libopenmpt-0.3.10/soundlib -Idep/openmpt-libopenmpt-0.3.10/common -CFLAGS += -CXXFLAGS += +CFLAGS += +CXXFLAGS += # Careful about linking to shared libraries, since you can't assume much about the user's environment and library search path. # Static libraries are fine. #LDFLAGS = -Ldep -Ldep/openmpt-libopenmpt-0.3.10/bin/libopenmpt.a +LDFLAGS = -Ldep # Add .cpp and .c files to the build SOURCES += $(wildcard src/*.cpp) $(wildcard src/*.c) diff --git a/dep/Makefile b/dep/Makefile deleted file mode 100644 index 976ba22..0000000 --- a/dep/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -RACK_DIR ?= ../../.. -.NOTPARALLEL: - - -# Target paths - -include $(RACK_DIR)/arch.mk - -ifdef ARCH_LIN - openmpt = lib/openmpt.a -endif - -ifdef ARCH_MAC - openmtp = lib/openmpt.a -endif - -ifdef ARCH_WIN - openmpt = lib/openmpt.a -endif - -nanovg = include/openmpt.h - -DEPS += $(openmpt) -include $(RACK_DIR)/dep.mk - - -# Targets - -$(openmpt): - $(WGET) "https://github.com/OpenMPT/openmpt/archive/libopenmpt-0.3.10.tar.gz" - $(UNTAR) libopenmpt-0.3.10.tar.gz - $(MAKE) -C openmpt-libopenmpt-0.3.10 - - -clean: - git clean -fdx - git submodule foreach git clean -fdx diff --git a/res/AudioInterface16.svg b/res/AudioInterface16.svg new file mode 100644 index 0000000..ff11172 --- /dev/null +++ b/res/AudioInterface16.svg @@ -0,0 +1,10517 @@ + + + + + + image/svg+xml + + AudioInterface + + + + + + + + + + + + + + + + + + + + + AudioInterface + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/CVMoment.svg b/res/CVMoment.svg new file mode 100644 index 0000000..e89246e --- /dev/null +++ b/res/CVMoment.svg @@ -0,0 +1,4894 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/CVSlider0to10.svg b/res/CVSlider0to10.svg new file mode 100644 index 0000000..78564ee --- /dev/null +++ b/res/CVSlider0to10.svg @@ -0,0 +1,4891 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AudioInterface16.cpp b/src/AudioInterface16.cpp new file mode 100644 index 0000000..7255b4d --- /dev/null +++ b/src/AudioInterface16.cpp @@ -0,0 +1,314 @@ +#include +#include +#include +#include +#include +#include +#include "GVerbWidget.hpp" +#include "audio.hpp" +#include "dsp/samplerate.hpp" +#include "dsp/ringbuffer.hpp" + + +#define AUDIO_OUTPUTS 16 +#define AUDIO_INPUTS 16 + + +using namespace rack; + +// Sound by Yaroslav Samoylov from the Noun Project + +struct AudioInterfaceIO16 : AudioIO { + std::mutex engineMutex; + std::condition_variable engineCv; + std::mutex audioMutex; + std::condition_variable audioCv; + // Audio thread produces, engine thread consumes + DoubleRingBuffer, (1<<15)> inputBuffer; + // Audio thread consumes, engine thread produces + DoubleRingBuffer, (1<<15)> outputBuffer; + bool active = false; + + AudioInterfaceIO16() { + maxChannels = 16; + } + + ~AudioInterfaceIO16() { + // Close stream here before destructing AudioInterfaceIO16, so the mutexes are still valid when waiting to close. + setDevice(-1, 0); + } + + void processStream(const float *input, float *output, int frames) override { + // Reactivate idle stream + if (!active) { + active = true; + inputBuffer.clear(); + outputBuffer.clear(); + } + + if (numInputs > 0) { + // TODO Do we need to wait on the input to be consumed here? Experimentally, it works fine if we don't. + for (int i = 0; i < frames; i++) { + if (inputBuffer.full()) + break; + Frame inputFrame; + memset(&inputFrame, 0, sizeof(inputFrame)); + memcpy(&inputFrame, &input[numInputs * i], numInputs * sizeof(float)); + inputBuffer.push(inputFrame); + } + } + + if (numOutputs > 0) { + std::unique_lock lock(audioMutex); + auto cond = [&] { + return (outputBuffer.size() >= (size_t) frames); + }; + auto timeout = std::chrono::milliseconds(100); + if (audioCv.wait_for(lock, timeout, cond)) { + // Consume audio block + for (int i = 0; i < frames; i++) { + Frame f = outputBuffer.shift(); + for (int j = 0; j < numOutputs; j++) { + output[numOutputs*i + j] = clamp(f.samples[j], -1.f, 1.f); + } + } + } + else { + // Timed out, fill output with zeros + memset(output, 0, frames * numOutputs * sizeof(float)); + debug("Audio Interface IO underflow"); + } + } + + // Notify engine when finished processing + engineCv.notify_one(); + } + + void onCloseStream() override { + inputBuffer.clear(); + outputBuffer.clear(); + } + + void onChannelsChange() override { + } +}; + + +struct AudioInterface16 : Module { + enum ParamIds { + NUM_PARAMS + }; + enum InputIds { + ENUMS(AUDIO_INPUT, AUDIO_INPUTS), + NUM_INPUTS + }; + enum OutputIds { + ENUMS(AUDIO_OUTPUT, AUDIO_OUTPUTS), + NUM_OUTPUTS + }; + enum LightIds { + ENUMS(INPUT_LIGHT, AUDIO_INPUTS / 2), + ENUMS(OUTPUT_LIGHT, AUDIO_OUTPUTS / 2), + NUM_LIGHTS + }; + + AudioInterfaceIO16 audioIO; + int lastSampleRate = 0; + int lastNumOutputs = -1; + int lastNumInputs = -1; + + SampleRateConverter inputSrc; + SampleRateConverter outputSrc; + + // in rack's sample rate + DoubleRingBuffer, 16> inputBuffer; + DoubleRingBuffer, 16> outputBuffer; + + AudioInterface16() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + onSampleRateChange(); + } + + void step() override; + + json_t *toJson() override { + json_t *rootJ = json_object(); + json_object_set_new(rootJ, "audio", audioIO.toJson()); + return rootJ; + } + + void fromJson(json_t *rootJ) override { + json_t *audioJ = json_object_get(rootJ, "audio"); + audioIO.fromJson(audioJ); + } + + void onReset() override { + audioIO.setDevice(-1, 0); + } +}; + + +void AudioInterface16::step() { + // Update SRC states + int sampleRate = (int) engineGetSampleRate(); + inputSrc.setRates(audioIO.sampleRate, sampleRate); + outputSrc.setRates(sampleRate, audioIO.sampleRate); + + inputSrc.setChannels(audioIO.numInputs); + outputSrc.setChannels(audioIO.numOutputs); + + // Inputs: audio engine -> rack engine + if (audioIO.active && audioIO.numInputs > 0) { + // Wait until inputs are present + // Give up after a timeout in case the audio device is being unresponsive. + std::unique_lock lock(audioIO.engineMutex); + auto cond = [&] { + return (!audioIO.inputBuffer.empty()); + }; + auto timeout = std::chrono::milliseconds(200); + if (audioIO.engineCv.wait_for(lock, timeout, cond)) { + // Convert inputs + int inLen = audioIO.inputBuffer.size(); + int outLen = inputBuffer.capacity(); + inputSrc.process(audioIO.inputBuffer.startData(), &inLen, inputBuffer.endData(), &outLen); + audioIO.inputBuffer.startIncr(inLen); + inputBuffer.endIncr(outLen); + } + else { + // Give up on pulling input + audioIO.active = false; + debug("Audio Interface underflow"); + } + } + + // Take input from buffer + Frame inputFrame; + if (!inputBuffer.empty()) { + inputFrame = inputBuffer.shift(); + } + else { + memset(&inputFrame, 0, sizeof(inputFrame)); + } + for (int i = 0; i < audioIO.numInputs; i++) { + outputs[AUDIO_OUTPUT + i].value = 10.f * inputFrame.samples[i]; + } + for (int i = audioIO.numInputs; i < AUDIO_INPUTS; i++) { + outputs[AUDIO_OUTPUT + i].value = 0.f; + } + + // Outputs: rack engine -> audio engine + if (audioIO.active && audioIO.numOutputs > 0) { + // Get and push output SRC frame + if (!outputBuffer.full()) { + Frame outputFrame; + for (int i = 0; i < AUDIO_OUTPUTS; i++) { + outputFrame.samples[i] = inputs[AUDIO_INPUT + i].value / 10.f; + } + outputBuffer.push(outputFrame); + } + + if (outputBuffer.full()) { + // Wait until enough outputs are consumed + // Give up after a timeout in case the audio device is being unresponsive. + std::unique_lock lock(audioIO.engineMutex); + auto cond = [&] { + return (audioIO.outputBuffer.size() < (size_t) audioIO.blockSize); + }; + auto timeout = std::chrono::milliseconds(200); + if (audioIO.engineCv.wait_for(lock, timeout, cond)) { + // Push converted output + int inLen = outputBuffer.size(); + int outLen = audioIO.outputBuffer.capacity(); + outputSrc.process(outputBuffer.startData(), &inLen, audioIO.outputBuffer.endData(), &outLen); + outputBuffer.startIncr(inLen); + audioIO.outputBuffer.endIncr(outLen); + } + else { + // Give up on pushing output + audioIO.active = false; + outputBuffer.clear(); + debug("Audio Interface underflow"); + } + } + + // Notify audio thread that an output is potentially ready + audioIO.audioCv.notify_one(); + } + + // Turn on light if at least one port is enabled in the nearby pair + for (int i = 0; i < AUDIO_INPUTS / 2; i++) + lights[INPUT_LIGHT + i].value = (audioIO.active && audioIO.numOutputs >= 2*i+1); + for (int i = 0; i < AUDIO_OUTPUTS / 2; i++) + lights[OUTPUT_LIGHT + i].value = (audioIO.active && audioIO.numInputs >= 2*i+1); +} + + +struct AudioInterfaceWidget16 : ModuleWidget { + AudioInterfaceWidget16(AudioInterface16 *module) : ModuleWidget(module) { + setPanel(SVG::load(assetPlugin(plugin, "res/AudioInterface16.svg"))); + + // addChild(Widget::create(Vec(RACK_GRID_WIDTH, 0))); + // addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); + // addChild(Widget::create(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + // addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + + addInput(Port::create(mm2px(Vec(3.7069211, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 0)); + addInput(Port::create(mm2px(Vec(15.307249, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 1)); + addInput(Port::create(mm2px(Vec(26.906193, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 2)); + addInput(Port::create(mm2px(Vec(38.506519, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 3)); + addInput(Port::create(mm2px(Vec(50.106845, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 4)); + addInput(Port::create(mm2px(Vec(61.707171, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 5)); + addInput(Port::create(mm2px(Vec(73.307497, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 6)); + addInput(Port::create(mm2px(Vec(84.907823, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 7)); + addInput(Port::create(mm2px(Vec(3.7069211, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 8)); + addInput(Port::create(mm2px(Vec(15.307249, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 9)); + addInput(Port::create(mm2px(Vec(26.906193, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 10)); + addInput(Port::create(mm2px(Vec(38.506519, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 11)); + addInput(Port::create(mm2px(Vec(50.106845, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 12)); + addInput(Port::create(mm2px(Vec(61.707171, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 13)); + addInput(Port::create(mm2px(Vec(73.307497, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 14)); + addInput(Port::create(mm2px(Vec(84.907823, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 15)); + + addOutput(Port::create(mm2px(Vec(3.7069209, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 0)); + addOutput(Port::create(mm2px(Vec(15.307249, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 1)); + addOutput(Port::create(mm2px(Vec(26.906193, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 2)); + addOutput(Port::create(mm2px(Vec(38.506519, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 3)); + addOutput(Port::create(mm2px(Vec(50.106845, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 4)); + addOutput(Port::create(mm2px(Vec(61.707171, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 5)); + addOutput(Port::create(mm2px(Vec(73.307497, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 6)); + addOutput(Port::create(mm2px(Vec(84.907823, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 7)); + addOutput(Port::create(mm2px(Vec(3.7069209, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 8)); + addOutput(Port::create(mm2px(Vec(15.307249, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 9)); + addOutput(Port::create(mm2px(Vec(26.906193, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 10)); + addOutput(Port::create(mm2px(Vec(38.506519, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 11)); + addOutput(Port::create(mm2px(Vec(50.106845, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 12)); + addOutput(Port::create(mm2px(Vec(61.707171, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 13)); + addOutput(Port::create(mm2px(Vec(73.307497, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 14)); + addOutput(Port::create(mm2px(Vec(84.907823, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 15)); + + addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 0)); + addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 1)); + addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 2)); + addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 3)); + addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 4)); + addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 5)); + addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 6)); + addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 7)); + + addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 0)); + addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 1)); + addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 2)); + addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 3)); + addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 4)); + addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 5)); + addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 6)); + addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 7)); + + AudioWidget *audioWidget = Widget::create(mm2px(Vec(3.2122073, 10.837339))); + audioWidget->box.size = mm2px(Vec(90.5, 28)); + audioWidget->audioIO = &module->audioIO; + addChild(audioWidget); + } +}; + + +Model *modelAudioInterface16 = Model::create("rcm", "AudioInterface16", "Audio 16", EXTERNAL_TAG); \ No newline at end of file diff --git a/src/GVerbModule.cpp b/src/GVerbModule.cpp index 66d7e99..73394f3 100644 --- a/src/GVerbModule.cpp +++ b/src/GVerbModule.cpp @@ -200,20 +200,20 @@ void GVerbModule::step() { auto R_L = 0.f, R_R = 0.f; if (gverbL != NULL) { - gverb_do(gverbL, inputs[LEFT_AUDIO].value, &L_L, &L_R); + gverb_do(gverbL, inputs[LEFT_AUDIO].value / 10.f, &L_L, &L_R); - L_L = isfinite(L_L) ? L_L : 0.f; - L_R = isfinite(L_R) ? L_R : 0.f; + L_L = isfinite(L_L) ? L_L * 10.f : 0.f; + L_R = isfinite(L_R) ? L_R * 10.f : 0.f; } auto L_L_S = (L_L + ((1-spread) * L_R)) / (2-spread); auto L_R_S = (L_R + ((1-spread) * L_L)) / (2-spread); if (gverbR != NULL) { - gverb_do(gverbR, inputs[RIGHT_AUDIO].value, &R_L, &R_R); + gverb_do(gverbR, inputs[RIGHT_AUDIO].value / 10.f, &R_L, &R_R); - R_L = isfinite(R_L) ? R_L : 0.f; - R_R = isfinite(R_R) ? R_R : 0.f; + R_L = isfinite(R_L) ? R_L * 10.f : 0.f; + R_R = isfinite(R_R) ? R_R * 10.f : 0.f; } auto R_L_S = (R_L + ((1-spread) * R_R)) / (2-spread); diff --git a/src/GVerbWidget.cpp b/src/GVerbWidget.cpp index 5043031..bd7d3ed 100644 --- a/src/GVerbWidget.cpp +++ b/src/GVerbWidget.cpp @@ -1,8 +1,18 @@ #include "GVerbWidget.hpp" +#include -Plugin *plugin; +#if ARCH_WIN + #include + #include + #define mkdir(_dir, _perms) _mkdir(_dir) +#else + #include +#endif + +using namespace std; +Plugin *plugin; void init(Plugin *p) { plugin = p; @@ -11,7 +21,8 @@ void init(Plugin *p) { // Add all Models defined throughout the plugin p->addModel(modelGVerbModule); - p->addModel(modelDuckModule); + p->addModel(modelLoadCounterModule); + p->addModel(modelAudioInterface16); p->addModel(modelCV0to10Module); p->addModel(modelCVS0to10Module); p->addModel(modelCV5to5Module); diff --git a/src/GVerbWidget.hpp b/src/GVerbWidget.hpp index e770b59..874d2c9 100644 --- a/src/GVerbWidget.hpp +++ b/src/GVerbWidget.hpp @@ -14,3 +14,4 @@ extern Model *modelCVS0to10Module; extern Model *modelCV5to5Module; extern Model *modelCVMmtModule; extern Model *modelCVTglModule; +extern Model *modelAudioInterface16; diff --git a/src/LoadCounter.cpp b/src/LoadCounter.cpp new file mode 100644 index 0000000..88433bb --- /dev/null +++ b/src/LoadCounter.cpp @@ -0,0 +1,66 @@ +#include "GVerbWidget.hpp" +#include + +struct LoadCounterModule : Module { + enum ParamIds { + NUM_PARAMS + }; + enum InputIds { + NUM_INPUTS + }; + enum OutputIds { + NUM_OUTPUTS + }; + enum LightIds { + NUM_LIGHTS + }; + + LoadCounterModule() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + } + void step() override; + + int counter = 0; + + // For more advanced Module features, read Rack's engine.hpp header file + // - toJson, fromJson: serialization of internal data + // - onSampleRateChange: event triggered by a change of sample rate + // - onReset, onRandomize, onCreate, onDelete: implements special behavior when user clicks these from the context menu +}; + +void LoadCounterModule::step() { + int n = 8; + for (int i = 1; i <= n; ++i) + { + std::vector x; + x.resize(50); + int m = 500; + for (auto &v : x) + { + v = 500 - m++; //rand(); + } + + std::sort(x.begin(), x.end()); + } +} + +struct CKSSWhite : SVGSwitch, ToggleSwitch { + CKSSWhite() { + addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_0_White.svg"))); + addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_1_White.svg"))); + } +}; + +struct LoadCounterModuleWidget : ModuleWidget { + TextField *textField; + + LoadCounterModuleWidget(LoadCounterModule *module) : ModuleWidget(module) { + setPanel(SVG::load(assetPlugin(plugin, "res/CVTgl.svg"))); + } +}; + + +// Specify the Module and ModuleWidget subclass, human-readable +// author name for categorization per plugin, module slug (should never +// change), human-readable module name, and any number of tags +// (found in `include/tags.hpp`) separated by commas. +Model *modelLoadCounterModule = Model::create("rcm", "rcm-counter", "Load Counter", ENVELOPE_FOLLOWER_TAG);