| @@ -1,171 +0,0 @@ | |||
| #!/usr/bin/make -f | |||
| # Makefile for native-plugins # | |||
| # --------------------------- # | |||
| # Created by falkTX | |||
| # | |||
| # NOTE: this file assumes Makefile.mk has been included before | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # DPF plugins | |||
| OBJS_all += \ | |||
| $(OBJDIR)/distrho-3bandeq.cpp.o \ | |||
| $(OBJDIR)/distrho-3bandsplitter.cpp.o \ | |||
| $(OBJDIR)/distrho-kars.cpp.o \ | |||
| $(OBJDIR)/distrho-nekobi.cpp.o \ | |||
| $(OBJDIR)/distrho-pingpongpan.cpp.o | |||
| ifeq ($(HAVE_DGL),true) | |||
| ifeq ($(HAVE_PROJECTM),true) | |||
| OBJS += $(OBJDIR)/distrho-prom.cpp.o | |||
| endif | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # DPF plugins (Juice) | |||
| OBJS_all += \ | |||
| $(OBJDIR)/distrho-vectorjuice.cpp.o \ | |||
| $(OBJDIR)/distrho-wobblejuice.cpp.o | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # ZynAddSubFX | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| OBJS_all += \ | |||
| $(OBJDIR)/zynaddsubfx-fx.cpp.o \ | |||
| $(OBJDIR)/zynaddsubfx-src.cpp.o | |||
| ifneq ($(SKIP_ZYN_SYNTH),true) | |||
| OBJS_all += \ | |||
| $(OBJDIR)/zynaddsubfx-synth.cpp.o | |||
| endif | |||
| ifeq ($(HAVE_ZYN_UI_DEPS),true) | |||
| TARGETS += resources/zynaddsubfx-ui$(APP_EXT) | |||
| ZYN_UI_FILES_CPP = \ | |||
| external/zynaddsubfx/UI/ADnoteUI.cpp \ | |||
| external/zynaddsubfx/UI/BankUI.cpp \ | |||
| external/zynaddsubfx/UI/ConfigUI.cpp \ | |||
| external/zynaddsubfx/UI/EffUI.cpp \ | |||
| external/zynaddsubfx/UI/EnvelopeUI.cpp \ | |||
| external/zynaddsubfx/UI/FilterUI.cpp \ | |||
| external/zynaddsubfx/UI/LFOUI.cpp \ | |||
| external/zynaddsubfx/UI/MasterUI.cpp \ | |||
| external/zynaddsubfx/UI/MicrotonalUI.cpp \ | |||
| external/zynaddsubfx/UI/OscilGenUI.cpp \ | |||
| external/zynaddsubfx/UI/PADnoteUI.cpp \ | |||
| external/zynaddsubfx/UI/PartUI.cpp \ | |||
| external/zynaddsubfx/UI/PresetsUI.cpp \ | |||
| external/zynaddsubfx/UI/ResonanceUI.cpp \ | |||
| external/zynaddsubfx/UI/SUBnoteUI.cpp \ | |||
| external/zynaddsubfx/UI/VirKeyboard.cpp | |||
| ZYN_UI_FILES_H = \ | |||
| external/zynaddsubfx/UI/ADnoteUI.h \ | |||
| external/zynaddsubfx/UI/BankUI.h \ | |||
| external/zynaddsubfx/UI/ConfigUI.h \ | |||
| external/zynaddsubfx/UI/EffUI.h \ | |||
| external/zynaddsubfx/UI/EnvelopeUI.h \ | |||
| external/zynaddsubfx/UI/FilterUI.h \ | |||
| external/zynaddsubfx/UI/LFOUI.h \ | |||
| external/zynaddsubfx/UI/MasterUI.h \ | |||
| external/zynaddsubfx/UI/MicrotonalUI.h \ | |||
| external/zynaddsubfx/UI/OscilGenUI.h \ | |||
| external/zynaddsubfx/UI/PADnoteUI.h \ | |||
| external/zynaddsubfx/UI/PartUI.h \ | |||
| external/zynaddsubfx/UI/PresetsUI.h \ | |||
| external/zynaddsubfx/UI/ResonanceUI.h \ | |||
| external/zynaddsubfx/UI/SUBnoteUI.h \ | |||
| external/zynaddsubfx/UI/VirKeyboard.h | |||
| endif | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| external/zynaddsubfx/UI/%.cpp: external/zynaddsubfx/UI/%.fl | |||
| @echo "Generating $@|h" | |||
| @$(FLUID) -c -o external/zynaddsubfx/UI/$*.cpp -h external/zynaddsubfx/UI/$*.h $< | |||
| external/zynaddsubfx/UI/%.h: external/zynaddsubfx/UI/%.fl | |||
| @echo "Generating $@|cpp" | |||
| @$(FLUID) -c -o external/zynaddsubfx/UI/$*.cpp -h external/zynaddsubfx/UI/$*.h $< | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| $(OBJDIR)/distrho-3bandeq.cpp.o: external/distrho-3bandeq.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) -DDISTRHO_NAMESPACE=d3BandEQ -Iexternal/distrho-3bandeq -c -o $@ | |||
| $(OBJDIR)/distrho-3bandsplitter.cpp.o: external/distrho-3bandsplitter.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) -DDISTRHO_NAMESPACE=d3BandSplitter -Iexternal/distrho-3bandsplitter -c -o $@ | |||
| $(OBJDIR)/distrho-kars.cpp.o: external/distrho-kars.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) -DDISTRHO_NAMESPACE=dKars -Iexternal/distrho-kars -c -o $@ | |||
| $(OBJDIR)/distrho-nekobi.cpp.o: external/distrho-nekobi.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) -DDISTRHO_NAMESPACE=dNekobi -Iexternal/distrho-nekobi -w -c -o $@ | |||
| $(OBJDIR)/distrho-pingpongpan.cpp.o: external/distrho-pingpongpan.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) -DDISTRHO_NAMESPACE=dPingPongPan -Iexternal/distrho-pingpongpan -c -o $@ | |||
| $(OBJDIR)/distrho-prom.cpp.o: external/distrho-prom.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) $(PROJECTM_FLAGS) -DDISTRHO_NAMESPACE=dProM -Iexternal/distrho-prom -c -o $@ | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| $(OBJDIR)/distrho-vectorjuice.cpp.o: external/distrho-vectorjuice.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) -DDISTRHO_NAMESPACE=dVectorJuice -Iexternal/distrho-vectorjuice -c -o $@ | |||
| $(OBJDIR)/distrho-wobblejuice.cpp.o: external/distrho-wobblejuice.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(DPF_FLAGS) -DDISTRHO_NAMESPACE=dWobbleJuice -Iexternal/distrho-wobblejuice -c -o $@ | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| $(OBJDIR)/zynaddsubfx-fx.cpp.o: external/zynaddsubfx-fx.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(ZYN_DSP_FLAGS) -c -o $@ | |||
| $(OBJDIR)/zynaddsubfx-synth.cpp.o: external/zynaddsubfx-synth.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(ZYN_DSP_FLAGS) -Wno-unused-parameter -c -o $@ | |||
| $(OBJDIR)/zynaddsubfx-src.cpp.o: external/zynaddsubfx-src.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(ZYN_DSP_FLAGS) -Wno-unused-parameter -Wno-unused-variable -c -o $@ | |||
| $(OBJDIR)/zynaddsubfx-ui.cpp.o: external/zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FILES_CPP) | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(ZYN_UI_FLAGS) -Wno-unused-parameter -Wno-unused-variable -c -o $@ | |||
| resources/zynaddsubfx-ui$(APP_EXT): $(OBJDIR)/zynaddsubfx-ui.cpp.o | |||
| -@mkdir -p ../resources | |||
| @echo "Linking zynaddsubfx-ui" | |||
| @$(CXX) $^ $(LINK_FLAGS) $(ZYN_UI_LIBS) -o $@ | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| -include $(OBJDIR)/zynaddsubfx-ui.cpp.d | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| @@ -1,233 +0,0 @@ | |||
| #!/usr/bin/make -f | |||
| # Makefile for native-plugins # | |||
| # --------------------------- # | |||
| # Created by falkTX | |||
| # | |||
| ifeq ($(TESTBUILD),true) | |||
| ifeq ($(LINUX),true) | |||
| CXXFLAGS += -isystem /opt/kxstudio/include/ntk | |||
| endif | |||
| endif | |||
| ifeq ($(MACOS_OR_WIN32),true) | |||
| HAVE_DGL = true | |||
| SKIP_ZYN_SYNTH = true | |||
| else | |||
| HAVE_DGL = $(shell pkg-config --exists gl x11 && echo true) | |||
| endif | |||
| HAVE_NTK = $(shell pkg-config --exists ntk ntk_images && echo true) | |||
| HAVE_PROJECTM = $(shell pkg-config --exists libprojectM && echo true) | |||
| ifneq ($(MACOS_OLD),true) | |||
| HAVE_ZYN_DEPS = $(shell pkg-config --exists liblo fftw3 mxml zlib && echo true) | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # Check for optional libs (special non-pkgconfig unix tests) | |||
| ifeq ($(UNIX),true) | |||
| # fltk doesn't have a pkg-config file but has fltk-config instead. | |||
| # Also, don't try looking for it if we already have NTK. | |||
| ifneq ($(HAVE_NTK),true) | |||
| ifeq ($(shell which fltk-config 1>/dev/null 2>/dev/null && echo true),true) | |||
| ifeq ($(shell which fluid 1>/dev/null 2>/dev/null && echo true),true) | |||
| HAVE_FLTK = true | |||
| endif | |||
| endif | |||
| endif | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| ifeq ($(HAVE_FLTK),true) | |||
| HAVE_ZYN_UI_DEPS = true | |||
| endif | |||
| ifeq ($(HAVE_NTK),true) | |||
| HAVE_ZYN_UI_DEPS = true | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| ifeq ($(HAVE_DGL),true) | |||
| BASE_FLAGS += -DHAVE_DGL | |||
| endif | |||
| ifeq ($(HAVE_PROJECTM),true) | |||
| BASE_FLAGS += -DHAVE_PROJECTM | |||
| endif | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| BASE_FLAGS += -DHAVE_ZYN_DEPS | |||
| ifeq ($(HAVE_ZYN_UI_DEPS),true) | |||
| BASE_FLAGS += -DHAVE_ZYN_UI_DEPS | |||
| endif | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| ifeq ($(HAVE_DGL),true) | |||
| ifeq ($(MACOS_OR_WIN32),true) | |||
| ifeq ($(MACOS),true) | |||
| DGL_LIBS = -framework OpenGL -framework Cocoa | |||
| endif | |||
| ifeq ($(WIN32),true) | |||
| DGL_LIBS = -lopengl32 -lgdi32 | |||
| endif | |||
| else | |||
| DGL_FLAGS = $(shell pkg-config --cflags gl x11) | |||
| DGL_LIBS = $(shell pkg-config --libs gl x11) | |||
| endif | |||
| DGL_FLAGS += -DDGL_NAMESPACE=CarlaDGL -DDGL_FILE_BROWSER_DISABLED -DDGL_NO_SHARED_RESOURCES | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| ifeq ($(HAVE_PROJECTM),true) | |||
| PROJECTM_FLAGS = $(shell pkg-config --cflags libprojectM) | |||
| PROJECTM_LIBS = $(shell pkg-config --libs libprojectM) | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # Flags for DPF Plugins | |||
| DPF_FLAGS = -I$(CWDE)/modules/distrho | |||
| ifeq ($(HAVE_DGL),true) | |||
| ifneq ($(MACOS_OR_WIN32),true) | |||
| DPF_FLAGS += $(shell pkg-config --cflags gl) | |||
| endif | |||
| DPF_FLAGS += -I$(CWDE)/modules/dgl -DDGL_NAMESPACE=CarlaDGL -DDGL_FILE_BROWSER_DISABLED -DDGL_NO_SHARED_RESOURCES | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| # Flags for ZynAddSubFX (DSP and UI separated) | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| # Common flags | |||
| ZYN_BASE_FLAGS = $(shell pkg-config --cflags liblo mxml) | |||
| ZYN_BASE_FLAGS += -Iexternal/zynaddsubfx -Iexternal/zynaddsubfx/rtosc | |||
| ifneq ($(WIN32),true) | |||
| ZYN_BASE_FLAGS += -DHAVE_ASYNC | |||
| endif | |||
| ZYN_BASE_LIBS = $(shell pkg-config --libs liblo mxml) -lpthread | |||
| ZYN_BASE_LIBS += $(LIBDL_LIBS) | |||
| # DSP flags | |||
| ZYN_DSP_FLAGS = $(ZYN_BASE_FLAGS) | |||
| ZYN_DSP_FLAGS += $(shell pkg-config --cflags fftw3 zlib) | |||
| ZYN_DSP_LIBS = $(ZYN_BASE_LIBS) | |||
| ZYN_DSP_LIBS += $(shell pkg-config --libs fftw3 zlib) | |||
| ifeq ($(SKIP_ZYN_SYNTH),true) | |||
| BASE_FLAGS += -DSKIP_ZYN_SYNTH | |||
| else | |||
| # UI flags | |||
| ifeq ($(HAVE_ZYN_UI_DEPS),true) | |||
| # Common UI flags | |||
| ZYN_UI_FLAGS = $(ZYN_BASE_FLAGS) | |||
| ZYN_UI_LIBS = $(ZYN_BASE_LIBS) | |||
| # NTK or FLTK UI flags | |||
| ifeq ($(HAVE_NTK),true) | |||
| FLUID = ntk-fluid | |||
| ZYN_UI_FLAGS += $(shell pkg-config --cflags ntk_images ntk) -DNTK_GUI | |||
| ZYN_UI_LIBS += $(shell pkg-config --libs ntk_images ntk) | |||
| else # HAVE_NTK | |||
| FLUID = fluid | |||
| ZYN_UI_FLAGS += $(shell fltk-config --use-images --cxxflags) -DFLTK_GUI | |||
| ZYN_UI_LIBS += $(shell fltk-config --use-images --ldflags) | |||
| endif # HAVE_NTK | |||
| # UI extra flags | |||
| ifeq ($(HAVE_X11),true) | |||
| ZYN_UI_FLAGS += $(shell pkg-config --cflags x11) | |||
| ZYN_UI_LIBS += $(shell pkg-config --libs x11) | |||
| endif | |||
| ifeq ($(LINUX),true) | |||
| ZYN_UI_LIBS += -lrt | |||
| endif | |||
| else # HAVE_ZYN_UI_DEPS | |||
| ZYN_DSP_FLAGS += -DNO_UI | |||
| endif # SKIP_ZYN_SYNTH | |||
| endif # HAVE_ZYN_UI_DEPS | |||
| endif # HAVE_ZYN_DEPS | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| NATIVE_PLUGINS_LIBS += $(DGL_LIBS) | |||
| NATIVE_PLUGINS_LIBS += $(PROJECTM_LIBS) | |||
| NATIVE_PLUGINS_LIBS += $(ZYN_DSP_LIBS) | |||
| NATIVE_PLUGINS_LIBS += $(ZITA_DSP_LIBS) | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| ifeq ($(HAVE_DGL),true) | |||
| ALL_LIBS += $(MODULEDIR)/dgl.a | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| all: | |||
| install_external_plugins: | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| ifeq ($(HAVE_ZYN_UI_DEPS),true) | |||
| # Create directories (zynaddsubfx) | |||
| install -d $(DESTDIR)$(DATADIR)/carla/resources/zynaddsubfx | |||
| # Install resources (zynaddsubfx) | |||
| install -m 644 \ | |||
| bin/resources/zynaddsubfx/*.png \ | |||
| $(DESTDIR)$(DATADIR)/carla/resources/zynaddsubfx | |||
| install -m 755 \ | |||
| bin/resources/zynaddsubfx-ui \ | |||
| $(DESTDIR)$(DATADIR)/carla/resources | |||
| endif | |||
| endif | |||
| features_print_external_plugins: | |||
| @printf -- "\n" | |||
| @printf -- "$(tS)---> External plugins: $(tE)\n" | |||
| ifeq ($(HAVE_DGL),true) | |||
| @printf -- "DPF Plugins: $(ANS_YES) (with UI)\n" | |||
| ifeq ($(HAVE_PROJECTM),true) | |||
| @printf -- "DPF ProM: $(ANS_YES)\n" | |||
| else | |||
| @printf -- "DPF ProM: $(ANS_NO) $(mS)missing libprojectM$(mE)\n" | |||
| endif | |||
| else | |||
| @printf -- "DPF Plugins: $(ANS_YES) (without UI)\n" | |||
| ifeq ($(HAVE_PROJECTM),true) | |||
| @printf -- "DPF ProM: $(ANS_NO) $(mS)missing OpenGL$(mE)\n" | |||
| else | |||
| @printf -- "DPF ProM: $(ANS_NO) $(mS)missing OpenGL and libprojectM$(mE)\n" | |||
| endif | |||
| endif | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| ifeq ($(HAVE_ZYN_UI_DEPS),true) | |||
| ifeq ($(HAVE_NTK),true) | |||
| @printf -- "ZynAddSubFX: $(ANS_YES) (with NTK UI)\n" | |||
| else | |||
| @printf -- "ZynAddSubFX: $(ANS_YES) (with FLTK UI)\n" | |||
| endif | |||
| else | |||
| @printf -- "ZynAddSubFX: $(ANS_YES) (without UI) $(mS)FLTK or NTK missing$(mE)\n" | |||
| endif | |||
| else | |||
| @printf -- "ZynAddSubFX: $(ANS_NO) $(mS)liblo, fftw3, mxml or zlib missing$(mE)\n" | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| @@ -1,66 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaDefines.h" | |||
| #include "CarlaNative.h" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // DISTRHO plugins | |||
| extern void carla_register_native_plugin_distrho_3bandeq(void); | |||
| extern void carla_register_native_plugin_distrho_3bandsplitter(void); | |||
| extern void carla_register_native_plugin_distrho_kars(void); | |||
| extern void carla_register_native_plugin_distrho_nekobi(void); | |||
| extern void carla_register_native_plugin_distrho_pingpongpan(void); | |||
| extern void carla_register_native_plugin_distrho_prom(void); | |||
| // DISTRHO plugins (Juice) | |||
| extern void carla_register_native_plugin_distrho_vectorjuice(void); | |||
| extern void carla_register_native_plugin_distrho_wobblejuice(void); | |||
| // ZynAddSubFX | |||
| extern void carla_register_native_plugin_zynaddsubfx_fx(void); | |||
| extern void carla_register_native_plugin_zynaddsubfx_synth(void); | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| void carla_register_all_native_external_plugins(void) | |||
| { | |||
| // DISTRHO Plugins | |||
| carla_register_native_plugin_distrho_3bandeq(); | |||
| carla_register_native_plugin_distrho_3bandsplitter(); | |||
| carla_register_native_plugin_distrho_kars(); | |||
| carla_register_native_plugin_distrho_nekobi(); | |||
| carla_register_native_plugin_distrho_pingpongpan(); | |||
| #if defined(HAVE_DGL) && defined(HAVE_PROJECTM) | |||
| carla_register_native_plugin_distrho_prom(); | |||
| #endif | |||
| // DISTRHO plugins (Juice) | |||
| carla_register_native_plugin_distrho_vectorjuice(); | |||
| carla_register_native_plugin_distrho_wobblejuice(); | |||
| #ifdef HAVE_ZYN_DEPS | |||
| // ZynAddSubFX | |||
| carla_register_native_plugin_zynaddsubfx_fx(); | |||
| # ifndef SKIP_ZYN_SYNTH | |||
| carla_register_native_plugin_zynaddsubfx_synth(); | |||
| # endif | |||
| #endif | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -1,470 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaNative.h" | |||
| #include "CarlaMIDI.h" | |||
| #include "CarlaUtils.hpp" | |||
| #ifndef CARLA_EXTERNAL_PLUGINS_INCLUDED_DIRECTLY | |||
| # define DESCFUNCS \ | |||
| nullptr, nullptr, nullptr, nullptr, nullptr, \ | |||
| nullptr, nullptr, nullptr, nullptr, nullptr, \ | |||
| nullptr, nullptr, nullptr, nullptr, nullptr, \ | |||
| nullptr, nullptr, nullptr, nullptr, nullptr, nullptr | |||
| static const NativePluginDescriptor sNativePluginDescriptors[] = { | |||
| #endif | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // DISTRHO Plugins | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_EQ, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 6, | |||
| /* paramOuts */ 0, | |||
| /* name */ "3 Band EQ", | |||
| /* label */ "3bandeq", | |||
| /* maker */ "falkTX, Michael Gruhn", | |||
| /* copyright */ "LGPL", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_EQ, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 6, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 6, | |||
| /* paramOuts */ 0, | |||
| /* name */ "3 Band Splitter", | |||
| /* label */ "3bandsplitter", | |||
| /* maker */ "falkTX, Michael Gruhn", | |||
| /* copyright */ "LGPL", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_SYNTH, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 0, | |||
| /* audioOuts */ 1, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 1, | |||
| /* paramOuts */ 0, | |||
| /* name */ "Kars", | |||
| /* label */ "kars", | |||
| /* maker */ "falkTX, Chris Cannam", | |||
| /* copyright */ "ISC", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_SYNTH, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH), | |||
| #endif | |||
| /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES | |||
| |NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF), | |||
| /* audioIns */ 0, | |||
| /* audioOuts */ 1, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 8, | |||
| /* paramOuts */ 0, | |||
| /* name */ "Nekobi", | |||
| /* label */ "nekobi", | |||
| /* maker */ "falkTX, Sean Bolton and others", | |||
| /* copyright */ "GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "Ping Pong Pan", | |||
| /* label */ "pingpongpan", | |||
| /* maker */ "falkTX, Michael Gruhn", | |||
| /* copyright */ "LGPL", | |||
| DESCFUNCS | |||
| }, | |||
| #ifdef HAVE_DGL | |||
| #ifdef HAVE_PROJECTM | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 1, | |||
| /* audioOuts */ 1, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 0, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ProM", | |||
| /* label */ "prom", | |||
| /* maker */ "falkTX", | |||
| /* copyright */ "LGPL", | |||
| DESCFUNCS | |||
| }, | |||
| #endif // HAVE_PROJECTM | |||
| #endif // HAVE_DGL | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // DISTRHO plugins (Juice) | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DYNAMICS, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 6, | |||
| /* paramOuts */ 0, | |||
| /* name */ "WobbleJuice", | |||
| /* label */ "wobblejuice", | |||
| /* maker */ "Andre Sklenar", | |||
| /* copyright */ "GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 8, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 13, | |||
| /* paramOuts */ 4, | |||
| /* name */ "VectorJuice", | |||
| /* label */ "vectorjuice", | |||
| /* maker */ "Andre Sklenar", | |||
| /* copyright */ "GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // ZynAddSubFX | |||
| #ifdef HAVE_ZYN_DEPS | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_MODULATOR, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_USES_PANNING | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 11-2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynAlienWah", | |||
| /* label */ "zynalienwah", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_MODULATOR, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_USES_PANNING | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 12-2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynChorus", | |||
| /* label */ "zynchorus", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_MODULATOR, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_USES_PANNING | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 11-2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynDistortion", | |||
| /* label */ "zyndistortion", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_FILTER, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_USES_PANNING | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 10-2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynDynamicFilter", | |||
| /* label */ "zyndynamicfilter", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DELAY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_USES_PANNING | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 7-2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynEcho", | |||
| /* label */ "zynecho", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_MODULATOR, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_USES_PANNING | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 15-2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynPhaser", | |||
| /* label */ "zynphaser", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DELAY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_USES_PANNING | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 13-2, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynReverb", | |||
| /* label */ "zynreverb", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| # ifndef SKIP_ZYN_SYNTH | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_SYNTH, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH | |||
| # ifdef HAVE_ZYN_UI_DEPS | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| # endif | |||
| |NATIVE_PLUGIN_USES_MULTI_PROGS | |||
| |NATIVE_PLUGIN_USES_STATE), | |||
| /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES | |||
| |NATIVE_PLUGIN_SUPPORTS_NOTE_AFTERTOUCH | |||
| |NATIVE_PLUGIN_SUPPORTS_PITCHBEND | |||
| |NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF), | |||
| /* audioIns */ 0, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 6, | |||
| /* paramOuts */ 0, | |||
| /* name */ "ZynAddSubFX", | |||
| /* label */ "zynaddsubfx", | |||
| /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul", | |||
| /* copyright */ "GNU GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| # endif // ! SKIP_ZYN_SYNTH | |||
| #endif // HAVE_ZYN_DEPS | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // Experimental plugins | |||
| #ifdef HAVE_EXPERIMENTAL_PLUGINS | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_MODULATOR, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS | |||
| |NATIVE_PLUGIN_USES_STATE), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 1, | |||
| /* audioOuts */ 1, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 6, | |||
| /* paramOuts */ 0, | |||
| /* name */ "AT1", | |||
| /* label */ "at1", | |||
| /* maker */ "falkTX, Fons Adriaensen", | |||
| /* copyright */ "GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_FILTER, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 6, | |||
| /* paramOuts */ 0, | |||
| /* name */ "BLS1", | |||
| /* label */ "bls1", | |||
| /* maker */ "falkTX, Fons Adriaensen", | |||
| /* copyright */ "GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DELAY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 4, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 10, | |||
| /* paramOuts */ 0, | |||
| /* name */ "REV1 (Ambisonic)", | |||
| /* label */ "rev1-ambisonic", | |||
| /* maker */ "falkTX, Fons Adriaensen", | |||
| /* copyright */ "GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DELAY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 10, | |||
| /* paramOuts */ 0, | |||
| /* name */ "REV1 (Stereo)", | |||
| /* label */ "rev1-stereo", | |||
| /* maker */ "falkTX, Fons Adriaensen", | |||
| /* copyright */ "GPL v2+", | |||
| DESCFUNCS | |||
| }, | |||
| #endif // HAVE_EXPERIMENTAL_PLUGINS | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| #ifndef CARLA_EXTERNAL_PLUGINS_INCLUDED_DIRECTLY | |||
| } | |||
| #endif | |||
| @@ -1,85 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // config fix | |||
| #include "distrho-3bandeq/DistrhoPluginInfo.h" | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-3bandeq/DistrhoArtwork3BandEQ.cpp" | |||
| #include "distrho-3bandeq/DistrhoPlugin3BandEQ.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "distrho-3bandeq/DistrhoUI3BandEQ.cpp" | |||
| #endif | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "DistrhoUIMain.cpp" | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor _3bandeqDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_EQ, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ DistrhoPlugin3BandEQ::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "3bandeq", | |||
| /* maker */ "falkTX, Michael Gruhn", | |||
| /* copyright */ "LGPL", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_3bandeq(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_3bandeq() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&_3bandeqDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,40 +0,0 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_DISTRHOARTWORK3BANDEQ_HPP | |||
| #define BINARY_DISTRHOARTWORK3BANDEQ_HPP | |||
| namespace DistrhoArtwork3BandEQ | |||
| { | |||
| extern const char* aboutData; | |||
| const unsigned int aboutDataSize = 172710; | |||
| const unsigned int aboutWidth = 303; | |||
| const unsigned int aboutHeight = 190; | |||
| extern const char* aboutButtonHoverData; | |||
| const unsigned int aboutButtonHoverDataSize = 5888; | |||
| const unsigned int aboutButtonHoverWidth = 92; | |||
| const unsigned int aboutButtonHoverHeight = 16; | |||
| extern const char* aboutButtonNormalData; | |||
| const unsigned int aboutButtonNormalDataSize = 5888; | |||
| const unsigned int aboutButtonNormalWidth = 92; | |||
| const unsigned int aboutButtonNormalHeight = 16; | |||
| extern const char* backgroundData; | |||
| const unsigned int backgroundDataSize = 437472; | |||
| const unsigned int backgroundWidth = 392; | |||
| const unsigned int backgroundHeight = 372; | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 15376; | |||
| const unsigned int knobWidth = 62; | |||
| const unsigned int knobHeight = 62; | |||
| extern const char* sliderData; | |||
| const unsigned int sliderDataSize = 6000; | |||
| const unsigned int sliderWidth = 50; | |||
| const unsigned int sliderHeight = 30; | |||
| } | |||
| #endif // BINARY_DISTRHOARTWORK3BANDEQ_HPP | |||
| @@ -1,264 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandEQ Plugin, based on 3BandEQ by Michael Gruhn | |||
| * Copyright (C) 2007 Michael Gruhn <michael-gruhn@web.de> | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPlugin3BandEQ.hpp" | |||
| #include <cmath> | |||
| static const float kAMP_DB = 8.656170245f; | |||
| static const float kDC_ADD = 1e-30f; | |||
| static const float kPI = 3.141592654f; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoPlugin3BandEQ::DistrhoPlugin3BandEQ() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| loadProgram(0); | |||
| // reset | |||
| deactivate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void DistrhoPlugin3BandEQ::initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramLow: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Low"; | |||
| parameter.symbol = "low"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramMid: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Mid"; | |||
| parameter.symbol = "mid"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramHigh: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "High"; | |||
| parameter.symbol = "high"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramMaster: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Master"; | |||
| parameter.symbol = "master"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramLowMidFreq: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Low-Mid Freq"; | |||
| parameter.symbol = "low_mid"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 440.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1000.0f; | |||
| break; | |||
| case paramMidHighFreq: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Mid-High Freq"; | |||
| parameter.symbol = "mid_high"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 1000.0f; | |||
| parameter.ranges.min = 1000.0f; | |||
| parameter.ranges.max = 20000.0f; | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoPlugin3BandEQ::initProgramName(uint32_t index, String& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float DistrhoPlugin3BandEQ::getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramLow: | |||
| return fLow; | |||
| case paramMid: | |||
| return fMid; | |||
| case paramHigh: | |||
| return fHigh; | |||
| case paramMaster: | |||
| return fMaster; | |||
| case paramLowMidFreq: | |||
| return fLowMidFreq; | |||
| case paramMidHighFreq: | |||
| return fMidHighFreq; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void DistrhoPlugin3BandEQ::setParameterValue(uint32_t index, float value) | |||
| { | |||
| if (getSampleRate() <= 0.0) | |||
| return; | |||
| switch (index) | |||
| { | |||
| case paramLow: | |||
| fLow = value; | |||
| lowVol = std::exp( (fLow/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramMid: | |||
| fMid = value; | |||
| midVol = std::exp( (fMid/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramHigh: | |||
| fHigh = value; | |||
| highVol = std::exp( (fHigh/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramMaster: | |||
| fMaster = value; | |||
| outVol = std::exp( (fMaster/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramLowMidFreq: | |||
| fLowMidFreq = std::fmin(value, fMidHighFreq); | |||
| freqLP = fLowMidFreq; | |||
| xLP = std::exp(-2.0f * kPI * freqLP / (float)getSampleRate()); | |||
| a0LP = 1.0f - xLP; | |||
| b1LP = -xLP; | |||
| break; | |||
| case paramMidHighFreq: | |||
| fMidHighFreq = std::fmax(value, fLowMidFreq); | |||
| freqHP = fMidHighFreq; | |||
| xHP = std::exp(-2.0f * kPI * freqHP / (float)getSampleRate()); | |||
| a0HP = 1.0f - xHP; | |||
| b1HP = -xHP; | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoPlugin3BandEQ::loadProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fLow = 0.0f; | |||
| fMid = 0.0f; | |||
| fHigh = 0.0f; | |||
| fMaster = 0.0f; | |||
| fLowMidFreq = 220.0f; | |||
| fMidHighFreq = 2000.0f; | |||
| // Internal stuff | |||
| lowVol = midVol = highVol = outVol = 1.0f; | |||
| freqLP = 200.0f; | |||
| freqHP = 2000.0f; | |||
| // reset filter values | |||
| activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void DistrhoPlugin3BandEQ::activate() | |||
| { | |||
| const float sr = (float)getSampleRate(); | |||
| xLP = std::exp(-2.0f * kPI * freqLP / sr); | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| // don't ask me why, but this fixes a crash/exception below on windows... | |||
| printf("%f\n", -xLP); | |||
| #endif | |||
| a0LP = 1.0f - xLP; | |||
| b1LP = -xLP; | |||
| xHP = std::exp(-2.0f * kPI * freqHP / sr); | |||
| a0HP = 1.0f - xHP; | |||
| b1HP = -xHP; | |||
| } | |||
| void DistrhoPlugin3BandEQ::deactivate() | |||
| { | |||
| out1LP = out2LP = out1HP = out2HP = 0.0f; | |||
| tmp1LP = tmp2LP = tmp1HP = tmp2HP = 0.0f; | |||
| } | |||
| void DistrhoPlugin3BandEQ::run(const float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| const float* in1 = inputs[0]; | |||
| const float* in2 = inputs[1]; | |||
| float* out1 = outputs[0]; | |||
| float* out2 = outputs[1]; | |||
| for (uint32_t i=0; i < frames; ++i) | |||
| { | |||
| tmp1LP = a0LP * in1[i] - b1LP * tmp1LP + kDC_ADD; | |||
| tmp2LP = a0LP * in2[i] - b1LP * tmp2LP + kDC_ADD; | |||
| out1LP = tmp1LP - kDC_ADD; | |||
| out2LP = tmp2LP - kDC_ADD; | |||
| tmp1HP = a0HP * in1[i] - b1HP * tmp1HP + kDC_ADD; | |||
| tmp2HP = a0HP * in2[i] - b1HP * tmp2HP + kDC_ADD; | |||
| out1HP = in1[i] - tmp1HP - kDC_ADD; | |||
| out2HP = in2[i] - tmp2HP - kDC_ADD; | |||
| out1[i] = (out1LP*lowVol + (in1[i] - out1LP - out1HP)*midVol + out1HP*highVol) * outVol; | |||
| out2[i] = (out2LP*lowVol + (in2[i] - out2LP - out2HP)*midVol + out2HP*highVol) * outVol; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new DistrhoPlugin3BandEQ(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,123 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandEQ Plugin, based on 3BandEQ by Michael Gruhn | |||
| * Copyright (C) 2007 Michael Gruhn <michael-gruhn@web.de> | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_3BANDEQ_HPP_INCLUDED | |||
| #define DISTRHO_PLUGIN_3BANDEQ_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoPlugin3BandEQ : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramLow = 0, | |||
| paramMid, | |||
| paramHigh, | |||
| paramMaster, | |||
| paramLowMidFreq, | |||
| paramMidHighFreq, | |||
| paramCount | |||
| }; | |||
| DistrhoPlugin3BandEQ(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "3BandEQ"; | |||
| } | |||
| const char* getDescription() const override | |||
| { | |||
| return "3 Band Equalizer, stereo version."; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "DISTRHO"; | |||
| } | |||
| const char* getHomePage() const override | |||
| { | |||
| return "https://github.com/DISTRHO/Mini-Series"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "LGPL"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return d_version(1, 0, 0); | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('D', '3', 'E', 'Q'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t index, Parameter& parameter) override; | |||
| void initProgramName(uint32_t index, String& programName) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t index) const override; | |||
| void setParameterValue(uint32_t index, float value) override; | |||
| void loadProgram(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void activate() override; | |||
| void deactivate() override; | |||
| void run(const float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float fLow, fMid, fHigh, fMaster, fLowMidFreq, fMidHighFreq; | |||
| float lowVol, midVol, highVol, outVol; | |||
| float freqLP, freqHP; | |||
| float xLP, a0LP, b1LP; | |||
| float xHP, a0HP, b1HP; | |||
| float out1LP, out2LP, out1HP, out2HP; | |||
| float tmp1LP, tmp2LP, tmp1HP, tmp2HP; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPlugin3BandEQ) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_PLUGIN_3BANDEQ_HPP_INCLUDED | |||
| @@ -1,32 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandEQ Plugin, based on 3BandEQ by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_BRAND "DISTRHO" | |||
| #define DISTRHO_PLUGIN_NAME "3 Band EQ" | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandEQ" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_RT_SAFE 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:EQPlugin" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,211 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandEQ Plugin, based on 3BandEQ by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPlugin3BandEQ.hpp" | |||
| #include "DistrhoUI3BandEQ.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| namespace Art = DistrhoArtwork3BandEQ; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUI3BandEQ::DistrhoUI3BandEQ() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, GL_BGR), | |||
| fAboutWindow(this) | |||
| { | |||
| // about | |||
| Image aboutImage(Art::aboutData, Art::aboutWidth, Art::aboutHeight, GL_BGR); | |||
| fAboutWindow.setImage(aboutImage); | |||
| // sliders | |||
| Image sliderImage(Art::sliderData, Art::sliderWidth, Art::sliderHeight); | |||
| Point<int> sliderPosStart(57, 43); | |||
| Point<int> sliderPosEnd(57, 43 + 160); | |||
| // slider Low | |||
| fSliderLow = new ImageSlider(this, sliderImage); | |||
| fSliderLow->setId(DistrhoPlugin3BandEQ::paramLow); | |||
| fSliderLow->setInverted(true); | |||
| fSliderLow->setStartPos(sliderPosStart); | |||
| fSliderLow->setEndPos(sliderPosEnd); | |||
| fSliderLow->setRange(-24.0f, 24.0f); | |||
| fSliderLow->setCallback(this); | |||
| // slider Mid | |||
| sliderPosStart.setX(120); | |||
| sliderPosEnd.setX(120); | |||
| fSliderMid = new ImageSlider(this, sliderImage); | |||
| fSliderMid->setId(DistrhoPlugin3BandEQ::paramMid); | |||
| fSliderMid->setInverted(true); | |||
| fSliderMid->setStartPos(sliderPosStart); | |||
| fSliderMid->setEndPos(sliderPosEnd); | |||
| fSliderMid->setRange(-24.0f, 24.0f); | |||
| fSliderMid->setCallback(this); | |||
| // slider High | |||
| sliderPosStart.setX(183); | |||
| sliderPosEnd.setX(183); | |||
| fSliderHigh = new ImageSlider(this, sliderImage); | |||
| fSliderHigh->setId(DistrhoPlugin3BandEQ::paramHigh); | |||
| fSliderHigh->setInverted(true); | |||
| fSliderHigh->setStartPos(sliderPosStart); | |||
| fSliderHigh->setEndPos(sliderPosEnd); | |||
| fSliderHigh->setRange(-24.0f, 24.0f); | |||
| fSliderHigh->setCallback(this); | |||
| // slider Master | |||
| sliderPosStart.setX(287); | |||
| sliderPosEnd.setX(287); | |||
| fSliderMaster = new ImageSlider(this, sliderImage); | |||
| fSliderMaster->setId(DistrhoPlugin3BandEQ::paramMaster); | |||
| fSliderMaster->setInverted(true); | |||
| fSliderMaster->setStartPos(sliderPosStart); | |||
| fSliderMaster->setEndPos(sliderPosEnd); | |||
| fSliderMaster->setRange(-24.0f, 24.0f); | |||
| fSliderMaster->setCallback(this); | |||
| // knobs | |||
| Image knobImage(Art::knobData, Art::knobWidth, Art::knobHeight); | |||
| // knob Low-Mid | |||
| fKnobLowMid = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobLowMid->setId(DistrhoPlugin3BandEQ::paramLowMidFreq); | |||
| fKnobLowMid->setAbsolutePos(65, 269); | |||
| fKnobLowMid->setRange(0.0f, 1000.0f); | |||
| fKnobLowMid->setDefault(440.0f); | |||
| fKnobLowMid->setRotationAngle(270); | |||
| fKnobLowMid->setCallback(this); | |||
| // knob Mid-High | |||
| fKnobMidHigh = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobMidHigh->setId(DistrhoPlugin3BandEQ::paramMidHighFreq); | |||
| fKnobMidHigh->setAbsolutePos(159, 269); | |||
| fKnobMidHigh->setRange(1000.0f, 20000.0f); | |||
| fKnobMidHigh->setDefault(1000.0f); | |||
| fKnobMidHigh->setRotationAngle(270); | |||
| fKnobMidHigh->setCallback(this); | |||
| // about button | |||
| Image aboutImageNormal(Art::aboutButtonNormalData, Art::aboutButtonNormalWidth, Art::aboutButtonNormalHeight); | |||
| Image aboutImageHover(Art::aboutButtonHoverData, Art::aboutButtonHoverWidth, Art::aboutButtonHoverHeight); | |||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | |||
| fButtonAbout->setAbsolutePos(264, 300); | |||
| fButtonAbout->setCallback(this); | |||
| // set default values | |||
| programLoaded(0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void DistrhoUI3BandEQ::parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case DistrhoPlugin3BandEQ::paramLow: | |||
| fSliderLow->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandEQ::paramMid: | |||
| fSliderMid->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandEQ::paramHigh: | |||
| fSliderHigh->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandEQ::paramMaster: | |||
| fSliderMaster->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandEQ::paramLowMidFreq: | |||
| fKnobLowMid->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandEQ::paramMidHighFreq: | |||
| fKnobMidHigh->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoUI3BandEQ::programLoaded(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fSliderLow->setValue(0.0f); | |||
| fSliderMid->setValue(0.0f); | |||
| fSliderHigh->setValue(0.0f); | |||
| fSliderMaster->setValue(0.0f); | |||
| fKnobLowMid->setValue(220.0f); | |||
| fKnobMidHigh->setValue(2000.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void DistrhoUI3BandEQ::imageButtonClicked(ImageButton* button, int) | |||
| { | |||
| if (button != fButtonAbout) | |||
| return; | |||
| fAboutWindow.exec(); | |||
| } | |||
| void DistrhoUI3BandEQ::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), true); | |||
| } | |||
| void DistrhoUI3BandEQ::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), false); | |||
| } | |||
| void DistrhoUI3BandEQ::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| setParameterValue(knob->getId(), value); | |||
| } | |||
| void DistrhoUI3BandEQ::imageSliderDragStarted(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), true); | |||
| } | |||
| void DistrhoUI3BandEQ::imageSliderDragFinished(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), false); | |||
| } | |||
| void DistrhoUI3BandEQ::imageSliderValueChanged(ImageSlider* slider, float value) | |||
| { | |||
| setParameterValue(slider->getId(), value); | |||
| } | |||
| void DistrhoUI3BandEQ::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new DistrhoUI3BandEQ(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,72 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandEQ Plugin, based on 3BandEQ by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_UI_3BANDEQ_HPP_INCLUDED | |||
| #define DISTRHO_UI_3BANDEQ_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageWidgets.hpp" | |||
| #include "DistrhoArtwork3BandEQ.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoUI3BandEQ : public UI, | |||
| public ImageButton::Callback, | |||
| public ImageKnob::Callback, | |||
| public ImageSlider::Callback | |||
| { | |||
| public: | |||
| DistrhoUI3BandEQ(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t index, float value) override; | |||
| void programLoaded(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageButtonClicked(ImageButton* button, int) override; | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void imageSliderDragStarted(ImageSlider* slider) override; | |||
| void imageSliderDragFinished(ImageSlider* slider) override; | |||
| void imageSliderValueChanged(ImageSlider* slider, float value) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageAboutWindow fAboutWindow; | |||
| ScopedPointer<ImageButton> fButtonAbout; | |||
| ScopedPointer<ImageKnob> fKnobLowMid, fKnobMidHigh; | |||
| ScopedPointer<ImageSlider> fSliderLow, fSliderMid, fSliderHigh, fSliderMaster; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUI3BandEQ) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_UI_3BANDEQ_HPP_INCLUDED | |||
| @@ -1,85 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // config fix | |||
| #include "distrho-3bandsplitter/DistrhoPluginInfo.h" | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-3bandsplitter/DistrhoArtwork3BandSplitter.cpp" | |||
| #include "distrho-3bandsplitter/DistrhoPlugin3BandSplitter.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "distrho-3bandsplitter/DistrhoUI3BandSplitter.cpp" | |||
| #endif | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "DistrhoUIMain.cpp" | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor _3bandsplitterDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_EQ, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ DistrhoPlugin3BandSplitter::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "3bandsplitter", | |||
| /* maker */ "falkTX, Michael Gruhn", | |||
| /* copyright */ "LGPL", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_3bandsplitter(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_3bandsplitter() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&_3bandsplitterDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,40 +0,0 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_DISTRHOARTWORK3BANDSPLITTER_HPP | |||
| #define BINARY_DISTRHOARTWORK3BANDSPLITTER_HPP | |||
| namespace DistrhoArtwork3BandSplitter | |||
| { | |||
| extern const char* aboutData; | |||
| const unsigned int aboutDataSize = 172710; | |||
| const unsigned int aboutWidth = 303; | |||
| const unsigned int aboutHeight = 190; | |||
| extern const char* aboutButtonHoverData; | |||
| const unsigned int aboutButtonHoverDataSize = 5888; | |||
| const unsigned int aboutButtonHoverWidth = 92; | |||
| const unsigned int aboutButtonHoverHeight = 16; | |||
| extern const char* aboutButtonNormalData; | |||
| const unsigned int aboutButtonNormalDataSize = 5888; | |||
| const unsigned int aboutButtonNormalWidth = 92; | |||
| const unsigned int aboutButtonNormalHeight = 16; | |||
| extern const char* backgroundData; | |||
| const unsigned int backgroundDataSize = 437472; | |||
| const unsigned int backgroundWidth = 392; | |||
| const unsigned int backgroundHeight = 372; | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 15376; | |||
| const unsigned int knobWidth = 62; | |||
| const unsigned int knobHeight = 62; | |||
| extern const char* sliderData; | |||
| const unsigned int sliderDataSize = 6000; | |||
| const unsigned int sliderWidth = 50; | |||
| const unsigned int sliderHeight = 30; | |||
| } | |||
| #endif // BINARY_DISTRHOARTWORK3BANDSPLITTER_HPP | |||
| @@ -1,272 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandSplitter Plugin, based on 3BandSplitter by Michael Gruhn | |||
| * Copyright (C) 2007 Michael Gruhn <michael-gruhn@web.de> | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPlugin3BandSplitter.hpp" | |||
| #include <cmath> | |||
| static const float kAMP_DB = 8.656170245f; | |||
| static const float kDC_ADD = 1e-30f; | |||
| static const float kPI = 3.141592654f; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoPlugin3BandSplitter::DistrhoPlugin3BandSplitter() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| loadProgram(0); | |||
| // reset | |||
| deactivate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void DistrhoPlugin3BandSplitter::initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramLow: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Low"; | |||
| parameter.symbol = "low"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramMid: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Mid"; | |||
| parameter.symbol = "mid"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramHigh: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "High"; | |||
| parameter.symbol = "high"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramMaster: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Master"; | |||
| parameter.symbol = "master"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -24.0f; | |||
| parameter.ranges.max = 24.0f; | |||
| break; | |||
| case paramLowMidFreq: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Low-Mid Freq"; | |||
| parameter.symbol = "low_mid"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 440.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1000.0f; | |||
| break; | |||
| case paramMidHighFreq: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Mid-High Freq"; | |||
| parameter.symbol = "mid_high"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 1000.0f; | |||
| parameter.ranges.min = 1000.0f; | |||
| parameter.ranges.max = 20000.0f; | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoPlugin3BandSplitter::initProgramName(uint32_t index, String& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float DistrhoPlugin3BandSplitter::getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramLow: | |||
| return fLow; | |||
| case paramMid: | |||
| return fMid; | |||
| case paramHigh: | |||
| return fHigh; | |||
| case paramMaster: | |||
| return fMaster; | |||
| case paramLowMidFreq: | |||
| return fLowMidFreq; | |||
| case paramMidHighFreq: | |||
| return fMidHighFreq; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void DistrhoPlugin3BandSplitter::setParameterValue(uint32_t index, float value) | |||
| { | |||
| if (getSampleRate() <= 0.0) | |||
| return; | |||
| switch (index) | |||
| { | |||
| case paramLow: | |||
| fLow = value; | |||
| lowVol = std::exp( (fLow/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramMid: | |||
| fMid = value; | |||
| midVol = std::exp( (fMid/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramHigh: | |||
| fHigh = value; | |||
| highVol = std::exp( (fHigh/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramMaster: | |||
| fMaster = value; | |||
| outVol = std::exp( (fMaster/48.0f) * 48.0f / kAMP_DB); | |||
| break; | |||
| case paramLowMidFreq: | |||
| fLowMidFreq = std::fmin(value, fMidHighFreq); | |||
| freqLP = fLowMidFreq; | |||
| xLP = std::exp(-2.0f * kPI * freqLP / (float)getSampleRate()); | |||
| a0LP = 1.0f - xLP; | |||
| b1LP = -xLP; | |||
| break; | |||
| case paramMidHighFreq: | |||
| fMidHighFreq = std::fmax(value, fLowMidFreq); | |||
| freqHP = fMidHighFreq; | |||
| xHP = std::exp(-2.0f * kPI * freqHP / (float)getSampleRate()); | |||
| a0HP = 1.0f - xHP; | |||
| b1HP = -xHP; | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoPlugin3BandSplitter::loadProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fLow = 0.0f; | |||
| fMid = 0.0f; | |||
| fHigh = 0.0f; | |||
| fMaster = 0.0f; | |||
| fLowMidFreq = 220.0f; | |||
| fMidHighFreq = 2000.0f; | |||
| // Internal stuff | |||
| lowVol = midVol = highVol = outVol = 1.0f; | |||
| freqLP = 200.0f; | |||
| freqHP = 2000.0f; | |||
| // reset filter values | |||
| activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void DistrhoPlugin3BandSplitter::activate() | |||
| { | |||
| const float sr = (float)getSampleRate(); | |||
| xLP = std::exp(-2.0f * kPI * freqLP / sr); | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| // don't ask me why, but this fixes a crash/exception below on windows... | |||
| printf("%f\n", -xLP); | |||
| #endif | |||
| a0LP = 1.0f - xLP; | |||
| b1LP = -xLP; | |||
| xHP = std::exp(-2.0f * kPI * freqHP / sr); | |||
| a0HP = 1.0f - xHP; | |||
| b1HP = -xHP; | |||
| } | |||
| void DistrhoPlugin3BandSplitter::deactivate() | |||
| { | |||
| out1LP = out2LP = out1HP = out2HP = 0.0f; | |||
| tmp1LP = tmp2LP = tmp1HP = tmp2HP = 0.0f; | |||
| } | |||
| void DistrhoPlugin3BandSplitter::run(const float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| const float* in1 = inputs[0]; | |||
| const float* in2 = inputs[1]; | |||
| float* out1 = outputs[0]; | |||
| float* out2 = outputs[1]; | |||
| float* out3 = outputs[2]; | |||
| float* out4 = outputs[3]; | |||
| float* out5 = outputs[4]; | |||
| float* out6 = outputs[5]; | |||
| for (uint32_t i=0; i < frames; ++i) | |||
| { | |||
| tmp1LP = a0LP * in1[i] - b1LP * tmp1LP + kDC_ADD; | |||
| tmp2LP = a0LP * in2[i] - b1LP * tmp2LP + kDC_ADD; | |||
| out1LP = tmp1LP - kDC_ADD; | |||
| out2LP = tmp2LP - kDC_ADD; | |||
| tmp1HP = a0HP * in1[i] - b1HP * tmp1HP + kDC_ADD; | |||
| tmp2HP = a0HP * in2[i] - b1HP * tmp2HP + kDC_ADD; | |||
| out1HP = in1[i] - tmp1HP - kDC_ADD; | |||
| out2HP = in2[i] - tmp2HP - kDC_ADD; | |||
| out6[i] = out2HP*highVol * outVol; | |||
| out5[i] = out1HP*highVol * outVol; | |||
| out4[i] = (in2[i] - out2LP - out2HP)*midVol * outVol; | |||
| out3[i] = (in1[i] - out1LP - out1HP)*midVol * outVol; | |||
| out2[i] = out2LP*lowVol * outVol; | |||
| out1[i] = out1LP*lowVol * outVol; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new DistrhoPlugin3BandSplitter(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,123 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandSplitter Plugin, based on 3BandSplitter by Michael Gruhn | |||
| * Copyright (C) 2007 Michael Gruhn <michael-gruhn@web.de> | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_3BANDSPLITTER_HPP_INCLUDED | |||
| #define DISTRHO_PLUGIN_3BANDSPLITTER_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoPlugin3BandSplitter : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramLow = 0, | |||
| paramMid, | |||
| paramHigh, | |||
| paramMaster, | |||
| paramLowMidFreq, | |||
| paramMidHighFreq, | |||
| paramCount | |||
| }; | |||
| DistrhoPlugin3BandSplitter(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "3BandSplitter"; | |||
| } | |||
| const char* getDescription() const override | |||
| { | |||
| return "3 Band Equalizer, splitted output version."; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "DISTRHO"; | |||
| } | |||
| const char* getHomePage() const override | |||
| { | |||
| return "https://github.com/DISTRHO/Mini-Series"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "LGPL"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return d_version(1, 0, 0); | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('D', '3', 'E', 'S'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t index, Parameter& parameter) override; | |||
| void initProgramName(uint32_t index, String& programName) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t index) const override; | |||
| void setParameterValue(uint32_t index, float value) override; | |||
| void loadProgram(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void activate() override; | |||
| void deactivate() override; | |||
| void run(const float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float fLow, fMid, fHigh, fMaster, fLowMidFreq, fMidHighFreq; | |||
| float lowVol, midVol, highVol, outVol; | |||
| float freqLP, freqHP; | |||
| float xLP, a0LP, b1LP; | |||
| float xHP, a0HP, b1HP; | |||
| float out1LP, out2LP, out1HP, out2HP; | |||
| float tmp1LP, tmp2LP, tmp1HP, tmp2HP; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPlugin3BandSplitter) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_PLUGIN_3BANDSPLITTER_HPP_INCLUDED | |||
| @@ -1,32 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandSplitter Plugin, based on 3BandSplitter by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_BRAND "DISTRHO" | |||
| #define DISTRHO_PLUGIN_NAME "3 Band Splitter" | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandSplitter" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_RT_SAFE 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 6 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:EQPlugin" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,211 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandSplitter Plugin, based on 3BandSplitter by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPlugin3BandSplitter.hpp" | |||
| #include "DistrhoUI3BandSplitter.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| namespace Art = DistrhoArtwork3BandSplitter; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUI3BandSplitter::DistrhoUI3BandSplitter() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, GL_BGR), | |||
| fAboutWindow(this) | |||
| { | |||
| // about | |||
| Image aboutImage(Art::aboutData, Art::aboutWidth, Art::aboutHeight, GL_BGR); | |||
| fAboutWindow.setImage(aboutImage); | |||
| // sliders | |||
| Image sliderImage(Art::sliderData, Art::sliderWidth, Art::sliderHeight); | |||
| Point<int> sliderPosStart(57, 43); | |||
| Point<int> sliderPosEnd(57, 43 + 160); | |||
| // slider Low | |||
| fSliderLow = new ImageSlider(this, sliderImage); | |||
| fSliderLow->setId(DistrhoPlugin3BandSplitter::paramLow); | |||
| fSliderLow->setInverted(true); | |||
| fSliderLow->setStartPos(sliderPosStart); | |||
| fSliderLow->setEndPos(sliderPosEnd); | |||
| fSliderLow->setRange(-24.0f, 24.0f); | |||
| fSliderLow->setCallback(this); | |||
| // slider Mid | |||
| sliderPosStart.setX(120); | |||
| sliderPosEnd.setX(120); | |||
| fSliderMid = new ImageSlider(this, sliderImage); | |||
| fSliderMid->setId(DistrhoPlugin3BandSplitter::paramMid); | |||
| fSliderMid->setInverted(true); | |||
| fSliderMid->setStartPos(sliderPosStart); | |||
| fSliderMid->setEndPos(sliderPosEnd); | |||
| fSliderMid->setRange(-24.0f, 24.0f); | |||
| fSliderMid->setCallback(this); | |||
| // slider High | |||
| sliderPosStart.setX(183); | |||
| sliderPosEnd.setX(183); | |||
| fSliderHigh = new ImageSlider(this, sliderImage); | |||
| fSliderHigh->setId(DistrhoPlugin3BandSplitter::paramHigh); | |||
| fSliderHigh->setInverted(true); | |||
| fSliderHigh->setStartPos(sliderPosStart); | |||
| fSliderHigh->setEndPos(sliderPosEnd); | |||
| fSliderHigh->setRange(-24.0f, 24.0f); | |||
| fSliderHigh->setCallback(this); | |||
| // slider Master | |||
| sliderPosStart.setX(287); | |||
| sliderPosEnd.setX(287); | |||
| fSliderMaster = new ImageSlider(this, sliderImage); | |||
| fSliderMaster->setId(DistrhoPlugin3BandSplitter::paramMaster); | |||
| fSliderMaster->setInverted(true); | |||
| fSliderMaster->setStartPos(sliderPosStart); | |||
| fSliderMaster->setEndPos(sliderPosEnd); | |||
| fSliderMaster->setRange(-24.0f, 24.0f); | |||
| fSliderMaster->setCallback(this); | |||
| // knobs | |||
| Image knobImage(Art::knobData, Art::knobWidth, Art::knobHeight); | |||
| // knob Low-Mid | |||
| fKnobLowMid = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobLowMid->setId(DistrhoPlugin3BandSplitter::paramLowMidFreq); | |||
| fKnobLowMid->setAbsolutePos(65, 269); | |||
| fKnobLowMid->setRange(0.0f, 1000.0f); | |||
| fKnobLowMid->setDefault(440.0f); | |||
| fKnobLowMid->setRotationAngle(270); | |||
| fKnobLowMid->setCallback(this); | |||
| // knob Mid-High | |||
| fKnobMidHigh = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobMidHigh->setId(DistrhoPlugin3BandSplitter::paramMidHighFreq); | |||
| fKnobMidHigh->setAbsolutePos(159, 269); | |||
| fKnobMidHigh->setRange(1000.0f, 20000.0f); | |||
| fKnobMidHigh->setDefault(1000.0f); | |||
| fKnobMidHigh->setRotationAngle(270); | |||
| fKnobMidHigh->setCallback(this); | |||
| // about button | |||
| Image aboutImageNormal(Art::aboutButtonNormalData, Art::aboutButtonNormalWidth, Art::aboutButtonNormalHeight); | |||
| Image aboutImageHover(Art::aboutButtonHoverData, Art::aboutButtonHoverWidth, Art::aboutButtonHoverHeight); | |||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | |||
| fButtonAbout->setAbsolutePos(264, 300); | |||
| fButtonAbout->setCallback(this); | |||
| // set default values | |||
| programLoaded(0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void DistrhoUI3BandSplitter::parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case DistrhoPlugin3BandSplitter::paramLow: | |||
| fSliderLow->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandSplitter::paramMid: | |||
| fSliderMid->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandSplitter::paramHigh: | |||
| fSliderHigh->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandSplitter::paramMaster: | |||
| fSliderMaster->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandSplitter::paramLowMidFreq: | |||
| fKnobLowMid->setValue(value); | |||
| break; | |||
| case DistrhoPlugin3BandSplitter::paramMidHighFreq: | |||
| fKnobMidHigh->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoUI3BandSplitter::programLoaded(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fSliderLow->setValue(0.0f); | |||
| fSliderMid->setValue(0.0f); | |||
| fSliderHigh->setValue(0.0f); | |||
| fSliderMaster->setValue(0.0f); | |||
| fKnobLowMid->setValue(220.0f); | |||
| fKnobMidHigh->setValue(2000.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void DistrhoUI3BandSplitter::imageButtonClicked(ImageButton* button, int) | |||
| { | |||
| if (button != fButtonAbout) | |||
| return; | |||
| fAboutWindow.exec(); | |||
| } | |||
| void DistrhoUI3BandSplitter::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), true); | |||
| } | |||
| void DistrhoUI3BandSplitter::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), false); | |||
| } | |||
| void DistrhoUI3BandSplitter::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| setParameterValue(knob->getId(), value); | |||
| } | |||
| void DistrhoUI3BandSplitter::imageSliderDragStarted(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), true); | |||
| } | |||
| void DistrhoUI3BandSplitter::imageSliderDragFinished(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), false); | |||
| } | |||
| void DistrhoUI3BandSplitter::imageSliderValueChanged(ImageSlider* slider, float value) | |||
| { | |||
| setParameterValue(slider->getId(), value); | |||
| } | |||
| void DistrhoUI3BandSplitter::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new DistrhoUI3BandSplitter(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,72 +0,0 @@ | |||
| /* | |||
| * DISTRHO 3BandSplitter Plugin, based on 3BandSplitter by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_UI_3BANDSPLITTER_HPP_INCLUDED | |||
| #define DISTRHO_UI_3BANDSPLITTER_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageWidgets.hpp" | |||
| #include "DistrhoArtwork3BandSplitter.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoUI3BandSplitter : public UI, | |||
| public ImageButton::Callback, | |||
| public ImageKnob::Callback, | |||
| public ImageSlider::Callback | |||
| { | |||
| public: | |||
| DistrhoUI3BandSplitter(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t index, float value) override; | |||
| void programLoaded(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageButtonClicked(ImageButton* button, int) override; | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void imageSliderDragStarted(ImageSlider* slider) override; | |||
| void imageSliderDragFinished(ImageSlider* slider) override; | |||
| void imageSliderValueChanged(ImageSlider* slider, float value) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageAboutWindow fAboutWindow; | |||
| ScopedPointer<ImageButton> fButtonAbout; | |||
| ScopedPointer<ImageKnob> fKnobLowMid, fKnobMidHigh; | |||
| ScopedPointer<ImageSlider> fSliderLow, fSliderMid, fSliderHigh, fSliderMaster; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUI3BandSplitter) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_UI_3BANDSPLITTER_HPP_INCLUDED | |||
| @@ -1,86 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // config fix | |||
| #include "distrho-kars/DistrhoPluginInfo.h" | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-kars/DistrhoArtworkKars.cpp" | |||
| #include "distrho-kars/DistrhoPluginKars.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "distrho-kars/DistrhoUIKars.cpp" | |||
| #endif | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "DistrhoUIMain.cpp" | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor karsDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_SYNTH, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ DistrhoPluginKars::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "kars", | |||
| /* maker */ "falkTX, Chris Cannam", | |||
| /* copyright */ "ISC", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_kars(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_kars() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&karsDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,20 +0,0 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_DISTRHOARTWORKKARS_HPP | |||
| #define BINARY_DISTRHOARTWORKKARS_HPP | |||
| namespace DistrhoArtworkKars | |||
| { | |||
| extern const char* backgroundData; | |||
| const unsigned int backgroundDataSize = 379260; | |||
| const unsigned int backgroundWidth = 301; | |||
| const unsigned int backgroundHeight = 315; | |||
| extern const char* switchData; | |||
| const unsigned int switchDataSize = 61952; | |||
| const unsigned int switchWidth = 88; | |||
| const unsigned int switchHeight = 176; | |||
| } | |||
| #endif // BINARY_DISTRHOARTWORKKARS_HPP | |||
| @@ -1,31 +0,0 @@ | |||
| /* | |||
| * DISTRHO Kars Plugin, based on karplong by Chris Cannam. | |||
| * Copyright (C) 2015 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_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_BRAND "DISTRHO" | |||
| #define DISTRHO_PLUGIN_NAME "Kars" | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Kars" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_RT_SAFE 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
| #define DISTRHO_PLUGIN_USES_MODGUI 1 | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,214 +0,0 @@ | |||
| /* | |||
| * DISTRHO Kars Plugin, based on karplong by Chris Cannam. | |||
| * Copyright (C) 2015 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. | |||
| */ | |||
| #include "DistrhoPluginKars.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoPluginKars::DistrhoPluginKars() | |||
| : Plugin(paramCount, 0, 0), // 0 programs, 0 states | |||
| fSustain(false), | |||
| fSampleRate(getSampleRate()), | |||
| fBlockStart(0) | |||
| { | |||
| for (int i=kMaxNotes; --i >= 0;) | |||
| { | |||
| fNotes[i].index = i; | |||
| fNotes[i].setSampleRate(fSampleRate); | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| parameter.hints = kParameterIsAutomable|kParameterIsBoolean; | |||
| parameter.name = "Sustain"; | |||
| parameter.symbol = "sustain"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float DistrhoPluginKars::getParameterValue(uint32_t index) const | |||
| { | |||
| if (index != 0) | |||
| return 0.0f; | |||
| return fSustain ? 1.0f : 0.0f; | |||
| } | |||
| void DistrhoPluginKars::setParameterValue(uint32_t index, float value) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| fSustain = value > 0.5f; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void DistrhoPluginKars::activate() | |||
| { | |||
| fBlockStart = 0; | |||
| for (int i=kMaxNotes; --i >= 0;) | |||
| { | |||
| fNotes[i].on = kNoteNull; | |||
| fNotes[i].off = kNoteNull; | |||
| fNotes[i].velocity = 0; | |||
| } | |||
| } | |||
| void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) | |||
| { | |||
| uint8_t note, velo; | |||
| float* out = outputs[0]; | |||
| for (uint32_t count, pos=0, curEventIndex=0; pos<frames;) | |||
| { | |||
| for (;curEventIndex < midiEventCount && pos >= midiEvents[curEventIndex].frame; ++curEventIndex) | |||
| { | |||
| if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) | |||
| continue; | |||
| const uint8_t* data = midiEvents[curEventIndex].data; | |||
| const uint8_t status = data[0] & 0xF0; | |||
| switch (status) | |||
| { | |||
| case 0x90: | |||
| note = data[1]; | |||
| velo = data[2]; | |||
| DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes | |||
| if (velo > 0) | |||
| { | |||
| fNotes[note].on = fBlockStart + midiEvents[curEventIndex].frame; | |||
| fNotes[note].off = kNoteNull; | |||
| fNotes[note].velocity = velo; | |||
| break; | |||
| } | |||
| // fall through | |||
| case 0x80: | |||
| note = data[1]; | |||
| DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes | |||
| fNotes[note].off = fBlockStart + midiEvents[curEventIndex].frame; | |||
| break; | |||
| } | |||
| } | |||
| if (curEventIndex < midiEventCount && midiEvents[curEventIndex].frame < frames) | |||
| count = midiEvents[curEventIndex].frame - pos; | |||
| else | |||
| count = frames - pos; | |||
| std::memset(out+pos, 0, sizeof(float)*count); | |||
| //for (uint32_t i=0; i<count; ++i) | |||
| // out[pos + i] = 0.0f; | |||
| for (int i=kMaxNotes; --i >= 0;) | |||
| { | |||
| if (fNotes[i].on != kNoteNull) | |||
| addSamples(out, i, pos, count); | |||
| } | |||
| pos += count; | |||
| } | |||
| fBlockStart += frames; | |||
| } | |||
| void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t offset, uint32_t count) | |||
| { | |||
| const uint32_t start = fBlockStart + offset; | |||
| Note& note(fNotes[voice]); | |||
| if (start < note.on) | |||
| return; | |||
| if (start == note.on) | |||
| { | |||
| for (int i=note.sizei; --i >= 0;) | |||
| note.wavetable[i] = (float(rand()) / float(RAND_MAX)) * 2.0f - 1.0f; | |||
| } | |||
| const float vgain = float(note.velocity) / 127.0f; | |||
| bool decay; | |||
| float gain, sample; | |||
| uint32_t index, size; | |||
| for (uint32_t i=0, s=start-note.on; i<count; ++i, ++s) | |||
| { | |||
| gain = vgain; | |||
| if ((! fSustain) && note.off != kNoteNull && note.off < i+start) | |||
| { | |||
| // reuse index and size to save some performance. | |||
| // actual values are release and dist | |||
| index = 1 + uint32_t(0.01 * fSampleRate); // release, not index | |||
| size = i + start - note.off; // dist, not size | |||
| if (size > index) | |||
| { | |||
| note.on = kNoteNull; | |||
| break; | |||
| } | |||
| gain = gain * float(index - size) / float(index); | |||
| } | |||
| size = uint32_t(note.sizei); | |||
| decay = s > size; | |||
| index = s % size; | |||
| sample = note.wavetable[index]; | |||
| if (decay) | |||
| { | |||
| if (index == 0) | |||
| sample += note.wavetable[size-1]; | |||
| else | |||
| sample += note.wavetable[index-1]; | |||
| note.wavetable[index] = sample/2; | |||
| } | |||
| out[offset+i] += gain * sample; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new DistrhoPluginKars(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,152 +0,0 @@ | |||
| /* | |||
| * DISTRHO Kars Plugin, based on karplong by Chris Cannam. | |||
| * Copyright (C) 2015 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_KARS_HPP_INCLUDED | |||
| #define DISTRHO_PLUGIN_KARS_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoPluginKars : public Plugin | |||
| { | |||
| public: | |||
| static const int kMaxNotes = 128; | |||
| static const uint32_t kNoteNull = (uint32_t)-1; | |||
| enum Parameters | |||
| { | |||
| paramSustain = 0, | |||
| paramCount | |||
| }; | |||
| DistrhoPluginKars(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "Kars"; | |||
| } | |||
| const char* getDescription() const override | |||
| { | |||
| return "Simple karplus-strong plucked string synth."; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "falkTX"; | |||
| } | |||
| const char* getHomePage() const override | |||
| { | |||
| return "https://github.com/DISTRHO/Kars"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "ISC"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return d_version(1, 0, 0); | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('D', 'K', 'r', 's'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t index, Parameter& parameter) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t index) const override; | |||
| void setParameterValue(uint32_t index, float value) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void activate() override; | |||
| void run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| bool fSustain; | |||
| double fSampleRate; | |||
| uint32_t fBlockStart; | |||
| struct Note { | |||
| uint32_t on; | |||
| uint32_t off; | |||
| uint8_t velocity; | |||
| float index; | |||
| float size; | |||
| int sizei; | |||
| float* wavetable; | |||
| Note() noexcept | |||
| : on(kNoteNull), | |||
| off(kNoteNull), | |||
| velocity(0), | |||
| index(0.0f), | |||
| size(0.0f), | |||
| wavetable(nullptr) {} | |||
| ~Note() noexcept | |||
| { | |||
| if (wavetable != nullptr) | |||
| { | |||
| delete[] wavetable; | |||
| wavetable = nullptr; | |||
| } | |||
| } | |||
| void setSampleRate(const double sampleRate) | |||
| { | |||
| if (wavetable != nullptr) | |||
| delete[] wavetable; | |||
| const float frequency = 440.0f * std::pow(2.0f, (index - 69.0f) / 12.0f); | |||
| size = sampleRate / frequency; | |||
| sizei = int(size)+1; | |||
| wavetable = new float[sizei]; | |||
| std::memset(wavetable, 0, sizeof(float)*static_cast<size_t>(sizei)); | |||
| } | |||
| } fNotes[kMaxNotes]; | |||
| void addSamples(float* out, int voice, uint32_t offset, uint32_t count); | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPluginKars) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_PLUGIN_KARS_HPP_INCLUDED | |||
| @@ -1,77 +0,0 @@ | |||
| /* | |||
| * DISTRHO Kars Plugin, based on karplong by Chris Cannam. | |||
| * Copyright (C) 2015 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. | |||
| */ | |||
| #include "DistrhoPluginKars.hpp" | |||
| #include "DistrhoUIKars.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| namespace Art = DistrhoArtworkKars; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUIKars::DistrhoUIKars() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight) | |||
| { | |||
| // sustain switch | |||
| Image switchImageNormal(Art::switchData, Art::switchWidth, Art::switchHeight/2); | |||
| Image switchImageDown(Art::switchData+(Art::switchWidth*Art::switchHeight/2*4), Art::switchWidth, Art::switchHeight/2); | |||
| fSwitchSustain = new ImageSwitch(this, switchImageNormal, switchImageDown); | |||
| fSwitchSustain->setAbsolutePos(Art::backgroundWidth/2-Art::switchWidth/2, Art::backgroundHeight/2-Art::switchHeight/4); | |||
| fSwitchSustain->setId(DistrhoPluginKars::paramSustain); | |||
| fSwitchSustain->setCallback(this); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void DistrhoUIKars::parameterChanged(uint32_t index, float value) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| fSwitchSustain->setDown(value > 0.5f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void DistrhoUIKars::imageSwitchClicked(ImageSwitch* imageSwitch, bool down) | |||
| { | |||
| if (imageSwitch != fSwitchSustain) | |||
| return; | |||
| editParameter(DistrhoPluginKars::paramSustain, true); | |||
| setParameterValue(DistrhoPluginKars::paramSustain, down ? 1.0f : 0.0f); | |||
| editParameter(DistrhoPluginKars::paramSustain, false); | |||
| } | |||
| void DistrhoUIKars::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new DistrhoUIKars(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,60 +0,0 @@ | |||
| /* | |||
| * DISTRHO Kars Plugin, based on karplong by Chris Cannam. | |||
| * Copyright (C) 2015 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_UI_KARS_HPP_INCLUDED | |||
| #define DISTRHO_UI_KARS_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageWidgets.hpp" | |||
| #include "DistrhoArtworkKars.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoUIKars : public UI, | |||
| public ImageSwitch::Callback | |||
| { | |||
| public: | |||
| DistrhoUIKars(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t index, float value) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageSwitchClicked(ImageSwitch* imageSwitch, bool down) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ScopedPointer<ImageSwitch> fSwitchSustain; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUIKars) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_UI_KARS_HPP_INCLUDED | |||
| @@ -1,87 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // config fix | |||
| #include "distrho-nekobi/DistrhoPluginInfo.h" | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-nekobi/DistrhoArtworkNekobi.cpp" | |||
| #include "distrho-nekobi/DistrhoPluginNekobi.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "distrho-nekobi/DistrhoUINekobi.cpp" | |||
| #endif | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "DistrhoUIMain.cpp" | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor nekobiDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_SYNTH, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_IS_SYNTH), | |||
| #endif | |||
| /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES | |||
| |NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ DistrhoPluginNekobi::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "nekobi", | |||
| /* maker */ "falkTX, Sean Bolton and others", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_nekobi(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_nekobi() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&nekobiDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,90 +0,0 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_DISTRHOARTWORKNEKOBI_HPP | |||
| #define BINARY_DISTRHOARTWORKNEKOBI_HPP | |||
| namespace DistrhoArtworkNekobi | |||
| { | |||
| extern const char* aboutData; | |||
| const unsigned int aboutDataSize = 172710; | |||
| const unsigned int aboutWidth = 303; | |||
| const unsigned int aboutHeight = 190; | |||
| extern const char* aboutButtonHoverData; | |||
| const unsigned int aboutButtonHoverDataSize = 5888; | |||
| const unsigned int aboutButtonHoverWidth = 92; | |||
| const unsigned int aboutButtonHoverHeight = 16; | |||
| extern const char* aboutButtonNormalData; | |||
| const unsigned int aboutButtonNormalDataSize = 5888; | |||
| const unsigned int aboutButtonNormalWidth = 92; | |||
| const unsigned int aboutButtonNormalHeight = 16; | |||
| extern const char* backgroundData; | |||
| const unsigned int backgroundDataSize = 206064; | |||
| const unsigned int backgroundWidth = 636; | |||
| const unsigned int backgroundHeight = 108; | |||
| extern const char* claw1Data; | |||
| const unsigned int claw1DataSize = 4096; | |||
| const unsigned int claw1Width = 32; | |||
| const unsigned int claw1Height = 32; | |||
| extern const char* claw2Data; | |||
| const unsigned int claw2DataSize = 4096; | |||
| const unsigned int claw2Width = 32; | |||
| const unsigned int claw2Height = 32; | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 10000; | |||
| const unsigned int knobWidth = 50; | |||
| const unsigned int knobHeight = 50; | |||
| extern const char* run1Data; | |||
| const unsigned int run1DataSize = 4096; | |||
| const unsigned int run1Width = 32; | |||
| const unsigned int run1Height = 32; | |||
| extern const char* run2Data; | |||
| const unsigned int run2DataSize = 4096; | |||
| const unsigned int run2Width = 32; | |||
| const unsigned int run2Height = 32; | |||
| extern const char* run3Data; | |||
| const unsigned int run3DataSize = 4096; | |||
| const unsigned int run3Width = 32; | |||
| const unsigned int run3Height = 32; | |||
| extern const char* run4Data; | |||
| const unsigned int run4DataSize = 4096; | |||
| const unsigned int run4Width = 32; | |||
| const unsigned int run4Height = 32; | |||
| extern const char* scratch1Data; | |||
| const unsigned int scratch1DataSize = 4096; | |||
| const unsigned int scratch1Width = 32; | |||
| const unsigned int scratch1Height = 32; | |||
| extern const char* scratch2Data; | |||
| const unsigned int scratch2DataSize = 4096; | |||
| const unsigned int scratch2Width = 32; | |||
| const unsigned int scratch2Height = 32; | |||
| extern const char* sitData; | |||
| const unsigned int sitDataSize = 4096; | |||
| const unsigned int sitWidth = 32; | |||
| const unsigned int sitHeight = 32; | |||
| extern const char* sliderData; | |||
| const unsigned int sliderDataSize = 6084; | |||
| const unsigned int sliderWidth = 39; | |||
| const unsigned int sliderHeight = 39; | |||
| extern const char* tailData; | |||
| const unsigned int tailDataSize = 4096; | |||
| const unsigned int tailWidth = 32; | |||
| const unsigned int tailHeight = 32; | |||
| } | |||
| #endif // BINARY_DISTRHOARTWORKNEKOBI_HPP | |||
| @@ -1,32 +0,0 @@ | |||
| /* | |||
| * DISTRHO Nekobi Plugin, based on Nekobee by Sean Bolton and others. | |||
| * Copyright (C) 2013-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_BRAND "DISTRHO" | |||
| #define DISTRHO_PLUGIN_NAME "Nekobi" | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/Nekobi" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_RT_SAFE 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
| #define DISTRHO_PLUGIN_USES_MODGUI 1 | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,399 +0,0 @@ | |||
| /* | |||
| * DISTRHO Nekobi Plugin, based on Nekobee by Sean Bolton and others. | |||
| * Copyright (C) 2004 Sean Bolton and others | |||
| * Copyright (C) 2013-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPluginNekobi.hpp" | |||
| extern "C" { | |||
| #include "nekobee-src/nekobee_synth.c" | |||
| #include "nekobee-src/nekobee_voice.c" | |||
| #include "nekobee-src/nekobee_voice_render.c" | |||
| #include "nekobee-src/minblep_tables.c" | |||
| // ----------------------------------------------------------------------- | |||
| // mutual exclusion | |||
| bool dssp_voicelist_mutex_trylock(nekobee_synth_t* const synth) | |||
| { | |||
| /* Attempt the mutex lock */ | |||
| if (pthread_mutex_trylock(&synth->voicelist_mutex) != 0) | |||
| { | |||
| synth->voicelist_mutex_grab_failed = 1; | |||
| return false; | |||
| } | |||
| /* Clean up if a previous mutex grab failed */ | |||
| if (synth->voicelist_mutex_grab_failed) | |||
| { | |||
| nekobee_synth_all_voices_off(synth); | |||
| synth->voicelist_mutex_grab_failed = 0; | |||
| } | |||
| return true; | |||
| } | |||
| bool dssp_voicelist_mutex_unlock(nekobee_synth_t* const synth) | |||
| { | |||
| return (pthread_mutex_unlock(&synth->voicelist_mutex) == 0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // nekobee_handle_raw_event | |||
| void nekobee_handle_raw_event(nekobee_synth_t* const synth, const uint8_t size, const uint8_t* const data) | |||
| { | |||
| if (size != 3) | |||
| return; | |||
| switch (data[0] & 0xf0) | |||
| { | |||
| case 0x80: | |||
| nekobee_synth_note_off(synth, data[1], data[2]); | |||
| break; | |||
| case 0x90: | |||
| if (data[2] > 0) | |||
| nekobee_synth_note_on(synth, data[1], data[2]); | |||
| else | |||
| nekobee_synth_note_off(synth, data[1], 64); /* shouldn't happen, but... */ | |||
| break; | |||
| case 0xB0: | |||
| nekobee_synth_control_change(synth, data[1], data[2]); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| } /* extern "C" */ | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoPluginNekobi::DistrhoPluginNekobi() | |||
| : Plugin(paramCount, 0, 0) // 0 programs, 0 states | |||
| { | |||
| nekobee_init_tables(); | |||
| // init synth | |||
| fSynth.sample_rate = getSampleRate(); | |||
| fSynth.deltat = 1.0f / (float)getSampleRate(); | |||
| fSynth.nugget_remains = 0; | |||
| fSynth.note_id = 0; | |||
| fSynth.polyphony = XSYNTH_DEFAULT_POLYPHONY; | |||
| fSynth.voices = XSYNTH_DEFAULT_POLYPHONY; | |||
| fSynth.monophonic = XSYNTH_MONO_MODE_ONCE; | |||
| fSynth.glide = 0; | |||
| fSynth.last_noteon_pitch = 0.0f; | |||
| fSynth.vcf_accent = 0.0f; | |||
| fSynth.vca_accent = 0.0f; | |||
| for (int i=0; i<8; ++i) | |||
| fSynth.held_keys[i] = -1; | |||
| fSynth.voice = nekobee_voice_new(); | |||
| fSynth.voicelist_mutex_grab_failed = 0; | |||
| pthread_mutex_init(&fSynth.voicelist_mutex, nullptr); | |||
| fSynth.channel_pressure = 0; | |||
| fSynth.pitch_wheel_sensitivity = 0; | |||
| fSynth.pitch_wheel = 0; | |||
| for (int i=0; i<128; ++i) | |||
| { | |||
| fSynth.key_pressure[i] = 0; | |||
| fSynth.cc[i] = 0; | |||
| } | |||
| fSynth.cc[7] = 127; // full volume | |||
| fSynth.mod_wheel = 1.0f; | |||
| fSynth.pitch_bend = 1.0f; | |||
| fSynth.cc_volume = 1.0f; | |||
| // Default values | |||
| fParams.waveform = 0.0f; | |||
| fParams.tuning = 0.0f; | |||
| fParams.cutoff = 25.0f; | |||
| fParams.resonance = 25.0f; | |||
| fParams.envMod = 50.0f; | |||
| fParams.decay = 75.0f; | |||
| fParams.accent = 25.0f; | |||
| fParams.volume = 75.0f; | |||
| // Internal stuff | |||
| fSynth.waveform = 0.0f; | |||
| fSynth.tuning = 1.0f; | |||
| fSynth.cutoff = 5.0f; | |||
| fSynth.resonance = 0.8f; | |||
| fSynth.envmod = 0.3f; | |||
| fSynth.decay = 0.0002f; | |||
| fSynth.accent = 0.3f; | |||
| fSynth.volume = 0.75f; | |||
| // reset | |||
| deactivate(); | |||
| } | |||
| DistrhoPluginNekobi::~DistrhoPluginNekobi() | |||
| { | |||
| std::free(fSynth.voice); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramWaveform: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Waveform"; | |||
| parameter.symbol = "waveform"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramTuning: | |||
| parameter.hints = kParameterIsAutomable; // was 0.5 <-> 2.0, log | |||
| parameter.name = "Tuning"; | |||
| parameter.symbol = "tuning"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -12.0f; | |||
| parameter.ranges.max = 12.0f; | |||
| break; | |||
| case paramCutoff: | |||
| parameter.hints = kParameterIsAutomable; // modified x2.5 | |||
| parameter.name = "Cutoff"; | |||
| parameter.symbol = "cutoff"; | |||
| parameter.unit = "%"; | |||
| parameter.ranges.def = 25.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| case paramResonance: | |||
| parameter.hints = kParameterIsAutomable; // modified x100 | |||
| parameter.name = "VCF Resonance"; | |||
| parameter.symbol = "resonance"; | |||
| parameter.unit = "%"; | |||
| parameter.ranges.def = 25.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 95.0f; | |||
| break; | |||
| case paramEnvMod: | |||
| parameter.hints = kParameterIsAutomable; // modified x100 | |||
| parameter.name = "Env Mod"; | |||
| parameter.symbol = "env_mod"; | |||
| parameter.unit = "%"; | |||
| parameter.ranges.def = 50.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| case paramDecay: | |||
| parameter.hints = kParameterIsAutomable; // was 0.000009 <-> 0.0005, log | |||
| parameter.name = "Decay"; | |||
| parameter.symbol = "decay"; | |||
| parameter.unit = "%"; | |||
| parameter.ranges.def = 75.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| case paramAccent: | |||
| parameter.hints = kParameterIsAutomable; // modified x100 | |||
| parameter.name = "Accent"; | |||
| parameter.symbol = "accent"; | |||
| parameter.unit = "%"; | |||
| parameter.ranges.def = 25.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| case paramVolume: | |||
| parameter.hints = kParameterIsAutomable; // modified x100 | |||
| parameter.name = "Volume"; | |||
| parameter.symbol = "volume"; | |||
| parameter.unit = "%"; | |||
| parameter.ranges.def = 75.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float DistrhoPluginNekobi::getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramWaveform: | |||
| return fParams.waveform; | |||
| case paramTuning: | |||
| return fParams.tuning; | |||
| case paramCutoff: | |||
| return fParams.cutoff; | |||
| case paramResonance: | |||
| return fParams.resonance; | |||
| case paramEnvMod: | |||
| return fParams.envMod; | |||
| case paramDecay: | |||
| return fParams.decay; | |||
| case paramAccent: | |||
| return fParams.accent; | |||
| case paramVolume: | |||
| return fParams.volume; | |||
| } | |||
| return 0.0f; | |||
| } | |||
| void DistrhoPluginNekobi::setParameterValue(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramWaveform: | |||
| fParams.waveform = value; | |||
| fSynth.waveform = value; | |||
| DISTRHO_SAFE_ASSERT(fSynth.waveform == 0.0f || fSynth.waveform == 1.0f); | |||
| break; | |||
| case paramTuning: | |||
| fParams.tuning = value; | |||
| fSynth.tuning = (value+12.0f)/24.0f * 1.5 + 0.5f; // FIXME: log? | |||
| DISTRHO_SAFE_ASSERT(fSynth.tuning >= 0.5f && fSynth.tuning <= 2.0f); | |||
| break; | |||
| case paramCutoff: | |||
| fParams.cutoff = value; | |||
| fSynth.cutoff = value/2.5f; | |||
| DISTRHO_SAFE_ASSERT(fSynth.cutoff >= 0.0f && fSynth.cutoff <= 40.0f); | |||
| break; | |||
| case paramResonance: | |||
| fParams.resonance = value; | |||
| fSynth.resonance = value/100.0f; | |||
| DISTRHO_SAFE_ASSERT(fSynth.resonance >= 0.0f && fSynth.resonance <= 0.95f); | |||
| break; | |||
| case paramEnvMod: | |||
| fParams.envMod = value; | |||
| fSynth.envmod = value/100.0f; | |||
| DISTRHO_SAFE_ASSERT(fSynth.envmod >= 0.0f && fSynth.envmod <= 1.0f); | |||
| break; | |||
| case paramDecay: | |||
| fParams.decay = value; | |||
| fSynth.decay = value/100.0f * 0.000491f + 0.000009f; // FIXME: log? | |||
| DISTRHO_SAFE_ASSERT(fSynth.decay >= 0.000009f && fSynth.decay <= 0.0005f); | |||
| break; | |||
| case paramAccent: | |||
| fParams.accent = value; | |||
| fSynth.accent = value/100.0f; | |||
| DISTRHO_SAFE_ASSERT(fSynth.accent >= 0.0f && fSynth.accent <= 1.0f); | |||
| break; | |||
| case paramVolume: | |||
| fParams.volume = value; | |||
| fSynth.volume = value/100.0f; | |||
| DISTRHO_SAFE_ASSERT(fSynth.volume >= 0.0f && fSynth.volume <= 1.0f); | |||
| break; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void DistrhoPluginNekobi::activate() | |||
| { | |||
| fSynth.nugget_remains = 0; | |||
| fSynth.note_id = 0; | |||
| if (fSynth.voice != nullptr) | |||
| nekobee_synth_all_voices_off(&fSynth); | |||
| } | |||
| void DistrhoPluginNekobi::deactivate() | |||
| { | |||
| if (fSynth.voice != nullptr) | |||
| nekobee_synth_all_voices_off(&fSynth); | |||
| } | |||
| void DistrhoPluginNekobi::run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) | |||
| { | |||
| uint32_t framesDone = 0; | |||
| uint32_t curEventIndex = 0; | |||
| uint32_t burstSize; | |||
| float* out = outputs[0]; | |||
| if (fSynth.voice == nullptr || ! dssp_voicelist_mutex_trylock(&fSynth)) | |||
| { | |||
| std::memset(out, 0, sizeof(float)*frames); | |||
| return; | |||
| } | |||
| while (framesDone < frames) | |||
| { | |||
| if (fSynth.nugget_remains == 0) | |||
| fSynth.nugget_remains = XSYNTH_NUGGET_SIZE; | |||
| /* process any ready events */ | |||
| while (curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame) | |||
| { | |||
| if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) | |||
| continue; | |||
| nekobee_handle_raw_event(&fSynth, midiEvents[curEventIndex].size, midiEvents[curEventIndex].data); | |||
| curEventIndex++; | |||
| } | |||
| /* calculate the sample count (burstSize) for the next nekobee_voice_render() call to be the smallest of: | |||
| * - control calculation quantization size (XSYNTH_NUGGET_SIZE, in samples) | |||
| * - the number of samples remaining in an already-begun nugget (synth->nugget_remains) | |||
| * - the number of samples until the next event is ready | |||
| * - the number of samples left in this run | |||
| */ | |||
| burstSize = XSYNTH_NUGGET_SIZE; | |||
| /* we're still in the middle of a nugget, so reduce the burst size | |||
| * to end when the nugget ends */ | |||
| if (fSynth.nugget_remains < burstSize) | |||
| burstSize = fSynth.nugget_remains; | |||
| /* reduce burst size to end when next event is ready */ | |||
| if (curEventIndex < midiEventCount && midiEvents[curEventIndex].frame - framesDone < burstSize) | |||
| burstSize = midiEvents[curEventIndex].frame - framesDone; | |||
| /* reduce burst size to end at end of this run */ | |||
| if (frames - framesDone < burstSize) | |||
| burstSize = frames - framesDone; | |||
| /* render the burst */ | |||
| nekobee_synth_render_voices(&fSynth, out + framesDone, burstSize, (burstSize == fSynth.nugget_remains)); | |||
| framesDone += burstSize; | |||
| fSynth.nugget_remains -= burstSize; | |||
| } | |||
| dssp_voicelist_mutex_unlock(&fSynth); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new DistrhoPluginNekobi(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,131 +0,0 @@ | |||
| /* | |||
| * DISTRHO Nekobi Plugin, based on Nekobee by Sean Bolton and others. | |||
| * Copyright (C) 2004 Sean Bolton and others | |||
| * Copyright (C) 2013-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_NEKOBI_HPP_INCLUDED | |||
| #define DISTRHO_PLUGIN_NEKOBI_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| extern "C" { | |||
| #include "nekobee-src/nekobee_synth.h" | |||
| } | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoPluginNekobi : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramWaveform = 0, | |||
| paramTuning, | |||
| paramCutoff, | |||
| paramResonance, | |||
| paramEnvMod, | |||
| paramDecay, | |||
| paramAccent, | |||
| paramVolume, | |||
| paramCount | |||
| }; | |||
| DistrhoPluginNekobi(); | |||
| ~DistrhoPluginNekobi() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "Nekobi"; | |||
| } | |||
| const char* getDescription() const override | |||
| { | |||
| return "Simple single-oscillator synth based on the Roland TB-303."; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "Sean Bolton, falkTX"; | |||
| } | |||
| const char* getHomePage() const override | |||
| { | |||
| return "https://github.com/DISTRHO/Nekobi"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return d_version(1, 0, 0); | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('D', 'N', 'e', 'k'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t index, Parameter& parameter) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t index) const override; | |||
| void setParameterValue(uint32_t index, float value) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void activate() override; | |||
| void deactivate() override; | |||
| void run(const float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| struct ParamValues { | |||
| float waveform; | |||
| float tuning; | |||
| float cutoff; | |||
| float resonance; | |||
| float envMod; | |||
| float decay; | |||
| float accent; | |||
| float volume; | |||
| } fParams; | |||
| nekobee_synth_t fSynth; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPluginNekobi) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_PLUGIN_NEKOBI_HPP_INCLUDED | |||
| @@ -1,231 +0,0 @@ | |||
| /* | |||
| * DISTRHO Nekobi Plugin, based on Nekobee by Sean Bolton and others. | |||
| * Copyright (C) 2013-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPluginNekobi.hpp" | |||
| #include "DistrhoUINekobi.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| namespace Art = DistrhoArtworkNekobi; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUINekobi::DistrhoUINekobi() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, GL_BGR), | |||
| fAboutWindow(this) | |||
| { | |||
| // FIXME | |||
| fNeko.setTimerSpeed(5); | |||
| // about | |||
| Image aboutImage(Art::aboutData, Art::aboutWidth, Art::aboutHeight, GL_BGR); | |||
| fAboutWindow.setImage(aboutImage); | |||
| // slider | |||
| Image sliderImage(Art::sliderData, Art::sliderWidth, Art::sliderHeight); | |||
| fSliderWaveform = new ImageSlider(this, sliderImage); | |||
| fSliderWaveform->setId(DistrhoPluginNekobi::paramWaveform); | |||
| fSliderWaveform->setStartPos(133, 40); | |||
| fSliderWaveform->setEndPos(133, 60); | |||
| fSliderWaveform->setRange(0.0f, 1.0f); | |||
| fSliderWaveform->setStep(1.0f); | |||
| fSliderWaveform->setValue(0.0f); | |||
| fSliderWaveform->setCallback(this); | |||
| // knobs | |||
| Image knobImage(Art::knobData, Art::knobWidth, Art::knobHeight); | |||
| // knob Tuning | |||
| fKnobTuning = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobTuning->setId(DistrhoPluginNekobi::paramTuning); | |||
| fKnobTuning->setAbsolutePos(41, 43); | |||
| fKnobTuning->setRange(-12.0f, 12.0f); | |||
| fKnobTuning->setDefault(0.0f); | |||
| fKnobTuning->setValue(0.0f); | |||
| fKnobTuning->setRotationAngle(305); | |||
| fKnobTuning->setCallback(this); | |||
| // knob Cutoff | |||
| fKnobCutoff = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobCutoff->setId(DistrhoPluginNekobi::paramCutoff); | |||
| fKnobCutoff->setAbsolutePos(185, 43); | |||
| fKnobCutoff->setRange(0.0f, 100.0f); | |||
| fKnobCutoff->setDefault(25.0f); | |||
| fKnobCutoff->setValue(25.0f); | |||
| fKnobCutoff->setRotationAngle(305); | |||
| fKnobCutoff->setCallback(this); | |||
| // knob Resonance | |||
| fKnobResonance = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobResonance->setId(DistrhoPluginNekobi::paramResonance); | |||
| fKnobResonance->setAbsolutePos(257, 43); | |||
| fKnobResonance->setRange(0.0f, 95.0f); | |||
| fKnobResonance->setDefault(25.0f); | |||
| fKnobResonance->setValue(25.0f); | |||
| fKnobResonance->setRotationAngle(305); | |||
| fKnobResonance->setCallback(this); | |||
| // knob Env Mod | |||
| fKnobEnvMod = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobEnvMod->setId(DistrhoPluginNekobi::paramEnvMod); | |||
| fKnobEnvMod->setAbsolutePos(329, 43); | |||
| fKnobEnvMod->setRange(0.0f, 100.0f); | |||
| fKnobEnvMod->setDefault(50.0f); | |||
| fKnobEnvMod->setValue(50.0f); | |||
| fKnobEnvMod->setRotationAngle(305); | |||
| fKnobEnvMod->setCallback(this); | |||
| // knob Decay | |||
| fKnobDecay = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobDecay->setId(DistrhoPluginNekobi::paramDecay); | |||
| fKnobDecay->setAbsolutePos(400, 43); | |||
| fKnobDecay->setRange(0.0f, 100.0f); | |||
| fKnobDecay->setDefault(75.0f); | |||
| fKnobDecay->setValue(75.0f); | |||
| fKnobDecay->setRotationAngle(305); | |||
| fKnobDecay->setCallback(this); | |||
| // knob Accent | |||
| fKnobAccent = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobAccent->setId(DistrhoPluginNekobi::paramAccent); | |||
| fKnobAccent->setAbsolutePos(473, 43); | |||
| fKnobAccent->setRange(0.0f, 100.0f); | |||
| fKnobAccent->setDefault(25.0f); | |||
| fKnobAccent->setValue(25.0f); | |||
| fKnobAccent->setRotationAngle(305); | |||
| fKnobAccent->setCallback(this); | |||
| // knob Volume | |||
| fKnobVolume = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobVolume->setId(DistrhoPluginNekobi::paramVolume); | |||
| fKnobVolume->setAbsolutePos(545, 43); | |||
| fKnobVolume->setRange(0.0f, 100.0f); | |||
| fKnobVolume->setDefault(75.0f); | |||
| fKnobVolume->setValue(75.0f); | |||
| fKnobVolume->setRotationAngle(305); | |||
| fKnobVolume->setCallback(this); | |||
| // about button | |||
| Image aboutImageNormal(Art::aboutButtonNormalData, Art::aboutButtonNormalWidth, Art::aboutButtonNormalHeight); | |||
| Image aboutImageHover(Art::aboutButtonHoverData, Art::aboutButtonHoverWidth, Art::aboutButtonHoverHeight); | |||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | |||
| fButtonAbout->setAbsolutePos(505, 5); | |||
| fButtonAbout->setCallback(this); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void DistrhoUINekobi::parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case DistrhoPluginNekobi::paramTuning: | |||
| fKnobTuning->setValue(value); | |||
| break; | |||
| case DistrhoPluginNekobi::paramWaveform: | |||
| fSliderWaveform->setValue(value); | |||
| break; | |||
| case DistrhoPluginNekobi::paramCutoff: | |||
| fKnobCutoff->setValue(value); | |||
| break; | |||
| case DistrhoPluginNekobi::paramResonance: | |||
| fKnobResonance->setValue(value); | |||
| break; | |||
| case DistrhoPluginNekobi::paramEnvMod: | |||
| fKnobEnvMod->setValue(value); | |||
| break; | |||
| case DistrhoPluginNekobi::paramDecay: | |||
| fKnobDecay->setValue(value); | |||
| break; | |||
| case DistrhoPluginNekobi::paramAccent: | |||
| fKnobAccent->setValue(value); | |||
| break; | |||
| case DistrhoPluginNekobi::paramVolume: | |||
| fKnobVolume->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // UI Callbacks | |||
| void DistrhoUINekobi::uiIdle() | |||
| { | |||
| if (fNeko.idle()) | |||
| repaint(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void DistrhoUINekobi::imageButtonClicked(ImageButton* button, int) | |||
| { | |||
| if (button != fButtonAbout) | |||
| return; | |||
| fAboutWindow.exec(); | |||
| } | |||
| void DistrhoUINekobi::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), true); | |||
| } | |||
| void DistrhoUINekobi::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), false); | |||
| } | |||
| void DistrhoUINekobi::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| setParameterValue(knob->getId(), value); | |||
| } | |||
| void DistrhoUINekobi::imageSliderDragStarted(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), true); | |||
| } | |||
| void DistrhoUINekobi::imageSliderDragFinished(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), false); | |||
| } | |||
| void DistrhoUINekobi::imageSliderValueChanged(ImageSlider* slider, float value) | |||
| { | |||
| setParameterValue(slider->getId(), value); | |||
| } | |||
| void DistrhoUINekobi::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| fNeko.draw(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new DistrhoUINekobi(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,86 +0,0 @@ | |||
| /* | |||
| * DISTRHO Nekobi Plugin, based on Nekobee by Sean Bolton and others. | |||
| * Copyright (C) 2013-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_UI_NEKOBI_HPP_INCLUDED | |||
| #define DISTRHO_UI_NEKOBI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageWidgets.hpp" | |||
| #include "DistrhoArtworkNekobi.hpp" | |||
| #include "NekoWidget.hpp" | |||
| using DGL_NAMESPACE::ImageAboutWindow; | |||
| using DGL_NAMESPACE::ImageButton; | |||
| using DGL_NAMESPACE::ImageKnob; | |||
| using DGL_NAMESPACE::ImageSlider; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoUINekobi : public UI, | |||
| public ImageButton::Callback, | |||
| public ImageKnob::Callback, | |||
| public ImageSlider::Callback | |||
| { | |||
| public: | |||
| DistrhoUINekobi(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t index, float value) override; | |||
| // ------------------------------------------------------------------- | |||
| // UI Callbacks | |||
| void uiIdle() override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageButtonClicked(ImageButton* button, int) override; | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void imageSliderDragStarted(ImageSlider* slider) override; | |||
| void imageSliderDragFinished(ImageSlider* slider) override; | |||
| void imageSliderValueChanged(ImageSlider* slider, float value) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageAboutWindow fAboutWindow; | |||
| NekoWidget fNeko; | |||
| ScopedPointer<ImageButton> fButtonAbout; | |||
| ScopedPointer<ImageSlider> fSliderWaveform; | |||
| ScopedPointer<ImageKnob> fKnobTuning, fKnobCutoff, fKnobResonance; | |||
| ScopedPointer<ImageKnob> fKnobEnvMod, fKnobDecay, fKnobAccent, fKnobVolume; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUINekobi) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_UI_NEKOBI_HPP_INCLUDED | |||
| @@ -1,202 +0,0 @@ | |||
| /* | |||
| * Neko widget animation | |||
| * Copyright (C) 2013-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the LICENSE file. | |||
| */ | |||
| #ifndef NEKO_WIDGET_HPP_INCLUDED | |||
| #define NEKO_WIDGET_HPP_INCLUDED | |||
| #include "DistrhoArtworkNekobi.hpp" | |||
| #include "Image.hpp" | |||
| #include "Widget.hpp" | |||
| #include <cstdlib> // rand | |||
| using DGL_NAMESPACE::Image; | |||
| // ----------------------------------------------------------------------- | |||
| class NekoWidget | |||
| { | |||
| public: | |||
| NekoWidget() | |||
| : fPos(0), | |||
| fTimer(0), | |||
| fTimerSpeed(20), | |||
| fCurAction(kActionNone), | |||
| fCurImage(&fImages.sit) | |||
| { | |||
| // load images | |||
| { | |||
| using namespace DistrhoArtworkNekobi; | |||
| #define JOIN(a, b) a ## b | |||
| #define LOAD_IMAGE(NAME) fImages.NAME.loadFromMemory(JOIN(NAME, Data), JOIN(NAME, Width), JOIN(NAME, Height)); | |||
| LOAD_IMAGE(sit) | |||
| LOAD_IMAGE(tail) | |||
| LOAD_IMAGE(claw1) | |||
| LOAD_IMAGE(claw2) | |||
| LOAD_IMAGE(scratch1) | |||
| LOAD_IMAGE(scratch2) | |||
| LOAD_IMAGE(run1) | |||
| LOAD_IMAGE(run2) | |||
| LOAD_IMAGE(run3) | |||
| LOAD_IMAGE(run4) | |||
| #undef JOIN | |||
| #undef LOAD_IMAGE | |||
| } | |||
| } | |||
| void draw() | |||
| { | |||
| int x = fPos+108; | |||
| int y = -2; | |||
| if (fCurImage == &fImages.claw1 || fCurImage == &fImages.claw2) | |||
| { | |||
| x += 2; | |||
| y += 12; | |||
| } | |||
| fCurImage->drawAt(x, y); | |||
| } | |||
| // returns true if needs repaint | |||
| bool idle() | |||
| { | |||
| if (++fTimer % fTimerSpeed != 0) // target is 20ms | |||
| return false; | |||
| if (fTimer == fTimerSpeed*9) | |||
| { | |||
| if (fCurAction == kActionNone) | |||
| fCurAction = static_cast<Action>(std::rand() % kActionCount); | |||
| else | |||
| fCurAction = kActionNone; | |||
| fTimer = 0; | |||
| } | |||
| switch (fCurAction) | |||
| { | |||
| case kActionNone: | |||
| if (fCurImage == &fImages.sit) | |||
| fCurImage = &fImages.tail; | |||
| else | |||
| fCurImage = &fImages.sit; | |||
| break; | |||
| case kActionClaw: | |||
| if (fCurImage == &fImages.claw1) | |||
| fCurImage = &fImages.claw2; | |||
| else | |||
| fCurImage = &fImages.claw1; | |||
| break; | |||
| case kActionScratch: | |||
| if (fCurImage == &fImages.scratch1) | |||
| fCurImage = &fImages.scratch2; | |||
| else | |||
| fCurImage = &fImages.scratch1; | |||
| break; | |||
| case kActionRunRight: | |||
| if (fTimer == 0 && fPos > 20*9) | |||
| { | |||
| // run the other way | |||
| --fTimer; | |||
| fCurAction = kActionRunLeft; | |||
| idle(); | |||
| break; | |||
| } | |||
| fPos += 20; | |||
| if (fCurImage == &fImages.run1) | |||
| fCurImage = &fImages.run2; | |||
| else | |||
| fCurImage = &fImages.run1; | |||
| break; | |||
| case kActionRunLeft: | |||
| if (fTimer == 0 && fPos < 20*9) | |||
| { | |||
| // run the other way | |||
| --fTimer; | |||
| fCurAction = kActionRunRight; | |||
| idle(); | |||
| break; | |||
| } | |||
| fPos -= 20; | |||
| if (fCurImage == &fImages.run3) | |||
| fCurImage = &fImages.run4; | |||
| else | |||
| fCurImage = &fImages.run3; | |||
| break; | |||
| case kActionCount: | |||
| break; | |||
| } | |||
| return true; | |||
| } | |||
| void setTimerSpeed(int speed) | |||
| { | |||
| fTimer = 0; | |||
| fTimerSpeed = speed; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| enum Action { | |||
| kActionNone, // bounce tail | |||
| kActionClaw, | |||
| kActionScratch, | |||
| kActionRunRight, | |||
| kActionRunLeft, | |||
| kActionCount | |||
| }; | |||
| struct Images { | |||
| Image sit; | |||
| Image tail; | |||
| Image claw1; | |||
| Image claw2; | |||
| Image scratch1; | |||
| Image scratch2; | |||
| Image run1; | |||
| Image run2; | |||
| Image run3; | |||
| Image run4; | |||
| } fImages; | |||
| int fPos; | |||
| int fTimer; | |||
| int fTimerSpeed; | |||
| Action fCurAction; | |||
| Image* fCurImage; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| #endif // NEKO_WIDGET_HPP_INCLUDED | |||
| @@ -1,77 +0,0 @@ | |||
| /* nekobee DSSI software synthesizer plugin | |||
| * | |||
| * Copyright (C) 2004 Sean Bolton and others. | |||
| * | |||
| * Portions of this file may have come from Chris Cannam and Steve | |||
| * Harris's public domain DSSI example code. | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or (at your option) any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be | |||
| * useful, but WITHOUT ANY WARRANTY; without even the implied | |||
| * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
| * PURPOSE. See the GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public | |||
| * License along with this program; if not, write to the Free | |||
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |||
| * MA 02111-1307, USA. | |||
| */ | |||
| #ifndef _XSYNTH_H | |||
| #define _XSYNTH_H | |||
| /* ==== debugging ==== */ | |||
| /* XSYNTH_DEBUG bits */ | |||
| #define XDB_DSSI 1 /* DSSI interface */ | |||
| #define XDB_AUDIO 2 /* audio output */ | |||
| #define XDB_NOTE 4 /* note on/off, voice allocation */ | |||
| #define XDB_DATA 8 /* plugin patchbank handling */ | |||
| #define GDB_MAIN 16 /* GUI main program flow */ | |||
| #define GDB_OSC 32 /* GUI OSC handling */ | |||
| #define GDB_IO 64 /* GUI patch file input/output */ | |||
| #define GDB_GUI 128 /* GUI GUI callbacks, updating, etc. */ | |||
| /* If you want debug information, define XSYNTH_DEBUG to the XDB_* bits you're | |||
| * interested in getting debug information about, bitwise-ORed together. | |||
| * Otherwise, leave it undefined. */ | |||
| // #define XSYNTH_DEBUG (1+8+16+32+64) | |||
| //#define XSYNTH_DEBUG GDB_GUI + GDB_OSC | |||
| // #define XSYNTH_DEBUG XDB_DSSI | |||
| #ifdef XSYNTH_DEBUG | |||
| #include <stdio.h> | |||
| #define XSYNTH_DEBUG_INIT(x) | |||
| #define XDB_MESSAGE(type, fmt...) { if (XSYNTH_DEBUG & type) fprintf(stderr, "nekobee-dssi.so" fmt); } | |||
| #define GDB_MESSAGE(type, fmt...) { if (XSYNTH_DEBUG & type) fprintf(stderr, "nekobee_gtk" fmt); } | |||
| // -FIX-: | |||
| // #include "message_buffer.h" | |||
| // #define XSYNTH_DEBUG_INIT(x) mb_init(x) | |||
| // #define XDB_MESSAGE(type, fmt...) { \- | |||
| // if (XSYNTH_DEBUG & type) { \- | |||
| // char _m[256]; \- | |||
| // snprintf(_m, 255, fmt); \- | |||
| // add_message(_m); \- | |||
| // } \- | |||
| // } | |||
| #else /* !XSYNTH_DEBUG */ | |||
| #define XDB_MESSAGE(type, fmt...) | |||
| #define GDB_MESSAGE(type, fmt...) | |||
| #define XSYNTH_DEBUG_INIT(x) | |||
| #endif /* XSYNTH_DEBUG */ | |||
| /* ==== end of debugging ==== */ | |||
| #define XSYNTH_MAX_POLYPHONY 1 | |||
| #define XSYNTH_DEFAULT_POLYPHONY 1 | |||
| #endif /* _XSYNTH_H */ | |||
| @@ -1,237 +0,0 @@ | |||
| /* nekobee DSSI software synthesizer plugin | |||
| * | |||
| * Copyright (C) 2004 Sean Bolton and others. | |||
| * | |||
| * Portions of this file may have come from Steve Brookes' | |||
| * nekobee, copyright (C) 1999 S. J. Brookes. | |||
| * Portions of this file may have come from Peter Hanappe's | |||
| * Fluidsynth, copyright (C) 2003 Peter Hanappe and others. | |||
| * Portions of this file may have come from Chris Cannam and Steve | |||
| * Harris's public domain DSSI example code. | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or (at your option) any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be | |||
| * useful, but WITHOUT ANY WARRANTY; without even the implied | |||
| * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
| * PURPOSE. See the GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public | |||
| * License along with this program; if not, write to the Free | |||
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |||
| * MA 02111-1307, USA. | |||
| */ | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include <math.h> | |||
| #include <pthread.h> | |||
| #include "nekobee.h" | |||
| #include "nekobee_synth.h" | |||
| #include "nekobee_voice.h" | |||
| /* | |||
| * nekobee_synth_all_voices_off | |||
| * | |||
| * stop processing all notes immediately | |||
| */ | |||
| void | |||
| nekobee_synth_all_voices_off(nekobee_synth_t *synth) | |||
| { | |||
| int i; | |||
| nekobee_voice_t *voice; | |||
| for (i = 0; i < synth->voices; i++) { | |||
| //voice = synth->voice[i]; | |||
| voice = synth->voice; | |||
| if (_PLAYING(voice)) { | |||
| nekobee_voice_off(voice); | |||
| } | |||
| } | |||
| for (i = 0; i < 8; i++) synth->held_keys[i] = -1; | |||
| } | |||
| /* | |||
| * nekobee_synth_note_off | |||
| * | |||
| * handle a note off message | |||
| */ | |||
| void | |||
| nekobee_synth_note_off(nekobee_synth_t *synth, unsigned char key, unsigned char rvelocity) | |||
| { | |||
| int i, count = 0; | |||
| nekobee_voice_t *voice; | |||
| for (i = 0; i < synth->voices; i++) { | |||
| voice = synth->voice; | |||
| if (_PLAYING(voice)) { | |||
| XDB_MESSAGE(XDB_NOTE, " nekobee_synth_note_off: key %d rvel %d voice %d note id %d\n", key, rvelocity, i, voice->note_id); | |||
| nekobee_voice_note_off(synth, voice, key, 64); | |||
| count++; | |||
| } | |||
| } | |||
| if (!count) | |||
| nekobee_voice_remove_held_key(synth, key); | |||
| return; | |||
| (void)rvelocity; | |||
| } | |||
| /* | |||
| * nekobee_synth_all_notes_off | |||
| * | |||
| * put all notes into the released state | |||
| */ | |||
| void | |||
| nekobee_synth_all_notes_off(nekobee_synth_t* synth) | |||
| { | |||
| int i; | |||
| nekobee_voice_t *voice; | |||
| /* reset the sustain controller */ | |||
| synth->cc[MIDI_CTL_SUSTAIN] = 0; | |||
| for (i = 0; i < synth->voices; i++) { | |||
| //voice = synth->voice[i]; | |||
| voice = synth->voice; | |||
| if (_ON(voice) || _SUSTAINED(voice)) { | |||
| nekobee_voice_release_note(synth, voice); | |||
| } | |||
| } | |||
| } | |||
| /* | |||
| * nekobee_synth_note_on | |||
| */ | |||
| void | |||
| nekobee_synth_note_on(nekobee_synth_t *synth, unsigned char key, unsigned char velocity) | |||
| { | |||
| nekobee_voice_t* voice; | |||
| voice = synth->voice; | |||
| if (_PLAYING(synth->voice)) { | |||
| XDB_MESSAGE(XDB_NOTE, " nekobee_synth_note_on: retriggering mono voice on new key %d\n", key); | |||
| } | |||
| voice->note_id = synth->note_id++; | |||
| nekobee_voice_note_on(synth, voice, key, velocity); | |||
| } | |||
| /* | |||
| * nekobee_synth_update_volume | |||
| */ | |||
| void | |||
| nekobee_synth_update_volume(nekobee_synth_t* synth) | |||
| { | |||
| synth->cc_volume = (float)(synth->cc[MIDI_CTL_MSB_MAIN_VOLUME] * 128 + | |||
| synth->cc[MIDI_CTL_LSB_MAIN_VOLUME]) / 16256.0f; | |||
| if (synth->cc_volume > 1.0f) | |||
| synth->cc_volume = 1.0f; | |||
| /* don't need to check if any playing voices need updating, because it's global */ | |||
| } | |||
| /* | |||
| * nekobee_synth_control_change | |||
| */ | |||
| void | |||
| nekobee_synth_control_change(nekobee_synth_t *synth, unsigned int param, signed int value) | |||
| { | |||
| synth->cc[param] = value; | |||
| switch (param) { | |||
| case MIDI_CTL_MSB_MAIN_VOLUME: | |||
| case MIDI_CTL_LSB_MAIN_VOLUME: | |||
| nekobee_synth_update_volume(synth); | |||
| break; | |||
| case MIDI_CTL_ALL_SOUNDS_OFF: | |||
| nekobee_synth_all_voices_off(synth); | |||
| break; | |||
| case MIDI_CTL_RESET_CONTROLLERS: | |||
| nekobee_synth_init_controls(synth); | |||
| break; | |||
| case MIDI_CTL_ALL_NOTES_OFF: | |||
| nekobee_synth_all_notes_off(synth); | |||
| break; | |||
| /* what others should we respond to? */ | |||
| /* these we ignore (let the host handle): | |||
| * BANK_SELECT_MSB | |||
| * BANK_SELECT_LSB | |||
| * DATA_ENTRY_MSB | |||
| * NRPN_MSB | |||
| * NRPN_LSB | |||
| * RPN_MSB | |||
| * RPN_LSB | |||
| * -FIX- no! we need RPN (0, 0) Pitch Bend Sensitivity! | |||
| */ | |||
| } | |||
| } | |||
| /* | |||
| * nekobee_synth_init_controls | |||
| */ | |||
| void | |||
| nekobee_synth_init_controls(nekobee_synth_t *synth) | |||
| { | |||
| int i; | |||
| for (i = 0; i < 128; i++) { | |||
| synth->cc[i] = 0; | |||
| } | |||
| synth->cc[7] = 127; /* full volume */ | |||
| nekobee_synth_update_volume(synth); | |||
| } | |||
| /* | |||
| * nekobee_synth_render_voices | |||
| */ | |||
| void | |||
| nekobee_synth_render_voices(nekobee_synth_t *synth, float *out, unsigned long sample_count, | |||
| int do_control_update) | |||
| { | |||
| unsigned long i; | |||
| float res, wow; | |||
| /* clear the buffer */ | |||
| for (i = 0; i < sample_count; i++) | |||
| out[i] = 0.0f; | |||
| // we can do anything that must be updated all the time here | |||
| // this is called even when a voice isn't playing | |||
| // approximate a log scale | |||
| res = 1-synth->resonance; | |||
| wow = res*res; | |||
| wow = wow/10.0f; | |||
| // as the resonance is increased, "wow" slows down the accent attack | |||
| if ((synth->voice->velocity>90) && (synth->vcf_accent < synth->voice->vcf_eg)) { | |||
| synth->vcf_accent=(0.985-wow)*synth->vcf_accent+(0.015+wow)*synth->voice->vcf_eg; | |||
| } else { | |||
| synth->vcf_accent=(0.985-wow)*synth->vcf_accent; // or just decay | |||
| } | |||
| if (synth->voice->velocity>90) { | |||
| synth->vca_accent=0.95*synth->vca_accent+0.05; // ramp up accent on with a time constant | |||
| } else { | |||
| synth->vca_accent=0.95*synth->vca_accent; // accent off with time constant | |||
| } | |||
| #if defined(XSYNTH_DEBUG) && (XSYNTH_DEBUG & XDB_AUDIO) | |||
| out[0] += 0.10f; /* add a 'buzz' to output so there's something audible even when quiescent */ | |||
| #endif /* defined(XSYNTH_DEBUG) && (XSYNTH_DEBUG & XDB_AUDIO) */ | |||
| if (_PLAYING(synth->voice)) { | |||
| nekobee_voice_render(synth, synth->voice, out, sample_count, do_control_update); | |||
| } | |||
| } | |||
| @@ -1,132 +0,0 @@ | |||
| /* nekobee DSSI software synthesizer plugin | |||
| * | |||
| * Copyright (C) 2004 Sean Bolton and others. | |||
| * | |||
| * Portions of this file may have come from Peter Hanappe's | |||
| * Fluidsynth, copyright (C) 2003 Peter Hanappe and others. | |||
| * Portions of this file may have come from alsa-lib, copyright | |||
| * and licensed under the LGPL v2.1. | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or (at your option) any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be | |||
| * useful, but WITHOUT ANY WARRANTY; without even the implied | |||
| * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
| * PURPOSE. See the GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public | |||
| * License along with this program; if not, write to the Free | |||
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |||
| * MA 02111-1307, USA. | |||
| */ | |||
| #ifndef _XSYNTH_SYNTH_H | |||
| #define _XSYNTH_SYNTH_H | |||
| #include <pthread.h> | |||
| #include "nekobee.h" | |||
| #include "nekobee_types.h" | |||
| #define XSYNTH_MONO_MODE_OFF 0 | |||
| #define XSYNTH_MONO_MODE_ON 1 | |||
| #define XSYNTH_MONO_MODE_ONCE 2 | |||
| #define XSYNTH_MONO_MODE_BOTH 3 | |||
| #define XSYNTH_GLIDE_MODE_LEGATO 0 | |||
| #define XSYNTH_GLIDE_MODE_INITIAL 1 | |||
| #define XSYNTH_GLIDE_MODE_ALWAYS 2 | |||
| #define XSYNTH_GLIDE_MODE_LEFTOVER 3 | |||
| #define XSYNTH_GLIDE_MODE_OFF 4 | |||
| /* | |||
| * nekobee_synth_t | |||
| */ | |||
| struct _nekobee_synth_t { | |||
| /* output */ | |||
| unsigned long sample_rate; | |||
| float deltat; /* 1 / sample_rate */ | |||
| unsigned long nugget_remains; | |||
| /* voice tracking and data */ | |||
| unsigned int note_id; /* incremented for every new note, used for voice-stealing prioritization */ | |||
| int polyphony; /* requested polyphony, must be <= XSYNTH_MAX_POLYPHONY */ | |||
| int voices; /* current polyphony, either requested polyphony above or 1 while in monophonic mode */ | |||
| int monophonic; /* true if operating in monophonic mode */ | |||
| int glide; /* current glide mode */ | |||
| float last_noteon_pitch; /* glide start pitch for non-legato modes */ | |||
| signed char held_keys[8]; /* for monophonic key tracking, an array of note-ons, most recently received first */ | |||
| float vcf_accent; /* used to emulate the circuit that sweeps the vcf at full resonance */ | |||
| float vca_accent; /* used to smooth the accent pulse, removing the click */ | |||
| //nekobee_voice_t *voice[XSYNTH_MAX_POLYPHONY]; | |||
| nekobee_voice_t *voice; | |||
| pthread_mutex_t voicelist_mutex; | |||
| int voicelist_mutex_grab_failed; | |||
| /* current non-paramter-mapped controller values */ | |||
| unsigned char key_pressure[128]; | |||
| unsigned char cc[128]; /* controller values */ | |||
| unsigned char channel_pressure; | |||
| unsigned char pitch_wheel_sensitivity; /* in semitones */ | |||
| int pitch_wheel; /* range is -8192 - 8191 */ | |||
| /* translated controller values */ | |||
| float mod_wheel; /* filter cutoff multiplier, off = 1.0, full on = 0.0 */ | |||
| float pitch_bend; /* frequency multiplier, product of wheel setting and sensitivity, center = 1.0 */ | |||
| float cc_volume; /* volume multiplier, 0.0 to 1.0 */ | |||
| /* patch parameters */ | |||
| float tuning; | |||
| float waveform; | |||
| float cutoff; | |||
| float resonance; | |||
| float envmod; | |||
| float decay; | |||
| float accent; | |||
| float volume; | |||
| }; | |||
| void nekobee_synth_all_voices_off(nekobee_synth_t *synth); | |||
| void nekobee_synth_note_off(nekobee_synth_t *synth, unsigned char key, | |||
| unsigned char rvelocity); | |||
| void nekobee_synth_all_notes_off(nekobee_synth_t *synth); | |||
| void nekobee_synth_note_on(nekobee_synth_t *synth, unsigned char key, | |||
| unsigned char velocity); | |||
| void nekobee_synth_control_change(nekobee_synth_t *synth, unsigned int param, | |||
| signed int value); | |||
| void nekobee_synth_init_controls(nekobee_synth_t *synth); | |||
| void nekobee_synth_render_voices(nekobee_synth_t *synth, float *out, | |||
| unsigned long sample_count, | |||
| int do_control_update); | |||
| /* these come right out of alsa/asoundef.h */ | |||
| #define MIDI_CTL_MSB_MODWHEEL 0x01 /**< Modulation */ | |||
| #define MIDI_CTL_MSB_PORTAMENTO_TIME 0x05 /**< Portamento time */ | |||
| #define MIDI_CTL_MSB_MAIN_VOLUME 0x07 /**< Main volume */ | |||
| #define MIDI_CTL_MSB_BALANCE 0x08 /**< Balance */ | |||
| #define MIDI_CTL_LSB_MODWHEEL 0x21 /**< Modulation */ | |||
| #define MIDI_CTL_LSB_PORTAMENTO_TIME 0x25 /**< Portamento time */ | |||
| #define MIDI_CTL_LSB_MAIN_VOLUME 0x27 /**< Main volume */ | |||
| #define MIDI_CTL_LSB_BALANCE 0x28 /**< Balance */ | |||
| #define MIDI_CTL_SUSTAIN 0x40 /**< Sustain pedal */ | |||
| // nekobee defines | |||
| #define MIDI_CTL_TUNING 0x4b // impossible | |||
| #define MIDI_CTL_WAVEFORM 0x46 // select waveform | |||
| #define MIDI_CTL_CUTOFF 0x4a // VCF Cutoff | |||
| #define MIDI_CTL_RESONANCE 0x47 // VCF Resonance | |||
| #define MIDI_CTL_ENVMOD 0x01 // cheat and use modwheel | |||
| #define MIDI_CTL_DECAY 0x48 // Decay time (well release really) | |||
| #define MIDI_CTL_ACCENT 0x4c // impossible | |||
| #define MIDI_CTL_ALL_SOUNDS_OFF 0x78 /**< All sounds off */ | |||
| #define MIDI_CTL_RESET_CONTROLLERS 0x79 /**< Reset Controllers */ | |||
| #define MIDI_CTL_ALL_NOTES_OFF 0x7b /**< All notes off */ | |||
| #define XSYNTH_SYNTH_SUSTAINED(_s) ((_s)->cc[MIDI_CTL_SUSTAIN] >= 64) | |||
| #endif /* _XSYNTH_SYNTH_H */ | |||
| @@ -1,30 +0,0 @@ | |||
| /* nekobee DSSI software synthesizer plugin | |||
| * | |||
| * Copyright (C) 2004 Sean Bolton and others. | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or (at your option) any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be | |||
| * useful, but WITHOUT ANY WARRANTY; without even the implied | |||
| * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
| * PURPOSE. See the GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public | |||
| * License along with this library; if not, write to the Free | |||
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |||
| * MA 02111-1307, USA. | |||
| */ | |||
| #ifndef _XSYNTH_TYPES_H | |||
| #define _XSYNTH_TYPES_H | |||
| #include <stddef.h> | |||
| typedef struct _nekobee_synth_t nekobee_synth_t; | |||
| typedef struct _nekobee_voice_t nekobee_voice_t; | |||
| typedef struct _nekobee_patch_t nekobee_patch_t; | |||
| #endif /* _XSYNTH_TYPES_H */ | |||
| @@ -1,256 +0,0 @@ | |||
| /* nekobee DSSI software synthesizer plugin | |||
| * | |||
| * Copyright (C) 2004 Sean Bolton and others. | |||
| * | |||
| * Portions of this file may have come from Steve Brookes' | |||
| * nekobee, copyright (C) 1999 S. J. Brookes. | |||
| * Portions of this file may have come from Peter Hanappe's | |||
| * Fluidsynth, copyright (C) 2003 Peter Hanappe and others. | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or (at your option) any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be | |||
| * useful, but WITHOUT ANY WARRANTY; without even the implied | |||
| * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
| * PURPOSE. See the GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public | |||
| * License along with this program; if not, write to the Free | |||
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |||
| * MA 02111-1307, USA. | |||
| */ | |||
| #define _BSD_SOURCE 1 | |||
| #define _SVID_SOURCE 1 | |||
| #define _ISOC99_SOURCE 1 | |||
| #include <stdlib.h> | |||
| #include "nekobee_types.h" | |||
| #include "nekobee.h" | |||
| #include "nekobee_synth.h" | |||
| #include "nekobee_voice.h" | |||
| /* | |||
| * nekobee_voice_new | |||
| */ | |||
| nekobee_voice_t * | |||
| nekobee_voice_new() | |||
| { | |||
| nekobee_voice_t *voice; | |||
| voice = (nekobee_voice_t *)calloc(sizeof(nekobee_voice_t), 1); | |||
| if (voice) { | |||
| voice->status = XSYNTH_VOICE_OFF; | |||
| } | |||
| return voice; | |||
| } | |||
| /* | |||
| * nekobee_voice_note_on | |||
| */ | |||
| void | |||
| nekobee_voice_note_on(nekobee_synth_t *synth, nekobee_voice_t *voice, | |||
| unsigned char key, unsigned char velocity) | |||
| { | |||
| int i; | |||
| voice->key = key; | |||
| voice->velocity = velocity; | |||
| if (!synth->monophonic || !(_ON(voice) || _SUSTAINED(voice))) { | |||
| // brand-new voice, or monophonic voice in release phase; set everything up | |||
| XDB_MESSAGE(XDB_NOTE, " nekobee_voice_note_on in polyphonic/new section: key %d, mono %d, old status %d\n", key, synth->monophonic, voice->status); | |||
| voice->target_pitch = nekobee_pitch[key]; | |||
| if (synth->held_keys[0] >= 0) { | |||
| voice->prev_pitch = nekobee_pitch[synth->held_keys[0]]; | |||
| } else { | |||
| voice->prev_pitch = voice->target_pitch; | |||
| } | |||
| if (!_PLAYING(voice)) { | |||
| voice->lfo_pos = 0.0f; | |||
| voice->vca_eg = 0.0f; | |||
| voice->vcf_eg = 0.0f; | |||
| voice->delay1 = 0.0f; | |||
| voice->delay2 = 0.0f; | |||
| voice->delay3 = 0.0f; | |||
| voice->delay4 = 0.0f; | |||
| voice->c5 = 0.0f; | |||
| voice->osc_index = 0; | |||
| voice->osc1.last_waveform = -1; | |||
| voice->osc1.pos = 0.0f; | |||
| } | |||
| voice->vca_eg_phase = 0; | |||
| voice->vcf_eg_phase = 0; | |||
| // nekobee_voice_update_pressure_mod(synth, voice); | |||
| } else { | |||
| /* synth is monophonic, and we're modifying a playing voice */ | |||
| XDB_MESSAGE(XDB_NOTE, " nekobee_voice_note_on in monophonic section: old key %d => new key %d\n", synth->held_keys[0], key); | |||
| /* set new pitch */ | |||
| voice->target_pitch = nekobee_pitch[key]; | |||
| if (synth->glide == XSYNTH_GLIDE_MODE_INITIAL || | |||
| synth->glide == XSYNTH_GLIDE_MODE_OFF) | |||
| voice->prev_pitch = voice->target_pitch; | |||
| /* if in 'on' or 'both' modes, and key has changed, then re-trigger EGs */ | |||
| if ((synth->monophonic == XSYNTH_MONO_MODE_ON || | |||
| synth->monophonic == XSYNTH_MONO_MODE_BOTH) && | |||
| (synth->held_keys[0] < 0 || synth->held_keys[0] != key)) { | |||
| voice->vca_eg_phase = 0; | |||
| voice->vcf_eg_phase = 0; | |||
| } | |||
| /* all other variables stay what they are */ | |||
| } | |||
| synth->last_noteon_pitch = voice->target_pitch; | |||
| /* add new key to the list of held keys */ | |||
| /* check if new key is already in the list; if so, move it to the | |||
| * top of the list, otherwise shift the other keys down and add it | |||
| * to the top of the list. */ | |||
| for (i = 0; i < 7; i++) { | |||
| if (synth->held_keys[i] == key) | |||
| break; | |||
| } | |||
| for (; i > 0; i--) { | |||
| synth->held_keys[i] = synth->held_keys[i - 1]; | |||
| } | |||
| synth->held_keys[0] = key; | |||
| if (!_PLAYING(voice)) { | |||
| nekobee_voice_start_voice(voice); | |||
| } else if (!_ON(voice)) { /* must be XSYNTH_VOICE_SUSTAINED or XSYNTH_VOICE_RELEASED */ | |||
| voice->status = XSYNTH_VOICE_ON; | |||
| } | |||
| } | |||
| /* | |||
| * nekobee_voice_set_release_phase | |||
| */ | |||
| static inline void | |||
| nekobee_voice_set_release_phase(nekobee_voice_t *voice) | |||
| { | |||
| voice->vca_eg_phase = 2; | |||
| voice->vcf_eg_phase = 2; | |||
| } | |||
| /* | |||
| * nekobee_voice_remove_held_key | |||
| */ | |||
| inline void | |||
| nekobee_voice_remove_held_key(nekobee_synth_t *synth, unsigned char key) | |||
| { | |||
| int i; | |||
| /* check if this key is in list of held keys; if so, remove it and | |||
| * shift the other keys up */ | |||
| for (i = 7; i >= 0; i--) { | |||
| if (synth->held_keys[i] == key) | |||
| break; | |||
| } | |||
| if (i >= 0) { | |||
| for (; i < 7; i++) { | |||
| synth->held_keys[i] = synth->held_keys[i + 1]; | |||
| } | |||
| synth->held_keys[7] = -1; | |||
| } | |||
| } | |||
| /* | |||
| * nekobee_voice_note_off | |||
| */ | |||
| void | |||
| nekobee_voice_note_off(nekobee_synth_t *synth, nekobee_voice_t *voice, | |||
| unsigned char key, unsigned char rvelocity) | |||
| { | |||
| unsigned char previous_top_key; | |||
| XDB_MESSAGE(XDB_NOTE, " nekobee_set_note_off: called for voice %p, key %d\n", voice, key); | |||
| /* save release velocity */ | |||
| voice->velocity = rvelocity; | |||
| previous_top_key = synth->held_keys[0]; | |||
| /* remove this key from list of held keys */ | |||
| nekobee_voice_remove_held_key(synth, key); | |||
| if (synth->held_keys[0] >= 0) { | |||
| /* still some keys held */ | |||
| if (synth->held_keys[0] != previous_top_key) { | |||
| /* most-recently-played key has changed */ | |||
| voice->key = synth->held_keys[0]; | |||
| XDB_MESSAGE(XDB_NOTE, " note-off in monophonic section: changing pitch to %d\n", voice->key); | |||
| voice->target_pitch = nekobee_pitch[voice->key]; | |||
| if (synth->glide == XSYNTH_GLIDE_MODE_INITIAL || | |||
| synth->glide == XSYNTH_GLIDE_MODE_OFF) | |||
| voice->prev_pitch = voice->target_pitch; | |||
| /* if mono mode is 'both', re-trigger EGs */ | |||
| if (synth->monophonic == XSYNTH_MONO_MODE_BOTH && !_RELEASED(voice)) { | |||
| voice->vca_eg_phase = 0; | |||
| voice->vcf_eg_phase = 0; | |||
| } | |||
| } | |||
| } else { /* no keys still held */ | |||
| if (XSYNTH_SYNTH_SUSTAINED(synth)) { | |||
| /* no more keys in list, but we're sustained */ | |||
| XDB_MESSAGE(XDB_NOTE, " note-off in monophonic section: sustained with no held keys\n"); | |||
| if (!_RELEASED(voice)) | |||
| voice->status = XSYNTH_VOICE_SUSTAINED; | |||
| } else { /* not sustained */ | |||
| /* no more keys in list, so turn off note */ | |||
| XDB_MESSAGE(XDB_NOTE, " note-off in monophonic section: turning off voice %p\n", voice); | |||
| nekobee_voice_set_release_phase(voice); | |||
| voice->status = XSYNTH_VOICE_RELEASED; | |||
| } | |||
| } | |||
| } | |||
| /* | |||
| * nekobee_voice_release_note | |||
| */ | |||
| void | |||
| nekobee_voice_release_note(nekobee_synth_t *synth, nekobee_voice_t *voice) | |||
| { | |||
| XDB_MESSAGE(XDB_NOTE, " nekobee_voice_release_note: turning off voice %p\n", voice); | |||
| if (_ON(voice)) { | |||
| /* dummy up a release velocity */ | |||
| voice->rvelocity = 64; | |||
| } | |||
| nekobee_voice_set_release_phase(voice); | |||
| voice->status = XSYNTH_VOICE_RELEASED; | |||
| return; | |||
| (void)synth; | |||
| } | |||
| @@ -1,183 +0,0 @@ | |||
| /* nekobee DSSI software synthesizer plugin | |||
| * | |||
| * Copyright (C) 2004 Sean Bolton and others. | |||
| * | |||
| * Portions of this file may have come from Steve Brookes' | |||
| * nekobee, copyright (C) 1999 S. J. Brookes. | |||
| * Portions of this file may have come from Peter Hanappe's | |||
| * Fluidsynth, copyright (C) 2003 Peter Hanappe and others. | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or (at your option) any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be | |||
| * useful, but WITHOUT ANY WARRANTY; without even the implied | |||
| * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
| * PURPOSE. See the GNU General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU General Public | |||
| * License along with this program; if not, write to the Free | |||
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |||
| * MA 02111-1307, USA. | |||
| */ | |||
| #ifndef _XSYNTH_VOICE_H | |||
| #define _XSYNTH_VOICE_H | |||
| #include <string.h> | |||
| #include "nekobee_types.h" | |||
| /* maximum size of a rendering burst */ | |||
| #define XSYNTH_NUGGET_SIZE 64 | |||
| /* minBLEP constants */ | |||
| /* minBLEP table oversampling factor (must be a power of two): */ | |||
| #define MINBLEP_PHASES 64 | |||
| /* MINBLEP_PHASES minus one: */ | |||
| #define MINBLEP_PHASE_MASK 63 | |||
| /* length in samples of (truncated) step discontinuity delta: */ | |||
| #define STEP_DD_PULSE_LENGTH 72 | |||
| /* length in samples of (truncated) slope discontinuity delta: */ | |||
| #define SLOPE_DD_PULSE_LENGTH 71 | |||
| /* the longer of the two above: */ | |||
| #define LONGEST_DD_PULSE_LENGTH STEP_DD_PULSE_LENGTH | |||
| /* MINBLEP_BUFFER_LENGTH must be at least XSYNTH_NUGGET_SIZE plus | |||
| * LONGEST_DD_PULSE_LENGTH, and not less than twice LONGEST_DD_PULSE_LENGTH: */ | |||
| #define MINBLEP_BUFFER_LENGTH 512 | |||
| /* delay between start of DD pulse and the discontinuity, in samples: */ | |||
| #define DD_SAMPLE_DELAY 4 | |||
| struct _nekobee_patch_t | |||
| { | |||
| float tuning; | |||
| unsigned char waveform; | |||
| float cutoff; | |||
| float resonance; | |||
| float envmod; | |||
| float decay; | |||
| float accent; | |||
| float volume; | |||
| }; | |||
| enum nekobee_voice_status | |||
| { | |||
| XSYNTH_VOICE_OFF, /* silent: is not processed by render loop */ | |||
| XSYNTH_VOICE_ON, /* has not received a note off event */ | |||
| XSYNTH_VOICE_SUSTAINED, /* has received note off, but sustain controller is on */ | |||
| XSYNTH_VOICE_RELEASED /* had note off, not sustained, in final decay phase of envelopes */ | |||
| }; | |||
| struct blosc | |||
| { | |||
| int last_waveform, /* persistent */ | |||
| waveform, /* comes from LADSPA port each cycle */ | |||
| bp_high; /* persistent */ | |||
| float pos, /* persistent */ | |||
| pw; /* comes from LADSPA port each cycle */ | |||
| }; | |||
| /* | |||
| * nekobee_voice_t | |||
| */ | |||
| struct _nekobee_voice_t | |||
| { | |||
| unsigned int note_id; | |||
| unsigned char status; | |||
| unsigned char key; | |||
| unsigned char velocity; | |||
| unsigned char rvelocity; /* the note-off velocity */ | |||
| /* translated controller values */ | |||
| float pressure; /* filter resonance multiplier, off = 1.0, full on = 0.0 */ | |||
| /* persistent voice state */ | |||
| float prev_pitch, | |||
| target_pitch, | |||
| lfo_pos; | |||
| struct blosc osc1; | |||
| float vca_eg, | |||
| vcf_eg, | |||
| accent_slug, | |||
| delay1, | |||
| delay2, | |||
| delay3, | |||
| delay4, | |||
| c5; | |||
| unsigned char vca_eg_phase, | |||
| vcf_eg_phase; | |||
| int osc_index; /* shared index into osc_audio */ | |||
| float osc_audio[MINBLEP_BUFFER_LENGTH]; | |||
| float freqcut_buf[XSYNTH_NUGGET_SIZE]; | |||
| float vca_buf[XSYNTH_NUGGET_SIZE]; | |||
| }; | |||
| #define _PLAYING(voice) ((voice)->status != XSYNTH_VOICE_OFF) | |||
| #define _ON(voice) ((voice)->status == XSYNTH_VOICE_ON) | |||
| #define _SUSTAINED(voice) ((voice)->status == XSYNTH_VOICE_SUSTAINED) | |||
| #define _RELEASED(voice) ((voice)->status == XSYNTH_VOICE_RELEASED) | |||
| #define _AVAILABLE(voice) ((voice)->status == XSYNTH_VOICE_OFF) | |||
| extern float nekobee_pitch[128]; | |||
| typedef struct { float value, delta; } float_value_delta; | |||
| extern float_value_delta step_dd_table[]; | |||
| extern float slope_dd_table[]; | |||
| /* nekobee_voice.c */ | |||
| nekobee_voice_t *nekobee_voice_new(); | |||
| void nekobee_voice_note_on(nekobee_synth_t *synth, | |||
| nekobee_voice_t *voice, | |||
| unsigned char key, | |||
| unsigned char velocity); | |||
| void nekobee_voice_remove_held_key(nekobee_synth_t *synth, | |||
| unsigned char key); | |||
| void nekobee_voice_note_off(nekobee_synth_t *synth, | |||
| nekobee_voice_t *voice, | |||
| unsigned char key, | |||
| unsigned char rvelocity); | |||
| void nekobee_voice_release_note(nekobee_synth_t *synth, | |||
| nekobee_voice_t *voice); | |||
| void nekobee_voice_set_ports(nekobee_synth_t *synth, | |||
| nekobee_patch_t *patch); | |||
| void nekobee_voice_update_pressure_mod(nekobee_synth_t *synth, | |||
| nekobee_voice_t *voice); | |||
| /* nekobee_voice_render.c */ | |||
| void nekobee_init_tables(void); | |||
| void nekobee_voice_render(nekobee_synth_t *synth, nekobee_voice_t *voice, | |||
| float *out, unsigned long sample_count, | |||
| int do_control_update); | |||
| /* inline functions */ | |||
| /* | |||
| * nekobee_voice_off | |||
| * | |||
| * Purpose: Turns off a voice immediately, meaning that it is not processed | |||
| * anymore by the render loop. | |||
| */ | |||
| static inline void | |||
| nekobee_voice_off(nekobee_voice_t* voice) | |||
| { | |||
| voice->status = XSYNTH_VOICE_OFF; | |||
| /* silence the oscillator buffer for the next use */ | |||
| memset(voice->osc_audio, 0, MINBLEP_BUFFER_LENGTH * sizeof(float)); | |||
| /* -FIX- decrement active voice count? */ | |||
| } | |||
| /* | |||
| * nekobee_voice_start_voice | |||
| */ | |||
| static inline void | |||
| nekobee_voice_start_voice(nekobee_voice_t *voice) | |||
| { | |||
| voice->status = XSYNTH_VOICE_ON; | |||
| /* -FIX- increment active voice count? */ | |||
| } | |||
| #endif /* _XSYNTH_VOICE_H */ | |||
| @@ -1,414 +0,0 @@ | |||
| /* nekobee DSSI software synthesizer plugin | |||
| */ | |||
| #define _BSD_SOURCE 1 | |||
| #define _SVID_SOURCE 1 | |||
| #define _ISOC99_SOURCE 1 | |||
| #include <math.h> | |||
| #include "nekobee.h" | |||
| #include "nekobee_synth.h" | |||
| #include "nekobee_voice.h" | |||
| #ifndef M_PI | |||
| #define M_PI 3.14159265358979323846 | |||
| #endif | |||
| #define M_2PI_F (2.0f * (float)M_PI) | |||
| #define M_PI_F (float)M_PI | |||
| #define VCF_FREQ_MAX (0.825f) /* original filters only stable to this frequency */ | |||
| static int tables_initialized = 0; | |||
| float nekobee_pitch[128]; | |||
| #define pitch_ref_note 69 | |||
| #define volume_to_amplitude_scale 128 | |||
| static float volume_to_amplitude_table[4 + volume_to_amplitude_scale + 2]; | |||
| static float velocity_to_attenuation[128]; | |||
| static float qdB_to_amplitude_table[4 + 256 + 0]; | |||
| void | |||
| nekobee_init_tables(void) | |||
| { | |||
| int i; | |||
| float pexp; | |||
| float volume, volume_exponent; | |||
| float ol, amp; | |||
| if (tables_initialized) | |||
| return; | |||
| /* MIDI note to pitch */ | |||
| for (i = 0; i < 128; ++i) { | |||
| pexp = (float)(i - pitch_ref_note) / 12.0f; | |||
| nekobee_pitch[i] = powf(2.0f, pexp); | |||
| } | |||
| /* volume to amplitude | |||
| * | |||
| * This generates a curve which is: | |||
| * volume_to_amplitude_table[128 + 4] = 0.25 * 3.16... ~= -2dB | |||
| * volume_to_amplitude_table[64 + 4] = 0.25 * 1.0 ~= -12dB | |||
| * volume_to_amplitude_table[32 + 4] = 0.25 * 0.316... ~= -22dB | |||
| * volume_to_amplitude_table[16 + 4] = 0.25 * 0.1 ~= -32dB | |||
| * etc. | |||
| */ | |||
| volume_exponent = 1.0f / (2.0f * log10f(2.0f)); | |||
| for (i = 0; i <= volume_to_amplitude_scale; i++) { | |||
| volume = (float)i / (float)volume_to_amplitude_scale; | |||
| volume_to_amplitude_table[i + 4] = powf(2.0f * volume, volume_exponent) / 4.0f; | |||
| } | |||
| volume_to_amplitude_table[ -1 + 4] = 0.0f; | |||
| volume_to_amplitude_table[129 + 4] = volume_to_amplitude_table[128 + 4]; | |||
| /* velocity to attenuation | |||
| * | |||
| * Creates the velocity to attenuation lookup table, for converting | |||
| * velocities [1, 127] to full-velocity-sensitivity attenuation in | |||
| * quarter decibels. Modeled after my TX-7's velocity response.*/ | |||
| velocity_to_attenuation[0] = 253.9999f; | |||
| for (i = 1; i < 127; i++) { | |||
| if (i >= 10) { | |||
| ol = (powf(((float)i / 127.0f), 0.32f) - 1.0f) * 100.0f; | |||
| amp = powf(2.0f, ol / 8.0f); | |||
| } else { | |||
| ol = (powf(((float)10 / 127.0f), 0.32f) - 1.0f) * 100.0f; | |||
| amp = powf(2.0f, ol / 8.0f) * (float)i / 10.0f; | |||
| } | |||
| velocity_to_attenuation[i] = log10f(amp) * -80.0f; | |||
| } | |||
| velocity_to_attenuation[127] = 0.0f; | |||
| /* quarter-decibel attenuation to amplitude */ | |||
| qdB_to_amplitude_table[-1 + 4] = 1.0f; | |||
| for (i = 0; i <= 255; i++) { | |||
| qdB_to_amplitude_table[i + 4] = powf(10.0f, (float)i / -80.0f); | |||
| } | |||
| tables_initialized = 1; | |||
| } | |||
| static inline float | |||
| volume(float level) | |||
| { | |||
| unsigned char segment; | |||
| float fract; | |||
| level *= (float)volume_to_amplitude_scale; | |||
| segment = lrintf(level - 0.5f); | |||
| fract = level - (float)segment; | |||
| return volume_to_amplitude_table[segment + 4] + fract * | |||
| (volume_to_amplitude_table[segment + 5] - | |||
| volume_to_amplitude_table[segment + 4]); | |||
| } | |||
| static inline float | |||
| qdB_to_amplitude(float qdB) | |||
| { | |||
| int i = lrintf(qdB - 0.5f); | |||
| float f = qdB - (float)i; | |||
| return qdB_to_amplitude_table[i + 4] + f * | |||
| (qdB_to_amplitude_table[i + 5] - | |||
| qdB_to_amplitude_table[i + 4]); | |||
| } | |||
| void blosc_place_step_dd(float *buffer, int index, float phase, float w, float scale){ | |||
| float r; | |||
| int i; | |||
| r = MINBLEP_PHASES * phase / w; | |||
| i = lrintf(r - 0.5f); | |||
| r -= (float)i; | |||
| i &= MINBLEP_PHASE_MASK; /* port changes can cause i to be out-of-range */ | |||
| /* This would be better than the above, but more expensive: | |||
| * while (i < 0) { | |||
| * i += MINBLEP_PHASES; | |||
| * index++; | |||
| * } | |||
| */ | |||
| while (i < MINBLEP_PHASES * STEP_DD_PULSE_LENGTH) { | |||
| buffer[index] += scale * (step_dd_table[i].value + r * step_dd_table[i].delta); | |||
| i += MINBLEP_PHASES; | |||
| index++; | |||
| } | |||
| } | |||
| void vco(unsigned long sample_count, nekobee_voice_t *voice, struct blosc *osc, | |||
| int index, float w) | |||
| { | |||
| unsigned long sample; | |||
| float pos = osc->pos; | |||
| float pw, gain, halfgain, out; | |||
| pw=0.46f; | |||
| gain=1.0f; | |||
| halfgain=gain*0.5f; | |||
| int bp_high = osc->bp_high; | |||
| out=(bp_high ? halfgain : -halfgain); | |||
| switch (osc->waveform) | |||
| { | |||
| default: | |||
| case 0: { | |||
| for (sample = 0; sample < sample_count; sample++) { | |||
| pos += w; | |||
| if (bp_high) { | |||
| if (pos >= pw) { | |||
| blosc_place_step_dd(voice->osc_audio, index, pos - pw, w, -gain); | |||
| bp_high = 0; | |||
| out = -halfgain; | |||
| } | |||
| if (pos >= 1.0f) { | |||
| pos -= 1.0f; | |||
| blosc_place_step_dd(voice->osc_audio, index, pos, w, gain); | |||
| bp_high = 1; | |||
| out = halfgain; | |||
| } | |||
| } else { | |||
| if (pos >= 1.0f) { | |||
| pos -= 1.0f; | |||
| blosc_place_step_dd(voice->osc_audio, index, pos, w, gain); | |||
| bp_high = 1; | |||
| out = halfgain; | |||
| } | |||
| if (bp_high && pos >= pw) { | |||
| blosc_place_step_dd(voice->osc_audio, index, pos - pw, w, -gain); | |||
| bp_high = 0; | |||
| out = -halfgain; | |||
| } | |||
| } | |||
| voice->osc_audio[index + DD_SAMPLE_DELAY] += out; | |||
| index++; | |||
| } | |||
| osc->pos = pos; | |||
| osc->bp_high = bp_high; | |||
| break; | |||
| } | |||
| case 1: // sawtooth wave | |||
| { | |||
| for (sample=0; sample < sample_count; sample++) { | |||
| pos += w; | |||
| if (pos >= 1.0f) { | |||
| pos -= 1.0f; | |||
| blosc_place_step_dd(voice->osc_audio, index, pos, w, gain); | |||
| } | |||
| voice->osc_audio[index + DD_SAMPLE_DELAY] += gain * (0.5f - pos); | |||
| index++; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| osc->pos=pos; | |||
| } | |||
| static inline void | |||
| vcf_4pole(nekobee_voice_t *voice, unsigned long sample_count, | |||
| float *in, float *out, float *cutoff, float qres, float *amp) | |||
| { | |||
| unsigned long sample; | |||
| float freqcut, freqcut2, highpass, | |||
| delay1 = voice->delay1, | |||
| delay2 = voice->delay2, | |||
| delay3 = voice->delay3, | |||
| delay4 = voice->delay4; | |||
| qres = 2.0f - qres * 1.995f; | |||
| for (sample = 0; sample < sample_count; sample++) { | |||
| /* Hal Chamberlin's state variable filter */ | |||
| freqcut = cutoff[sample] * 2.0f; | |||
| freqcut2 = cutoff[sample] * 4.0f; | |||
| if (freqcut > VCF_FREQ_MAX) freqcut = VCF_FREQ_MAX; | |||
| if (freqcut2 > VCF_FREQ_MAX) freqcut2 = VCF_FREQ_MAX; | |||
| delay2 = delay2 + freqcut * delay1; /* delay2/4 = lowpass output */ | |||
| highpass = in[sample] - delay2 - qres * delay1; | |||
| delay1 = freqcut * highpass + delay1; /* delay1/3 = bandpass output */ | |||
| delay4 = delay4 + freqcut2 * delay3; | |||
| highpass = delay2 - delay4 - qres * delay3; | |||
| delay3 = freqcut2 * highpass + delay3; | |||
| /* mix filter output into output buffer */ | |||
| out[sample] += 0.1*atan(3*delay4 * amp[sample]); | |||
| } | |||
| voice->delay1 = delay1; | |||
| voice->delay2 = delay2; | |||
| voice->delay3 = delay3; | |||
| voice->delay4 = delay4; | |||
| voice->c5 = 0.0f; | |||
| } | |||
| /* | |||
| * nekobee_voice_render | |||
| * | |||
| * generate the actual sound data for this voice | |||
| */ | |||
| void | |||
| nekobee_voice_render(nekobee_synth_t *synth, nekobee_voice_t *voice, | |||
| float *out, unsigned long sample_count, | |||
| int do_control_update) | |||
| { | |||
| unsigned long sample; | |||
| /* state variables saved in voice */ | |||
| float lfo_pos = voice->lfo_pos, | |||
| vca_eg = voice->vca_eg, | |||
| vcf_eg = voice->vcf_eg; | |||
| unsigned char vca_eg_phase = voice->vca_eg_phase, | |||
| vcf_eg_phase = voice->vcf_eg_phase; | |||
| int osc_index = voice->osc_index; | |||
| /* temporary variables used in calculating voice */ | |||
| float fund_pitch; | |||
| float deltat = synth->deltat; | |||
| float freq, cutoff, vcf_amt; | |||
| float vcf_acc_amt; | |||
| /* set up synthesis variables from patch */ | |||
| float omega; | |||
| float vca_eg_amp = qdB_to_amplitude(velocity_to_attenuation[voice->velocity] * 0); | |||
| float vca_eg_rate_level[3], vca_eg_one_rate[3]; | |||
| float vcf_eg_amp = qdB_to_amplitude(velocity_to_attenuation[voice->velocity] * 0); | |||
| float vcf_eg_rate_level[3], vcf_eg_one_rate[3]; | |||
| float qres = synth->resonance; | |||
| float vol_out = volume(synth->volume); | |||
| float velocity = (voice->velocity); | |||
| float vcf_egdecay = synth->decay; | |||
| fund_pitch = 0.1f*voice->target_pitch +0.9 * voice->prev_pitch; /* glide */ | |||
| if (do_control_update) { | |||
| voice->prev_pitch = fund_pitch; /* save pitch for next time */ | |||
| } | |||
| fund_pitch *= 440.0f; | |||
| omega = synth->tuning * fund_pitch; | |||
| // if we have triggered ACCENT | |||
| // we need a shorter decay | |||
| // we should probably have something like this in the note on code | |||
| // that could trigger an ACCENT light | |||
| if (velocity>90) { | |||
| vcf_egdecay=.0005; | |||
| } | |||
| // VCA - In a real 303, it is set for around 2 seconds | |||
| vca_eg_rate_level[0] = 0.1f * vca_eg_amp; // instant on attack | |||
| vca_eg_one_rate[0] = 0.9f; // very fast | |||
| vca_eg_rate_level[1] = 0.0f; // sustain is zero | |||
| vca_eg_one_rate[1] = 1.0f - 0.00001f; // decay time is very slow | |||
| vca_eg_rate_level[2] = 0.0f; // decays to zero | |||
| vca_eg_one_rate[2] = 0.975f; // very fast release | |||
| // VCF - funny things go on with the accent | |||
| vcf_eg_rate_level[0] = 0.1f * vcf_eg_amp; | |||
| vcf_eg_one_rate[0] = 1-0.1f; //0.9f; | |||
| vcf_eg_rate_level[1] = 0.0f; // vcf_egdecay * *(synth->vcf_eg_sustain_level) * vcf_eg_amp; | |||
| vcf_eg_one_rate[1] = 1.0f - vcf_egdecay; | |||
| vcf_eg_rate_level[2] = 0.0f; | |||
| vcf_eg_one_rate[2] = 0.9995f; // 1.0f - *(synth->vcf_eg_release_time); | |||
| vca_eg_amp *= 0.99f; | |||
| vcf_eg_amp *= 0.99f; | |||
| freq = M_PI_F * deltat * fund_pitch * synth->mod_wheel; /* now (0 to 1) * pi */ | |||
| cutoff = 0.008f * synth->cutoff; | |||
| // 303 always has slight VCF mod | |||
| vcf_amt = 0.05f+(synth->envmod*0.75); | |||
| /* copy some things so oscillator functions can see them */ | |||
| voice->osc1.waveform = lrintf(synth->waveform); | |||
| // work out how much the accent will affect the filter | |||
| vcf_acc_amt=.333f+ (synth->resonance/1.5f); | |||
| for (sample = 0; sample < sample_count; sample++) { | |||
| vca_eg = vca_eg_rate_level[vca_eg_phase] + vca_eg_one_rate[vca_eg_phase] * vca_eg; | |||
| vcf_eg = vcf_eg_rate_level[vcf_eg_phase] + vcf_eg_one_rate[vcf_eg_phase] * vcf_eg; | |||
| voice->freqcut_buf[sample] = (cutoff + (vcf_amt * vcf_eg/2.0f) + (synth->vcf_accent * synth->accent*0.5f)); | |||
| voice->vca_buf[sample] = vca_eg * vol_out*(1.0f + synth->accent*synth->vca_accent); | |||
| if (!vca_eg_phase && vca_eg > vca_eg_amp) vca_eg_phase = 1; /* flip from attack to decay */ | |||
| if (!vcf_eg_phase && vcf_eg > vcf_eg_amp) vcf_eg_phase = 1; /* flip from attack to decay */ | |||
| } | |||
| // oscillator | |||
| vco(sample_count, voice, &voice->osc1, osc_index, deltat * omega); | |||
| // VCF and VCA | |||
| vcf_4pole(voice, sample_count, voice->osc_audio + osc_index, out, voice->freqcut_buf, qres, voice->vca_buf); | |||
| osc_index += sample_count; | |||
| if (do_control_update) { | |||
| /* do those things should be done only once per control-calculation | |||
| * interval ("nugget"), such as voice check-for-dead, pitch envelope | |||
| * calculations, volume envelope phase transition checks, etc. */ | |||
| /* check if we've decayed to nothing, turn off voice if so */ | |||
| if (vca_eg_phase == 2 && voice->vca_buf[sample_count - 1] < 6.26e-6f) { | |||
| // sound has completed its release phase (>96dB below volume '5' max) | |||
| XDB_MESSAGE(XDB_NOTE, " nekobee_voice_render check for dead: killing note id %d\n", voice->note_id); | |||
| nekobee_voice_off(voice); | |||
| return; // we're dead now, so return | |||
| } | |||
| /* already saved prev_pitch above */ | |||
| /* check oscillator audio buffer index, shift buffer if necessary */ | |||
| if (osc_index > MINBLEP_BUFFER_LENGTH - (XSYNTH_NUGGET_SIZE + LONGEST_DD_PULSE_LENGTH)) { | |||
| memcpy(voice->osc_audio, voice->osc_audio + osc_index, | |||
| LONGEST_DD_PULSE_LENGTH * sizeof (float)); | |||
| memset(voice->osc_audio + LONGEST_DD_PULSE_LENGTH, 0, | |||
| (MINBLEP_BUFFER_LENGTH - LONGEST_DD_PULSE_LENGTH) * sizeof (float)); | |||
| osc_index = 0; | |||
| } | |||
| } | |||
| /* save things for next time around */ | |||
| voice->lfo_pos = lfo_pos; | |||
| voice->vca_eg = vca_eg; | |||
| voice->vca_eg_phase = vca_eg_phase; | |||
| voice->vcf_eg = vcf_eg; | |||
| voice->vcf_eg_phase = vcf_eg_phase; | |||
| voice->osc_index = osc_index; | |||
| return; | |||
| (void)freq; | |||
| (void)vcf_acc_amt; | |||
| } | |||
| @@ -1,85 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // config fix | |||
| #include "distrho-pingpongpan/DistrhoPluginInfo.h" | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-pingpongpan/DistrhoArtworkPingPongPan.cpp" | |||
| #include "distrho-pingpongpan/DistrhoPluginPingPongPan.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "distrho-pingpongpan/DistrhoUIPingPongPan.cpp" | |||
| #endif | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "DistrhoUIMain.cpp" | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor pingpongpanDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ DistrhoPluginPingPongPan::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "pingpongpan", | |||
| /* maker */ "falkTX, Michael Gruhn", | |||
| /* copyright */ "LGPL", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_pingpongpan(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_pingpongpan() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&pingpongpanDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,35 +0,0 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_DISTRHOARTWORKPINGPONGPAN_HPP | |||
| #define BINARY_DISTRHOARTWORKPINGPONGPAN_HPP | |||
| namespace DistrhoArtworkPingPongPan | |||
| { | |||
| extern const char* aboutData; | |||
| const unsigned int aboutDataSize = 172710; | |||
| const unsigned int aboutWidth = 303; | |||
| const unsigned int aboutHeight = 190; | |||
| extern const char* aboutButtonHoverData; | |||
| const unsigned int aboutButtonHoverDataSize = 7600; | |||
| const unsigned int aboutButtonHoverWidth = 95; | |||
| const unsigned int aboutButtonHoverHeight = 20; | |||
| extern const char* aboutButtonNormalData; | |||
| const unsigned int aboutButtonNormalDataSize = 7600; | |||
| const unsigned int aboutButtonNormalWidth = 95; | |||
| const unsigned int aboutButtonNormalHeight = 20; | |||
| extern const char* backgroundData; | |||
| const unsigned int backgroundDataSize = 157080; | |||
| const unsigned int backgroundWidth = 308; | |||
| const unsigned int backgroundHeight = 170; | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 17956; | |||
| const unsigned int knobWidth = 67; | |||
| const unsigned int knobHeight = 67; | |||
| } | |||
| #endif // BINARY_DISTRHOARTWORKPINGPONGPAN_HPP | |||
| @@ -1,33 +0,0 @@ | |||
| /* | |||
| * DISTRHO PingPongPan Plugin, based on PingPongPan by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_BRAND "DISTRHO" | |||
| #define DISTRHO_PLUGIN_NAME "Ping Pong Pan" | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/PingPongPan" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_RT_SAFE 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_USES_MODGUI 1 | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:SpatialPlugin" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,161 +0,0 @@ | |||
| /* | |||
| * DISTRHO PingPongPan Plugin, based on PingPongPan by Michael Gruhn | |||
| * Copyright (C) 2007 Michael Gruhn <michael-gruhn@web.de> | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPluginPingPongPan.hpp" | |||
| #include <cmath> | |||
| static const float k2PI = 6.283185307f; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoPluginPingPongPan::DistrhoPluginPingPongPan() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| loadProgram(0); | |||
| // reset | |||
| deactivate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void DistrhoPluginPingPongPan::initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramFreq: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Frequency"; | |||
| parameter.symbol = "freq"; | |||
| parameter.ranges.def = 50.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| case paramWidth: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Width"; | |||
| parameter.symbol = "width"; | |||
| parameter.unit = "%"; | |||
| parameter.ranges.def = 75.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoPluginPingPongPan::initProgramName(uint32_t index, String& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float DistrhoPluginPingPongPan::getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramFreq: | |||
| return fFreq; | |||
| case paramWidth: | |||
| return fWidth; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void DistrhoPluginPingPongPan::setParameterValue(uint32_t index, float value) | |||
| { | |||
| if (getSampleRate() <= 0.0) | |||
| return; | |||
| switch (index) | |||
| { | |||
| case paramFreq: | |||
| fFreq = value; | |||
| waveSpeed = (k2PI * fFreq / 100.0f)/(float)getSampleRate(); | |||
| break; | |||
| case paramWidth: | |||
| fWidth = value; | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoPluginPingPongPan::loadProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fFreq = 50.0f; | |||
| fWidth = 75.0f; | |||
| // reset filter values | |||
| activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void DistrhoPluginPingPongPan::activate() | |||
| { | |||
| waveSpeed = (k2PI * fFreq / 100.0f)/(float)getSampleRate(); | |||
| } | |||
| void DistrhoPluginPingPongPan::deactivate() | |||
| { | |||
| wavePos = 0.0f; | |||
| } | |||
| void DistrhoPluginPingPongPan::run(const float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| const float* in1 = inputs[0]; | |||
| const float* in2 = inputs[1]; | |||
| float* out1 = outputs[0]; | |||
| float* out2 = outputs[1]; | |||
| for (uint32_t i=0; i < frames; ++i) | |||
| { | |||
| pan = std::fmin(std::fmax(std::sin(wavePos) * (fWidth/100.0f), -1.0f), 1.0f); | |||
| if ((wavePos += waveSpeed) >= k2PI) | |||
| wavePos -= k2PI; | |||
| out1[i] = in1[i] * (pan > 0.0f ? 1.0f-pan : 1.0f); | |||
| out2[i] = in2[i] * (pan < 0.0f ? 1.0f+pan : 1.0f); | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new DistrhoPluginPingPongPan(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,114 +0,0 @@ | |||
| /* | |||
| * DISTRHO PingPongPan Plugin, based on PingPongPan by Michael Gruhn | |||
| * Copyright (C) 2007 Michael Gruhn <michael-gruhn@web.de> | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_PINGPONGPAN_HPP_INCLUDED | |||
| #define DISTRHO_PLUGIN_PINGPONGPAN_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoPluginPingPongPan : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramFreq = 0, | |||
| paramWidth, | |||
| paramCount | |||
| }; | |||
| DistrhoPluginPingPongPan(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "PingPongPan"; | |||
| } | |||
| const char* getDescription() const override | |||
| { | |||
| return "Ping Pong Panning."; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "DISTRHO"; | |||
| } | |||
| const char* getHomePage() const override | |||
| { | |||
| return "https://github.com/DISTRHO/Mini-Series"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "LGPL"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return d_version(1, 0, 0); | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('D', 'P', 'P', 'P'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t index, Parameter& parameter) override; | |||
| void initProgramName(uint32_t index, String& programName) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t index) const override; | |||
| void setParameterValue(uint32_t index, float value) override; | |||
| void loadProgram(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void activate() override; | |||
| void deactivate() override; | |||
| void run(const float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float fFreq; | |||
| float fWidth; | |||
| float waveSpeed; | |||
| float pan, wavePos; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPluginPingPongPan) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_PLUGIN_PINGPONGPAN_HPP_INCLUDED | |||
| @@ -1,133 +0,0 @@ | |||
| /* | |||
| * DISTRHO PingPongPan Plugin, based on PingPongPan by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPluginPingPongPan.hpp" | |||
| #include "DistrhoUIPingPongPan.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| namespace Art = DistrhoArtworkPingPongPan; | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUIPingPongPan::DistrhoUIPingPongPan() | |||
| : UI(Art::backgroundWidth, Art::backgroundHeight), | |||
| fImgBackground(Art::backgroundData, Art::backgroundWidth, Art::backgroundHeight, GL_BGR), | |||
| fAboutWindow(this) | |||
| { | |||
| // about | |||
| Image imageAbout(Art::aboutData, Art::aboutWidth, Art::aboutHeight, GL_BGR); | |||
| fAboutWindow.setImage(imageAbout); | |||
| // knobs | |||
| Image knobImage(Art::knobData, Art::knobWidth, Art::knobHeight); | |||
| // knob Low-Mid | |||
| fKnobFreq = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobFreq->setId(DistrhoPluginPingPongPan::paramFreq); | |||
| fKnobFreq->setAbsolutePos(60, 58); | |||
| fKnobFreq->setRange(0.0f, 100.0f); | |||
| fKnobFreq->setDefault(50.0f); | |||
| fKnobFreq->setRotationAngle(270); | |||
| fKnobFreq->setCallback(this); | |||
| // knob Mid-High | |||
| fKnobWidth = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobWidth->setId(DistrhoPluginPingPongPan::paramWidth); | |||
| fKnobWidth->setAbsolutePos(182, 58); | |||
| fKnobWidth->setRange(0.0f, 100.0f); | |||
| fKnobWidth->setDefault(75.0f); | |||
| fKnobWidth->setRotationAngle(270); | |||
| fKnobWidth->setCallback(this); | |||
| // about button | |||
| Image aboutImageNormal(Art::aboutButtonNormalData, Art::aboutButtonNormalWidth, Art::aboutButtonNormalHeight); | |||
| Image aboutImageHover(Art::aboutButtonHoverData, Art::aboutButtonHoverWidth, Art::aboutButtonHoverHeight); | |||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | |||
| fButtonAbout->setAbsolutePos(183, 8); | |||
| fButtonAbout->setCallback(this); | |||
| // set default values | |||
| programLoaded(0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void DistrhoUIPingPongPan::parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case DistrhoPluginPingPongPan::paramFreq: | |||
| fKnobFreq->setValue(value); | |||
| break; | |||
| case DistrhoPluginPingPongPan::paramWidth: | |||
| fKnobWidth->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| void DistrhoUIPingPongPan::programLoaded(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fKnobFreq->setValue(50.0f); | |||
| fKnobWidth->setValue(75.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void DistrhoUIPingPongPan::imageButtonClicked(ImageButton* button, int) | |||
| { | |||
| if (button != fButtonAbout) | |||
| return; | |||
| fAboutWindow.exec(); | |||
| } | |||
| void DistrhoUIPingPongPan::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), true); | |||
| } | |||
| void DistrhoUIPingPongPan::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), false); | |||
| } | |||
| void DistrhoUIPingPongPan::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| setParameterValue(knob->getId(), value); | |||
| } | |||
| void DistrhoUIPingPongPan::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new DistrhoUIPingPongPan(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,67 +0,0 @@ | |||
| /* | |||
| * DISTRHO PingPongPan Plugin, based on PingPongPan by Michael Gruhn | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_UI_PINGPONGPAN_HPP_INCLUDED | |||
| #define DISTRHO_UI_PINGPONGPAN_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageWidgets.hpp" | |||
| #include "DistrhoArtworkPingPongPan.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoUIPingPongPan : public UI, | |||
| public ImageButton::Callback, | |||
| public ImageKnob::Callback | |||
| { | |||
| public: | |||
| DistrhoUIPingPongPan(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t index, float value) override; | |||
| void programLoaded(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageButtonClicked(ImageButton* button, int) override; | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageAboutWindow fAboutWindow; | |||
| ScopedPointer<ImageButton> fButtonAbout; | |||
| ScopedPointer<ImageKnob> fKnobFreq, fKnobWidth; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUIPingPongPan) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_UI_PINGPONGPAN_HPP_INCLUDED | |||
| @@ -1,67 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-prom/DistrhoPluginProM.cpp" | |||
| #include "distrho-prom/DistrhoUIProM.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor promDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 0, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "prom", | |||
| /* maker */ "falkTX", | |||
| /* copyright */ "LGPL", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_prom(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_prom() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&promDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,33 +0,0 @@ | |||
| /* | |||
| * DISTRHO ProM Plugin | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_BRAND "DISTRHO" | |||
| #define DISTRHO_PLUGIN_NAME "ProM" | |||
| #define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/ProM" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 1 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
| // required by projectM | |||
| #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,84 +0,0 @@ | |||
| /* | |||
| * DISTRHO ProM Plugin | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPluginProM.hpp" | |||
| #include "libprojectM/projectM.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoPluginProM::DistrhoPluginProM() | |||
| : Plugin(0, 0, 0), | |||
| fPM(nullptr) | |||
| { | |||
| } | |||
| DistrhoPluginProM::~DistrhoPluginProM() | |||
| { | |||
| DISTRHO_SAFE_ASSERT(fPM == nullptr); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void DistrhoPluginProM::initParameter(uint32_t, Parameter&) | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float DistrhoPluginProM::getParameterValue(uint32_t) const | |||
| { | |||
| return 0.0f; | |||
| } | |||
| void DistrhoPluginProM::setParameterValue(uint32_t, float) | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void DistrhoPluginProM::run(const float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| const float* in = inputs[0]; | |||
| float* out = outputs[0]; | |||
| if (out != in) | |||
| std::memcpy(out, in, sizeof(float)*frames); | |||
| const MutexLocker csm(fMutex); | |||
| if (fPM == nullptr) | |||
| return; | |||
| if (PCM* const pcm = const_cast<PCM*>(fPM->pcm())) | |||
| pcm->addPCMfloat(in, frames); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new DistrhoPluginProM(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,106 +0,0 @@ | |||
| /* | |||
| * DISTRHO ProM Plugin | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_PROM_HPP_INCLUDED | |||
| #define DISTRHO_PLUGIN_PROM_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| #include "extra/Mutex.hpp" | |||
| class projectM; | |||
| class DistrhoUIProM; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoPluginProM : public Plugin | |||
| { | |||
| public: | |||
| DistrhoPluginProM(); | |||
| ~DistrhoPluginProM() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "ProM"; | |||
| } | |||
| const char* getDescription() const override | |||
| { | |||
| return "ProjectM visualizer."; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "DISTRHO"; | |||
| } | |||
| const char* getHomePage() const override | |||
| { | |||
| return "https://github.com/DISTRHO/ProM"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "LGPL"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return d_version(1, 0, 0); | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('D', 'P', 'r', 'M'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t, Parameter&) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t) const override; | |||
| void setParameterValue(uint32_t, float) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void run(const float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| Mutex fMutex; | |||
| projectM* fPM; | |||
| friend class DistrhoUIProM; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPluginProM) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_PLUGIN_PROM_HPP_INCLUDED | |||
| @@ -1,304 +0,0 @@ | |||
| /* | |||
| * DISTRHO ProM Plugin | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "DistrhoPluginProM.hpp" | |||
| #include "DistrhoUIProM.hpp" | |||
| #include "libprojectM/projectM.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| #if 0 | |||
| static const projectM::Settings kSettings = { | |||
| /* meshX */ 32, | |||
| /* meshY */ 24, | |||
| /* fps */ 35, | |||
| /* textureSize */ 1024, | |||
| /* windowWidth */ 512, | |||
| /* windowHeight */ 512, | |||
| /* presetURL */ "/usr/share/projectM/presets", | |||
| /* titleFontURL */ "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", | |||
| /* menuFontURL */ "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf", | |||
| /* smoothPresetDuration */ 5, | |||
| /* presetDuration */ 30, | |||
| /* beatSensitivity */ 10.0f, | |||
| /* aspectCorrection */ true, | |||
| /* easterEgg */ 1.0f, | |||
| /* shuffleEnabled */ true, | |||
| /* softCutRatingsEnabled */ false | |||
| }; | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUIProM::DistrhoUIProM() | |||
| : UI(512, 512) | |||
| { | |||
| } | |||
| DistrhoUIProM::~DistrhoUIProM() | |||
| { | |||
| if (DistrhoPluginProM* const dspPtr = (DistrhoPluginProM*)getPluginInstancePointer()) | |||
| { | |||
| const MutexLocker csm(dspPtr->fMutex); | |||
| dspPtr->fPM = nullptr; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void DistrhoUIProM::parameterChanged(uint32_t, float) | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // UI Callbacks | |||
| void DistrhoUIProM::uiIdle() | |||
| { | |||
| if (fPM == nullptr) | |||
| return; | |||
| repaint(); | |||
| if (DistrhoPluginProM* const dspPtr = (DistrhoPluginProM*)getPluginInstancePointer()) | |||
| { | |||
| if (dspPtr->fPM != nullptr) | |||
| return; | |||
| const MutexLocker csm(dspPtr->fMutex); | |||
| dspPtr->fPM = fPM; | |||
| } | |||
| } | |||
| void DistrhoUIProM::uiReshape(uint width, uint height) | |||
| { | |||
| glEnable(GL_BLEND); | |||
| glEnable(GL_LINE_SMOOTH); | |||
| glEnable(GL_POINT_SMOOTH); | |||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
| glShadeModel(GL_SMOOTH); | |||
| glMatrixMode(GL_TEXTURE); | |||
| glLoadIdentity(); | |||
| glMatrixMode(GL_PROJECTION); | |||
| glLoadIdentity(); | |||
| glOrtho(0, width, height, 0, 0.0f, 1.0f); | |||
| glViewport(0, 0, width, height); | |||
| glMatrixMode(GL_MODELVIEW); | |||
| glLoadIdentity(); | |||
| glDrawBuffer(GL_BACK); | |||
| glReadBuffer(GL_BACK); | |||
| glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | |||
| glLineStipple(2, 0xAAAA); | |||
| if (fPM == nullptr) | |||
| //fPM = new projectM(kSettings); | |||
| fPM = new projectM("/usr/share/projectM/config.inp"); | |||
| fPM->projectM_resetGL(width, height); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void DistrhoUIProM::onDisplay() | |||
| { | |||
| if (fPM == nullptr) | |||
| return; | |||
| fPM->renderFrame(); | |||
| } | |||
| bool DistrhoUIProM::onKeyboard(const KeyboardEvent& ev) | |||
| { | |||
| if (fPM == nullptr) | |||
| return false; | |||
| if (ev.press && (ev.key == '1' || ev.key == '+' || ev.key == '-')) | |||
| { | |||
| if (ev.key == '1') | |||
| { | |||
| if (getWidth() != 512 || getHeight() != 512) | |||
| setSize(512, 512); | |||
| } | |||
| else if (ev.key == '+') | |||
| { | |||
| /**/ if (getWidth() < 1100 && getHeight() < 1100) | |||
| setSize(getWidth()+100, getHeight()+100); | |||
| else if (getWidth() != 1100 || getHeight() != 1100) | |||
| setSize(1100, 1100); | |||
| } | |||
| else if (ev.key == '-') | |||
| { | |||
| /**/ if (getWidth() >= 200 && getHeight() >= 200) | |||
| setSize(getWidth()-100, getHeight()-100); | |||
| else if (getWidth() != 100 || getHeight() != 100) | |||
| setSize(100, 100); | |||
| } | |||
| return true; | |||
| } | |||
| projectMKeycode pmKey = PROJECTM_K_NONE; | |||
| projectMModifier pmMod = PROJECTM_KMOD_LSHIFT; | |||
| if ((ev.key >= PROJECTM_K_0 && ev.key <= PROJECTM_K_9) || | |||
| (ev.key >= PROJECTM_K_A && ev.key <= PROJECTM_K_Z) || | |||
| (ev.key >= PROJECTM_K_a && ev.key <= PROJECTM_K_z)) | |||
| { | |||
| pmKey = static_cast<projectMKeycode>(ev.key); | |||
| } | |||
| else | |||
| { | |||
| switch (ev.key) | |||
| { | |||
| case DGL_NAMESPACE::kCharBackspace: | |||
| pmKey = PROJECTM_K_BACKSPACE; | |||
| break; | |||
| case DGL_NAMESPACE::kCharEscape: | |||
| pmKey = PROJECTM_K_ESCAPE; | |||
| break; | |||
| case DGL_NAMESPACE::kCharDelete: | |||
| pmKey = PROJECTM_K_DELETE; | |||
| break; | |||
| } | |||
| } | |||
| if (pmKey == PROJECTM_K_NONE) | |||
| return false; | |||
| if (ev.mod & DGL_NAMESPACE::kModifierControl) | |||
| pmMod = PROJECTM_KMOD_LCTRL; | |||
| fPM->key_handler(ev.press ? PROJECTM_KEYUP : PROJECTM_KEYDOWN, pmKey, pmMod); | |||
| return true; | |||
| } | |||
| bool DistrhoUIProM::onSpecial(const SpecialEvent& ev) | |||
| { | |||
| if (fPM == nullptr) | |||
| return false; | |||
| projectMKeycode pmKey = PROJECTM_K_NONE; | |||
| projectMModifier pmMod = PROJECTM_KMOD_LSHIFT; | |||
| switch (ev.key) | |||
| { | |||
| case DGL_NAMESPACE::kKeyF1: | |||
| pmKey = PROJECTM_K_F1; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF2: | |||
| pmKey = PROJECTM_K_F2; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF3: | |||
| pmKey = PROJECTM_K_F3; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF4: | |||
| pmKey = PROJECTM_K_F4; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF5: | |||
| pmKey = PROJECTM_K_F5; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF6: | |||
| pmKey = PROJECTM_K_F6; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF7: | |||
| pmKey = PROJECTM_K_F7; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF8: | |||
| pmKey = PROJECTM_K_F8; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF9: | |||
| pmKey = PROJECTM_K_F9; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF10: | |||
| pmKey = PROJECTM_K_F10; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF11: | |||
| pmKey = PROJECTM_K_F11; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyF12: | |||
| pmKey = PROJECTM_K_F12; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyLeft: | |||
| pmKey = PROJECTM_K_LEFT; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyUp: | |||
| pmKey = PROJECTM_K_UP; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyRight: | |||
| pmKey = PROJECTM_K_RIGHT; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyDown: | |||
| pmKey = PROJECTM_K_DOWN; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyPageUp: | |||
| pmKey = PROJECTM_K_PAGEUP; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyPageDown: | |||
| pmKey = PROJECTM_K_PAGEDOWN; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyHome: | |||
| pmKey = PROJECTM_K_HOME; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyEnd: | |||
| pmKey = PROJECTM_K_END; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyInsert: | |||
| pmKey = PROJECTM_K_INSERT; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyShift: | |||
| pmKey = PROJECTM_K_LSHIFT; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyControl: | |||
| pmKey = PROJECTM_K_LCTRL; | |||
| break; | |||
| case DGL_NAMESPACE::kKeyAlt: | |||
| case DGL_NAMESPACE::kKeySuper: | |||
| break; | |||
| } | |||
| if (pmKey == PROJECTM_K_NONE) | |||
| return false; | |||
| if (ev.mod & DGL_NAMESPACE::kModifierControl) | |||
| pmMod = PROJECTM_KMOD_LCTRL; | |||
| fPM->key_handler(ev.press ? PROJECTM_KEYUP : PROJECTM_KEYDOWN, pmKey, pmMod); | |||
| return true; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new DistrhoUIProM(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,63 +0,0 @@ | |||
| /* | |||
| * DISTRHO ProM Plugin | |||
| * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #ifndef DISTRHO_UI_PROM_HPP_INCLUDED | |||
| #define DISTRHO_UI_PROM_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| class projectM; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class DistrhoUIProM : public UI | |||
| { | |||
| public: | |||
| DistrhoUIProM(); | |||
| ~DistrhoUIProM() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t, float) override; | |||
| // ------------------------------------------------------------------- | |||
| // UI Callbacks | |||
| void uiIdle() override; | |||
| void uiReshape(uint width, uint height) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void onDisplay() override; | |||
| bool onKeyboard(const KeyboardEvent&) override; | |||
| bool onSpecial(const SpecialEvent&) override; | |||
| private: | |||
| ScopedPointer<projectM> fPM; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUIProM) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // DISTRHO_UI_PROM_HPP_INCLUDED | |||
| @@ -1,87 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // config fix | |||
| #include "distrho-vectorjuice/DistrhoPluginInfo.h" | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-vectorjuice/VectorJuicePlugin.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "distrho-vectorjuice/VectorJuiceArtwork.cpp" | |||
| #include "distrho-vectorjuice/VectorJuiceUI.cpp" | |||
| #endif | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "DistrhoUIMain.cpp" | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor vectorjuiceDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ 13, | |||
| /* paramOuts */ 4, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "vectorjuice", | |||
| /* maker */ "Andre Sklenar", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_vectorjuice(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_vectorjuice() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&vectorjuiceDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,36 +0,0 @@ | |||
| /* | |||
| * Vector Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_NAME "VectorJuice" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 8 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
| #define DISTRHO_PLUGIN_URI "urn:distrho:VectorJuice" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,55 +0,0 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_VECTORJUICEARTWORK_HPP | |||
| #define BINARY_VECTORJUICEARTWORK_HPP | |||
| namespace VectorJuiceArtwork | |||
| { | |||
| extern const char* aboutData; | |||
| const unsigned int aboutDataSize = 180000; | |||
| const unsigned int aboutWidth = 300; | |||
| const unsigned int aboutHeight = 200; | |||
| extern const char* aboutButtonHoverData; | |||
| const unsigned int aboutButtonHoverDataSize = 5888; | |||
| const unsigned int aboutButtonHoverWidth = 92; | |||
| const unsigned int aboutButtonHoverHeight = 16; | |||
| extern const char* aboutButtonNormalData; | |||
| const unsigned int aboutButtonNormalDataSize = 5888; | |||
| const unsigned int aboutButtonNormalWidth = 92; | |||
| const unsigned int aboutButtonNormalHeight = 16; | |||
| extern const char* backgroundData; | |||
| const unsigned int backgroundDataSize = 933432; | |||
| const unsigned int backgroundWidth = 712; | |||
| const unsigned int backgroundHeight = 437; | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 10404; | |||
| const unsigned int knobWidth = 51; | |||
| const unsigned int knobHeight = 51; | |||
| extern const char* orbitData; | |||
| const unsigned int orbitDataSize = 4096; | |||
| const unsigned int orbitWidth = 32; | |||
| const unsigned int orbitHeight = 32; | |||
| extern const char* roundletData; | |||
| const unsigned int roundletDataSize = 2500; | |||
| const unsigned int roundletWidth = 25; | |||
| const unsigned int roundletHeight = 25; | |||
| extern const char* sliderData; | |||
| const unsigned int sliderDataSize = 2600; | |||
| const unsigned int sliderWidth = 26; | |||
| const unsigned int sliderHeight = 25; | |||
| extern const char* subOrbitData; | |||
| const unsigned int subOrbitDataSize = 3364; | |||
| const unsigned int subOrbitWidth = 29; | |||
| const unsigned int subOrbitHeight = 29; | |||
| } | |||
| #endif // BINARY_VECTORJUICEARTWORK_HPP | |||
| @@ -1,391 +0,0 @@ | |||
| /* | |||
| * Vector Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "VectorJuicePlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| VectorJuicePlugin::VectorJuicePlugin() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| loadProgram(0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void VectorJuicePlugin::initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramX: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "X"; | |||
| parameter.symbol = "x"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramY: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Y"; | |||
| parameter.symbol = "y"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitSizeX: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Orbit Size X"; | |||
| parameter.symbol = "sizex"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitSizeY: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Orbit Size Y"; | |||
| parameter.symbol = "sizey"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitSpeedX: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Orbit Speed X"; | |||
| parameter.symbol = "speedx"; | |||
| parameter.ranges.def = 4.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 128.0f; | |||
| break; | |||
| case paramOrbitSpeedY: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Orbit Speed Y"; | |||
| parameter.symbol = "speedy"; | |||
| parameter.ranges.def = 4.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 128.0f; | |||
| break; | |||
| case paramSubOrbitSize: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "SubOrbit Size"; | |||
| parameter.symbol = "subsize"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSubOrbitSpeed: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "SubOrbit Speed"; | |||
| parameter.symbol = "subspeed"; | |||
| parameter.ranges.def = 32.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 128.0f; | |||
| break; | |||
| case paramSubOrbitSmooth: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "SubOrbit Wave"; | |||
| parameter.symbol = "subwave"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitWaveX: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Orbit Wave X"; | |||
| parameter.symbol = "wavex"; | |||
| parameter.ranges.def = 3.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| case paramOrbitWaveY: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Orbit Wave Y"; | |||
| parameter.symbol = "wavey"; | |||
| parameter.ranges.def = 3.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| case paramOrbitPhaseX: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Orbit Phase X"; | |||
| parameter.symbol = "phasex"; | |||
| parameter.ranges.def = 1.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| case paramOrbitPhaseY: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Orbit Phase Y"; | |||
| parameter.symbol = "phasey"; | |||
| parameter.ranges.def = 1.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| case paramOrbitOutX: | |||
| parameter.hints = kParameterIsOutput; | |||
| parameter.name = "Orbit X"; | |||
| parameter.symbol = "orx"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitOutY: | |||
| parameter.hints = kParameterIsOutput; | |||
| parameter.name = "Orbit Y"; | |||
| parameter.symbol = "ory"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSubOrbitOutX: | |||
| parameter.hints = kParameterIsOutput; | |||
| parameter.name = "SubOrbit X"; | |||
| parameter.symbol = "sorx"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSubOrbitOutY: | |||
| parameter.hints = kParameterIsOutput; | |||
| parameter.name = "SubOrbit Y"; | |||
| parameter.symbol = "sory"; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| } | |||
| } | |||
| void VectorJuicePlugin::initProgramName(uint32_t index, String& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float VectorJuicePlugin::getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramX: | |||
| return x; | |||
| case paramY: | |||
| return y; | |||
| case paramOrbitSizeX: | |||
| return orbitSizeX; | |||
| case paramOrbitSizeY: | |||
| return orbitSizeY; | |||
| case paramOrbitSpeedX: | |||
| return orbitSpeedX; | |||
| case paramOrbitSpeedY: | |||
| return orbitSpeedY; | |||
| case paramSubOrbitSize: | |||
| return subOrbitSize; | |||
| case paramSubOrbitSpeed: | |||
| return subOrbitSpeed; | |||
| case paramSubOrbitSmooth: | |||
| return subOrbitSmooth; | |||
| case paramOrbitWaveX: | |||
| return orbitWaveX; | |||
| case paramOrbitWaveY: | |||
| return orbitWaveY; | |||
| case paramOrbitPhaseX: | |||
| return orbitPhaseY; | |||
| case paramOrbitPhaseY: | |||
| return orbitPhaseY; | |||
| case paramOrbitOutX: | |||
| return orbitX; | |||
| case paramOrbitOutY: | |||
| return orbitY; | |||
| case paramSubOrbitOutX: | |||
| return subOrbitX; | |||
| case paramSubOrbitOutY: | |||
| return subOrbitY; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void VectorJuicePlugin::setParameterValue(uint32_t index, float value) | |||
| { | |||
| bool resetPhase = false; | |||
| switch (index) | |||
| { | |||
| case paramX: | |||
| x = value; | |||
| break; | |||
| case paramY: | |||
| y = value; | |||
| break; | |||
| case paramOrbitSizeX: | |||
| orbitSizeX = value; | |||
| break; | |||
| case paramOrbitSizeY: | |||
| orbitSizeY = value; | |||
| break; | |||
| case paramOrbitSpeedX: | |||
| orbitSpeedX = value; | |||
| resetPhase = true; | |||
| break; | |||
| case paramOrbitSpeedY: | |||
| orbitSpeedY = value; | |||
| resetPhase = true; | |||
| break; | |||
| case paramSubOrbitSize: | |||
| subOrbitSize = value; | |||
| break; | |||
| case paramSubOrbitSpeed: | |||
| subOrbitSpeed = value; | |||
| resetPhase = true; | |||
| break; | |||
| case paramSubOrbitSmooth: | |||
| subOrbitSmooth = value; | |||
| break; | |||
| case paramOrbitWaveX: | |||
| orbitWaveX = value; | |||
| break; | |||
| case paramOrbitWaveY: | |||
| orbitWaveY = value; | |||
| break; | |||
| case paramOrbitPhaseX: | |||
| orbitPhaseX = value; | |||
| resetPhase = true; | |||
| break; | |||
| case paramOrbitPhaseY: | |||
| orbitPhaseY = value; | |||
| resetPhase = true; | |||
| break; | |||
| } | |||
| if (resetPhase) | |||
| { | |||
| sinePosX = 0; | |||
| sinePosY = 0; | |||
| sinePos = 0; | |||
| } | |||
| } | |||
| void VectorJuicePlugin::loadProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default parameter values */ | |||
| x = 0.5f; | |||
| y = 0.5f; | |||
| orbitSizeX = 0.5f; | |||
| orbitSizeY = 0.5f; | |||
| orbitSpeedX = 4.0f; | |||
| orbitSpeedY = 4.0f; | |||
| subOrbitSize = 0.5f; | |||
| subOrbitSpeed = 32.0f; | |||
| subOrbitSmooth = 0.5f; | |||
| orbitWaveX = 3.0f; | |||
| orbitWaveY = 3.0f; | |||
| orbitPhaseX = 1.0f; | |||
| orbitPhaseY = 1.0f; | |||
| /* reset filter values */ | |||
| activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void VectorJuicePlugin::activate() | |||
| { | |||
| /* Default variable values */ | |||
| orbitX=orbitY=orbitTX=orbitTY=0.5; | |||
| subOrbitX=subOrbitY=subOrbitTX=subOrbitTY=0; | |||
| interpolationDivider=200; | |||
| bar=tickX=tickY=percentageX=percentageY=tickOffsetX=0; | |||
| tickOffsetY=sinePosX=sinePosY=tick=percentage=tickOffset=sinePos=0; | |||
| waveBlend=0; | |||
| //parameter smoothing | |||
| for (int i=0; i<2; i++) { | |||
| sA[i] = 0.99f; | |||
| sB[i] = 1.f - sA[i]; | |||
| sZ[i] = 0; | |||
| } | |||
| } | |||
| void VectorJuicePlugin::run(const float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| float out1, out2, tX, tY; | |||
| for (uint32_t i=0; i<frames; i++) { | |||
| //1.41421 -> 1 | |||
| //<0 = 0 | |||
| animate(); | |||
| tX = subOrbitX; | |||
| tY = subOrbitY; | |||
| out1 = inputs[0][i]*tN(1-std::sqrt((tX*tX)+(tY*tY))); | |||
| out2 = inputs[1][i]*tN(1-std::sqrt((tX*tX)+(tY*tY))); | |||
| out1 += inputs[2][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+(tY*tY))); | |||
| out2 += inputs[3][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+(tY*tY))); | |||
| out1 += inputs[4][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+((1-tY)*(1-tY)))); | |||
| out2 += inputs[5][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+((1-tY)*(1-tY)))); | |||
| out1 += inputs[6][i]*tN(1-std::sqrt((tX*tX)+((1-tY)*(1-tY)))); | |||
| out2 += inputs[7][i]*tN(1-std::sqrt((tX*tX)+((1-tY)*(1-tY)))); | |||
| outputs[0][i] = out1; | |||
| outputs[1][i] = out2; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new VectorJuicePlugin(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,236 +0,0 @@ | |||
| /* | |||
| * Vector Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef VECTORJUICEPLUGIN_HPP_INCLUDED | |||
| #define VECTORJUICEPLUGIN_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class VectorJuicePlugin : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramX = 0, | |||
| paramY, | |||
| paramOrbitSizeX, | |||
| paramOrbitSizeY, | |||
| paramOrbitSpeedX, | |||
| paramOrbitSpeedY, | |||
| paramSubOrbitSize, | |||
| paramSubOrbitSpeed, | |||
| paramSubOrbitSmooth, | |||
| paramOrbitWaveX, | |||
| paramOrbitWaveY, | |||
| paramOrbitPhaseX, | |||
| paramOrbitPhaseY, | |||
| paramOrbitOutX, | |||
| paramOrbitOutY, | |||
| paramSubOrbitOutX, | |||
| paramSubOrbitOutY, | |||
| paramCount | |||
| }; | |||
| float smoothParameter(float in, int axis) { | |||
| sZ[axis] = (in * sB[axis]) + (sZ[axis] * sA[axis]); | |||
| return sZ[axis]; | |||
| } | |||
| float getSinePhase(float x) { | |||
| return (-std::sin(x)); | |||
| } | |||
| float getSawPhase(float x) { | |||
| return (-(2/M_PI *std::atan(1/std::tan(x/2)))); | |||
| } | |||
| float getRevSawPhase(float x) { | |||
| return ((2/M_PI *std::atan(1/std::tan(x/2)))); | |||
| } | |||
| float getSquarePhase(float x) { | |||
| return (std::round((std::sin(x)+1)/2)-0.5)*2; | |||
| } | |||
| //saw, sqr, sin, revSaw | |||
| float getBlendedPhase(float x, float wave) | |||
| { | |||
| //wave = 2; | |||
| if (wave>=1 && wave<2) { | |||
| /* saw vs sqr */ | |||
| waveBlend = wave-1; | |||
| return (getSawPhase(x)*(1-waveBlend) + getSquarePhase(x)*waveBlend); | |||
| } else if (wave>=2 && wave<3) { | |||
| /* sqr vs sin */ | |||
| waveBlend = wave-2; | |||
| return (getSquarePhase(x)*(1-waveBlend) + getSinePhase(x)*waveBlend); | |||
| } else if (wave>=3 && wave<=4) { | |||
| /* sin vs revSaw */ | |||
| waveBlend = wave-3; | |||
| return (getSinePhase(x)*(1-waveBlend) + getRevSawPhase(x)*waveBlend); | |||
| } else { | |||
| return 0.0f; | |||
| } | |||
| } | |||
| float tN(float x) | |||
| { | |||
| if (x>0) return x; | |||
| else return 0; | |||
| } | |||
| void animate() | |||
| { | |||
| //sync orbit with frame, bpm | |||
| const TimePosition& time(getTimePosition()); | |||
| bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(getSampleRate())); | |||
| int multiplier = 16;//2000*4; | |||
| tickX = bar/(std::round(orbitSpeedX))*multiplier; | |||
| tickY = bar/(std::round(orbitSpeedY))*multiplier; | |||
| tick = bar/(std::round(subOrbitSpeed))*multiplier; | |||
| if (time.playing) | |||
| { | |||
| /* if rolling then sync to timepos */ | |||
| tickOffsetX = time.frame-std::floor(time.frame/tickX)*tickX; | |||
| tickOffsetY = time.frame-std::floor(time.frame/tickY)*tickY; | |||
| tickOffset = time.frame-std::floor(time.frame/tick)*tick; | |||
| percentageX = tickOffsetX/tickX; | |||
| percentageY = tickOffsetY/tickY; | |||
| percentage = tickOffset/tick; | |||
| sinePosX = (M_PI*2)*percentageX; | |||
| sinePosY = (M_PI*2)*percentageY; | |||
| sinePos = (M_PI*2)*percentage; | |||
| } else { | |||
| /* else just keep on wobblin' */ | |||
| sinePosX += (2*M_PI)/(tickX); | |||
| sinePosY += (2*M_PI)/(tickY); | |||
| sinePos += (M_PI)/(tick); | |||
| if (sinePosX>2*M_PI) { | |||
| sinePosX = 0; | |||
| } | |||
| if (sinePosY>2*M_PI) { | |||
| sinePosY = 0; | |||
| } | |||
| if (sinePos>2*M_PI) { | |||
| sinePos = 0; | |||
| } | |||
| } | |||
| //0..1 | |||
| //0..3 | |||
| //0, 1, 2, 3 | |||
| //* 0.25 | |||
| //0, 0.25, 0.5, 0.75 | |||
| float tempPhaseX = std::round(orbitPhaseX)*0.25-0.25; | |||
| float tempPhaseY = std::round(orbitPhaseY)*0.25-0.25; | |||
| orbitX = x+getBlendedPhase(sinePosX + tempPhaseX*(2*M_PI), std::round(orbitWaveX))*(orbitSizeX/2); | |||
| orbitY = y+getBlendedPhase(sinePosY+M_PI/2 + tempPhaseY*(2*M_PI), std::round(orbitWaveY))*(orbitSizeY/2); | |||
| subOrbitX = smoothParameter(orbitX+getBlendedPhase(sinePos, 3)*(subOrbitSize/3), 0); | |||
| subOrbitY = smoothParameter(orbitY+getBlendedPhase(sinePos+M_PI/2, 3)*(subOrbitSize/3), 1); | |||
| if (orbitX<0) orbitX=0; | |||
| if (orbitX>1) orbitX=1; | |||
| if (orbitY<0) orbitY=0; | |||
| if (orbitY>1) orbitY=1; | |||
| if (subOrbitX<0) subOrbitX=0; | |||
| if (subOrbitX>1) subOrbitX=1; | |||
| if (subOrbitY<0) subOrbitY=0; | |||
| if (subOrbitY>1) subOrbitY=1; | |||
| } | |||
| VectorJuicePlugin(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "VectorJuice"; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "Andre Sklenar"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('V', 'e', 'c', 'J'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t index, Parameter& parameter) override; | |||
| void initProgramName(uint32_t index, String& programName) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t index) const override; | |||
| void setParameterValue(uint32_t index, float value) override; | |||
| void loadProgram(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void activate() override; | |||
| void run(const float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float x, y; | |||
| float orbitX, orbitY; | |||
| float orbitTX, orbitTY; //targetX and targetY for interpolation | |||
| float subOrbitX, subOrbitY; | |||
| float subOrbitTX, subOrbitTY; | |||
| float subOrbitSpeed, subOrbitSize, orbitSpeedX, orbitSpeedY; | |||
| float orbitSizeX, orbitSizeY; | |||
| float interpolationDivider; | |||
| float bar, tickX, tickY, percentageX, percentageY, tickOffsetX, tickOffsetY; | |||
| float sinePosX, sinePosY, tick, percentage, tickOffset, sinePos; | |||
| float orbitWaveX, orbitWaveY, subOrbitSmooth, waveBlend; | |||
| float orbitPhaseX, orbitPhaseY; | |||
| //parameter smoothing, for subOrbitX and subOrbitY | |||
| float sA[2], sB[2], sZ[2]; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // VECTORJUICE_HPP_INCLUDED | |||
| @@ -1,461 +0,0 @@ | |||
| /* | |||
| * Vector Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "VectorJuicePlugin.hpp" | |||
| #include "VectorJuiceUI.hpp" | |||
| using DGL_NAMESPACE::Point; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| VectorJuiceUI::VectorJuiceUI() | |||
| : UI(), | |||
| fAboutWindow(this) | |||
| { | |||
| setSize(VectorJuiceArtwork::backgroundWidth, VectorJuiceArtwork::backgroundHeight); | |||
| // xy params | |||
| paramX = paramY = 0.5f; | |||
| // orbit params | |||
| orbitX = orbitY = subOrbitX = subOrbitY = 0.5f; | |||
| // set the XY canvas area | |||
| fDragging = false; | |||
| fDragValid = false; | |||
| fLastX = fLastY = 0; | |||
| fCanvasArea.setPos(22+12, 49+12); | |||
| fCanvasArea.setSize(368-24, 368-24); | |||
| // background | |||
| fImgBackground = Image(VectorJuiceArtwork::backgroundData, VectorJuiceArtwork::backgroundWidth, VectorJuiceArtwork::backgroundHeight, GL_BGR); | |||
| //roundlet | |||
| fImgRoundlet = Image(VectorJuiceArtwork::roundletData, VectorJuiceArtwork::roundletWidth, VectorJuiceArtwork::roundletHeight); | |||
| //orbit | |||
| fImgOrbit = Image(VectorJuiceArtwork::orbitData, VectorJuiceArtwork::orbitWidth, VectorJuiceArtwork::orbitHeight); | |||
| //subOrbit | |||
| fImgSubOrbit = Image(VectorJuiceArtwork::subOrbitData, VectorJuiceArtwork::subOrbitWidth, VectorJuiceArtwork::subOrbitHeight); | |||
| // about | |||
| Image aboutImage(VectorJuiceArtwork::aboutData, VectorJuiceArtwork::aboutWidth, VectorJuiceArtwork::aboutHeight, GL_BGR); | |||
| fAboutWindow.setImage(aboutImage); | |||
| // about button | |||
| Image aboutImageNormal(VectorJuiceArtwork::aboutButtonNormalData, VectorJuiceArtwork::aboutButtonNormalWidth, VectorJuiceArtwork::aboutButtonNormalHeight); | |||
| Image aboutImageHover(VectorJuiceArtwork::aboutButtonHoverData, VectorJuiceArtwork::aboutButtonHoverWidth, VectorJuiceArtwork::aboutButtonHoverHeight); | |||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | |||
| fButtonAbout->setAbsolutePos(599, 17); | |||
| fButtonAbout->setCallback(this); | |||
| // knobs | |||
| Image knobImage(VectorJuiceArtwork::knobData, VectorJuiceArtwork::knobWidth, VectorJuiceArtwork::knobHeight); | |||
| // knob KnobOrbitSizeX | |||
| fKnobOrbitSizeX = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobOrbitSizeX->setId(VectorJuicePlugin::paramOrbitSizeX); | |||
| fKnobOrbitSizeX->setAbsolutePos(423, 73); | |||
| fKnobOrbitSizeX->setRotationAngle(270); | |||
| fKnobOrbitSizeX->setRange(0.0f, 1.0f); | |||
| fKnobOrbitSizeX->setDefault(0.5f); | |||
| fKnobOrbitSizeX->setCallback(this); | |||
| // knob KnobOrbitSizeY | |||
| fKnobOrbitSizeY = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobOrbitSizeY->setId(VectorJuicePlugin::paramOrbitSizeY); | |||
| fKnobOrbitSizeY->setAbsolutePos(516, 73); | |||
| fKnobOrbitSizeY->setRotationAngle(270); | |||
| fKnobOrbitSizeY->setRange(0.0f, 1.0f); | |||
| fKnobOrbitSizeY->setDefault(0.5f); | |||
| fKnobOrbitSizeY->setCallback(this); | |||
| // knob KnobOrbitSpeedX | |||
| fKnobOrbitSpeedX = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobOrbitSpeedX->setId(VectorJuicePlugin::paramOrbitSpeedX); | |||
| fKnobOrbitSpeedX->setAbsolutePos(423, 185); | |||
| fKnobOrbitSpeedX->setRotationAngle(270); | |||
| fKnobOrbitSpeedX->setStep(1.0f); | |||
| fKnobOrbitSpeedX->setRange(1.0f, 128.0f); | |||
| fKnobOrbitSpeedX->setDefault(4.0f); | |||
| fKnobOrbitSpeedX->setCallback(this); | |||
| // knob KnobOrbitSpeedY | |||
| fKnobOrbitSpeedY = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobOrbitSpeedY->setId(VectorJuicePlugin::paramOrbitSpeedY); | |||
| fKnobOrbitSpeedY->setAbsolutePos(516, 185); | |||
| fKnobOrbitSpeedY->setRotationAngle(270); | |||
| fKnobOrbitSpeedY->setStep(1.0f); | |||
| fKnobOrbitSpeedY->setRange(1.0f, 128.0f); | |||
| fKnobOrbitSpeedY->setDefault(4.0f); | |||
| fKnobOrbitSpeedY->setCallback(this); | |||
| // knob KnobSubOrbitSize | |||
| fKnobSubOrbitSize = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobSubOrbitSize->setId(VectorJuicePlugin::paramSubOrbitSize); | |||
| fKnobSubOrbitSize->setAbsolutePos(620, 73); | |||
| fKnobSubOrbitSize->setRange(0.0f, 1.0f); | |||
| fKnobSubOrbitSize->setRotationAngle(270); | |||
| fKnobSubOrbitSize->setDefault(0.5f); | |||
| fKnobSubOrbitSize->setCallback(this); | |||
| // knob KnobSubOrbitSpeed | |||
| fKnobSubOrbitSpeed = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobSubOrbitSpeed->setId(VectorJuicePlugin::paramSubOrbitSpeed); | |||
| fKnobSubOrbitSpeed->setAbsolutePos(620, 185); | |||
| fKnobSubOrbitSpeed->setRotationAngle(270); | |||
| fKnobSubOrbitSpeed->setStep(1.0f); | |||
| fKnobSubOrbitSpeed->setRange(1.0f, 128.0f); | |||
| fKnobSubOrbitSpeed->setDefault(32.0f); | |||
| fKnobSubOrbitSpeed->setCallback(this); | |||
| // knob KnobSubOrbitSmooth | |||
| fKnobSubOrbitSmooth = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobSubOrbitSmooth->setId(VectorJuicePlugin::paramSubOrbitSmooth); | |||
| fKnobSubOrbitSmooth->setAbsolutePos(620, 297); | |||
| fKnobSubOrbitSmooth->setRotationAngle(270); | |||
| fKnobSubOrbitSmooth->setRange(0.0f, 1.0f); | |||
| fKnobSubOrbitSmooth->setDefault(0.5f); | |||
| fKnobSubOrbitSmooth->setCallback(this); | |||
| // sliders | |||
| Image sliderImage(VectorJuiceArtwork::sliderData, VectorJuiceArtwork::sliderWidth, VectorJuiceArtwork::sliderHeight); | |||
| Point<int> sliderPosStart(410, 284); | |||
| Point<int> sliderPosEnd(410+48, 284); | |||
| // slider OrbitWaveX | |||
| fSliderOrbitWaveX = new ImageSlider(this, sliderImage); | |||
| fSliderOrbitWaveX->setId(VectorJuicePlugin::paramOrbitWaveX); | |||
| fSliderOrbitWaveX->setStartPos(sliderPosStart); | |||
| fSliderOrbitWaveX->setEndPos(sliderPosEnd); | |||
| fSliderOrbitWaveX->setRange(1.0f, 4.0f); | |||
| fSliderOrbitWaveX->setStep(1.0f); | |||
| fSliderOrbitWaveX->setCallback(this); | |||
| // slider OrbitWaveY | |||
| sliderPosStart.setX(503); | |||
| sliderPosEnd.setX(503+48); | |||
| fSliderOrbitWaveY = new ImageSlider(this, sliderImage); | |||
| fSliderOrbitWaveY->setId(VectorJuicePlugin::paramOrbitWaveY); | |||
| fSliderOrbitWaveY->setStartPos(sliderPosStart); | |||
| fSliderOrbitWaveY->setEndPos(sliderPosEnd); | |||
| fSliderOrbitWaveY->setRange(1.0f, 4.0f); | |||
| fSliderOrbitWaveY->setStep(1.0f); | |||
| fSliderOrbitWaveY->setCallback(this); | |||
| // slider OrbitPhaseX | |||
| sliderPosStart.setX(410); | |||
| sliderPosStart.setY(345); | |||
| sliderPosEnd.setX(410+48); | |||
| sliderPosEnd.setY(345); | |||
| fSliderOrbitPhaseX = new ImageSlider(this, sliderImage); | |||
| fSliderOrbitPhaseX->setId(VectorJuicePlugin::paramOrbitPhaseX); | |||
| fSliderOrbitPhaseX->setStartPos(sliderPosStart); | |||
| fSliderOrbitPhaseX->setEndPos(sliderPosEnd); | |||
| fSliderOrbitPhaseX->setRange(1.0f, 4.0f); | |||
| fSliderOrbitPhaseX->setStep(1.0f); | |||
| fSliderOrbitPhaseX->setCallback(this); | |||
| // slider OrbitPhaseY | |||
| sliderPosStart.setX(503); | |||
| sliderPosEnd.setX(503+48); | |||
| fSliderOrbitPhaseY = new ImageSlider(this, sliderImage); | |||
| fSliderOrbitPhaseY->setId(VectorJuicePlugin::paramOrbitPhaseY); | |||
| fSliderOrbitPhaseY->setStartPos(sliderPosStart); | |||
| fSliderOrbitPhaseY->setEndPos(sliderPosEnd); | |||
| fSliderOrbitPhaseY->setRange(1.0f, 4.0f); | |||
| fSliderOrbitPhaseY->setStep(1.0f); | |||
| fSliderOrbitPhaseY->setCallback(this); | |||
| // set default values | |||
| programLoaded(0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void VectorJuiceUI::parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case VectorJuicePlugin::paramX: | |||
| if (paramX != value) | |||
| { | |||
| paramX = value; | |||
| fDragValid = false; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case VectorJuicePlugin::paramY: | |||
| if (paramY != value) | |||
| { | |||
| paramY = value; | |||
| fDragValid = false; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitSizeX: | |||
| fKnobOrbitSizeX->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitSizeY: | |||
| fKnobOrbitSizeY->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitSpeedX: | |||
| fKnobOrbitSpeedX->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitSpeedY: | |||
| fKnobOrbitSpeedY->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramSubOrbitSize: | |||
| fKnobSubOrbitSize->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramSubOrbitSpeed: | |||
| fKnobSubOrbitSpeed->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramSubOrbitSmooth: | |||
| fKnobSubOrbitSmooth->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitWaveX: | |||
| fSliderOrbitWaveX->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitWaveY: | |||
| fSliderOrbitWaveY->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitPhaseX: | |||
| fSliderOrbitPhaseX->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitPhaseY: | |||
| fSliderOrbitPhaseY->setValue(value); | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitOutX: | |||
| if (orbitX != value) | |||
| { | |||
| orbitX = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case VectorJuicePlugin::paramOrbitOutY: | |||
| if (orbitY != value) | |||
| { | |||
| orbitY = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case VectorJuicePlugin::paramSubOrbitOutX: | |||
| if (subOrbitX != value) | |||
| { | |||
| subOrbitX = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case VectorJuicePlugin::paramSubOrbitOutY: | |||
| if (subOrbitY != value) | |||
| { | |||
| subOrbitY = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| void VectorJuiceUI::programLoaded(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| paramX = paramY = 0.5f; | |||
| fKnobOrbitSizeX->setValue(0.5f); | |||
| fKnobOrbitSizeY->setValue(0.5f); | |||
| fKnobOrbitSpeedX->setValue(4.0f); | |||
| fKnobOrbitSpeedY->setValue(4.0f); | |||
| fKnobSubOrbitSize->setValue(0.5f); | |||
| fKnobSubOrbitSpeed->setValue(32.0f); | |||
| fKnobSubOrbitSmooth->setValue(0.5f); | |||
| fSliderOrbitWaveX->setValue(3.0f); | |||
| fSliderOrbitWaveY->setValue(3.0f); | |||
| fSliderOrbitPhaseX->setValue(1.0f); | |||
| fSliderOrbitPhaseY->setValue(1.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void VectorJuiceUI::imageButtonClicked(ImageButton* button, int) | |||
| { | |||
| if (button != fButtonAbout) | |||
| return; | |||
| fAboutWindow.exec(); | |||
| } | |||
| void VectorJuiceUI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), true); | |||
| } | |||
| void VectorJuiceUI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), false); | |||
| } | |||
| void VectorJuiceUI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| setParameterValue(knob->getId(), value); | |||
| } | |||
| void VectorJuiceUI::imageSliderDragStarted(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), true); | |||
| } | |||
| void VectorJuiceUI::imageSliderDragFinished(ImageSlider* slider) | |||
| { | |||
| editParameter(slider->getId(), false); | |||
| } | |||
| void VectorJuiceUI::imageSliderValueChanged(ImageSlider* slider, float value) | |||
| { | |||
| setParameterValue(slider->getId(), value); | |||
| } | |||
| void VectorJuiceUI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| // get x, y mapped to XY area | |||
| int x = fCanvasArea.getX() + paramX*fCanvasArea.getWidth() - fImgRoundlet.getWidth()/2; | |||
| int y = fCanvasArea.getY() + paramY*fCanvasArea.getHeight() - fImgRoundlet.getHeight()/2; | |||
| int nOrbitX = fCanvasArea.getX()+((orbitX)*fCanvasArea.getWidth())-15; | |||
| int nOrbitY = fCanvasArea.getY()+((orbitY)*fCanvasArea.getWidth())-15; | |||
| int nSubOrbitX = fCanvasArea.getX()+(subOrbitX*fCanvasArea.getWidth())-15; | |||
| int nSubOrbitY = fCanvasArea.getY()+(subOrbitY*fCanvasArea.getWidth())-14; | |||
| //draw lines, just for fun | |||
| glEnable(GL_BLEND); | |||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
| glColor4f(0.0f, 1.0f, 0.0f, 0.05f); | |||
| glLineWidth(4); | |||
| glBegin(GL_LINES); | |||
| glVertex2i(x+ fImgRoundlet.getWidth()/2, y+ fImgRoundlet.getHeight()/2); | |||
| glVertex2i(nOrbitX+15, nOrbitY+15); | |||
| glEnd(); | |||
| glBegin(GL_LINES); | |||
| glVertex2i(nOrbitX+15, nOrbitY+15); | |||
| glVertex2i(nSubOrbitX+15, nSubOrbitY+14); | |||
| glEnd(); | |||
| // reset color | |||
| glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |||
| // draw roundlet and orbits | |||
| fImgRoundlet.drawAt(x, y); | |||
| fImgOrbit.drawAt(nOrbitX, nOrbitY); | |||
| fImgSubOrbit.drawAt(nSubOrbitX, nSubOrbitY); | |||
| } | |||
| bool VectorJuiceUI::onMouse(const MouseEvent& ev) | |||
| { | |||
| if (ev.button != 1) | |||
| return false; | |||
| if (ev.press) | |||
| { | |||
| if (! fCanvasArea.contains(ev.pos)) | |||
| return false; | |||
| fDragging = true; | |||
| fDragValid = true; | |||
| fLastX = ev.pos.getX(); | |||
| fLastY = ev.pos.getY(); | |||
| return true; | |||
| } | |||
| else if (fDragging) | |||
| { | |||
| fDragging = false; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| bool VectorJuiceUI::onMotion(const MotionEvent& ev) | |||
| { | |||
| if (! fDragging) | |||
| return false; | |||
| const int x = ev.pos.getX(); | |||
| const int y = ev.pos.getY(); | |||
| if (! fDragValid) | |||
| { | |||
| fDragValid = true; | |||
| fLastX = x; | |||
| fLastY = y; | |||
| } | |||
| const int movedX = fLastX - x; | |||
| const int movedY = fLastY - y; | |||
| fLastX = x; | |||
| fLastY = y; | |||
| float newX = paramX; | |||
| float newY = paramY; | |||
| newX -= float(movedX)/fCanvasArea.getWidth(); | |||
| newY -= float(movedY)/fCanvasArea.getHeight(); | |||
| if (newX < 0.0f) | |||
| newX = 0.0f; | |||
| else if (newX > 1.0f) | |||
| newX = 1.0f; | |||
| if (newY < 0.0f) | |||
| newY = 0.0f; | |||
| else if (newY > 1.0f) | |||
| newY = 1.0f; | |||
| if (newX != paramX) | |||
| { | |||
| paramX = newX; | |||
| setParameterValue(VectorJuicePlugin::paramX, paramX); | |||
| repaint(); | |||
| } | |||
| if (newY != paramY) | |||
| { | |||
| paramY = newY; | |||
| setParameterValue(VectorJuicePlugin::paramY, paramY); | |||
| repaint(); | |||
| } | |||
| return true; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new VectorJuiceUI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,99 +0,0 @@ | |||
| /* | |||
| * Vector Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef VECTORJUICEUI_HPP_INCLUDED | |||
| #define VECTORJUICEUI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageWidgets.hpp" | |||
| #include "VectorJuiceArtwork.hpp" | |||
| using DGL_NAMESPACE::Image; | |||
| using DGL_NAMESPACE::ImageAboutWindow; | |||
| using DGL_NAMESPACE::ImageButton; | |||
| using DGL_NAMESPACE::ImageKnob; | |||
| using DGL_NAMESPACE::ImageSlider; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class VectorJuiceUI : public UI, | |||
| public ImageButton::Callback, | |||
| public ImageKnob::Callback, | |||
| public ImageSlider::Callback | |||
| { | |||
| public: | |||
| VectorJuiceUI(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t index, float value) override; | |||
| void programLoaded(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageButtonClicked(ImageButton* button, int) override; | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void imageSliderDragStarted(ImageSlider* slider) override; | |||
| void imageSliderDragFinished(ImageSlider* slider) override; | |||
| void imageSliderValueChanged(ImageSlider* slider, float value) override; | |||
| void onDisplay() override; | |||
| bool onMouse(const MouseEvent&) override; | |||
| bool onMotion(const MotionEvent&) override; | |||
| private: | |||
| float paramX, paramY; | |||
| Image fImgBackground; | |||
| Image fImgRoundlet; | |||
| Image fImgOrbit; | |||
| Image fImgSubOrbit; | |||
| ImageAboutWindow fAboutWindow; | |||
| ScopedPointer<ImageButton> fButtonAbout; | |||
| //knobs | |||
| ScopedPointer<ImageKnob> fKnobOrbitSpeedX, fKnobOrbitSpeedY, fKnobOrbitSizeX, fKnobOrbitSizeY; | |||
| ScopedPointer<ImageKnob> fKnobSubOrbitSpeed, fKnobSubOrbitSize, fKnobSubOrbitSmooth; | |||
| //sliders | |||
| ScopedPointer<ImageSlider> fSliderOrbitWaveX, fSliderOrbitWaveY; | |||
| ScopedPointer<ImageSlider> fSliderOrbitPhaseX, fSliderOrbitPhaseY; | |||
| // needed for XY canvas handling | |||
| bool fDragging; | |||
| bool fDragValid; | |||
| int fLastX; | |||
| int fLastY; | |||
| DGL_NAMESPACE::Rectangle<int> fCanvasArea; | |||
| float orbitX, orbitY, subOrbitX, subOrbitY; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // VECTORJUICEUI_HPP_INCLUDED | |||
| @@ -1,87 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // config fix | |||
| #include "distrho-wobblejuice/DistrhoPluginInfo.h" | |||
| #if DISTRHO_PLUGIN_HAS_UI && ! defined(HAVE_DGL) | |||
| # undef DISTRHO_PLUGIN_HAS_UI | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-wobblejuice/WobbleJuiceArtwork.cpp" | |||
| #include "distrho-wobblejuice/WobbleJuicePlugin.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "distrho-wobblejuice/WobbleJuiceUI.cpp" | |||
| #endif | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #ifdef HAVE_DGL | |||
| #include "DistrhoUIMain.cpp" | |||
| #endif | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor wobblejuiceDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DYNAMICS, | |||
| #ifdef HAVE_DGL | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #else | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_USES_TIME), | |||
| #endif | |||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ WobbleJuicePlugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "wobblejuice", | |||
| /* maker */ "Andre Sklenar", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_wobblejuice(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_distrho_wobblejuice() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&wobblejuiceDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,36 +0,0 @@ | |||
| /* | |||
| * Wobble Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_NAME "WobbleJuice" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | |||
| #define DISTRHO_PLUGIN_URI "urn:distrho:WobbleJuice" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -1,35 +0,0 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_WOBBLEJUICEARTWORK_HPP | |||
| #define BINARY_WOBBLEJUICEARTWORK_HPP | |||
| namespace WobbleJuiceArtwork | |||
| { | |||
| extern const char* aboutData; | |||
| const unsigned int aboutDataSize = 180000; | |||
| const unsigned int aboutWidth = 300; | |||
| const unsigned int aboutHeight = 200; | |||
| extern const char* aboutButtonHoverData; | |||
| const unsigned int aboutButtonHoverDataSize = 5888; | |||
| const unsigned int aboutButtonHoverWidth = 92; | |||
| const unsigned int aboutButtonHoverHeight = 16; | |||
| extern const char* aboutButtonNormalData; | |||
| const unsigned int aboutButtonNormalDataSize = 5888; | |||
| const unsigned int aboutButtonNormalWidth = 92; | |||
| const unsigned int aboutButtonNormalHeight = 16; | |||
| extern const char* backgroundData; | |||
| const unsigned int backgroundDataSize = 450000; | |||
| const unsigned int backgroundWidth = 500; | |||
| const unsigned int backgroundHeight = 300; | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 12544; | |||
| const unsigned int knobWidth = 56; | |||
| const unsigned int knobHeight = 56; | |||
| } | |||
| #endif // BINARY_WOBBLEJUICEARTWORK_HPP | |||
| @@ -1,243 +0,0 @@ | |||
| /* | |||
| * Wobble Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "WobbleJuicePlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| WobbleJuicePlugin::WobbleJuicePlugin() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| loadProgram(0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void WobbleJuicePlugin::initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramDivision: | |||
| parameter.hints = kParameterIsAutomable|kParameterIsInteger; | |||
| parameter.name = "Division"; | |||
| parameter.symbol = "div"; | |||
| parameter.unit = "x"; | |||
| parameter.ranges.def = 4.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 16.0f; | |||
| break; | |||
| case paramReso: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Resonance"; | |||
| parameter.symbol = "reso"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.1f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 0.2f; | |||
| break; | |||
| case paramRange: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Range"; | |||
| parameter.symbol = "rng"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 16000.0f; | |||
| parameter.ranges.min = 500.0f; | |||
| parameter.ranges.max = 16000.0f; | |||
| break; | |||
| case paramPhase: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Phase"; | |||
| parameter.symbol = "phs"; | |||
| parameter.unit = "Deg"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -1.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramWave: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Wave"; | |||
| parameter.symbol = "wav"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 2.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| case paramDrive: | |||
| parameter.hints = kParameterIsAutomable; | |||
| parameter.name = "Drive"; | |||
| parameter.symbol = "drv"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| } | |||
| } | |||
| void WobbleJuicePlugin::initProgramName(uint32_t index, String& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float WobbleJuicePlugin::getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramDivision: | |||
| return division; | |||
| case paramReso: | |||
| return reso; | |||
| case paramRange: | |||
| return range; | |||
| case paramPhase: | |||
| return phase; | |||
| case paramWave: | |||
| return wave; | |||
| case paramDrive: | |||
| return drive; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void WobbleJuicePlugin::setParameterValue(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramDivision: | |||
| division = value; | |||
| break; | |||
| case paramReso: | |||
| reso = value; | |||
| break; | |||
| case paramRange: | |||
| range = value; | |||
| break; | |||
| case paramPhase: | |||
| phase = value; | |||
| break; | |||
| case paramWave: | |||
| wave = value; | |||
| break; | |||
| case paramDrive: | |||
| drive = value; | |||
| break; | |||
| } | |||
| } | |||
| void WobbleJuicePlugin::loadProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default parameter values */ | |||
| division = 4.0f; | |||
| reso = 0.1f; | |||
| range = 16000.0f; | |||
| phase = 0.0f; | |||
| wave = 2.0f; | |||
| drive = 0.5f; | |||
| /* Default variable values */ | |||
| bar=tick=tickOffset=percentage=phaseOffset=currentPhaseL=0.0f; | |||
| currentPhaseR=posL=posR=cutoffL=cutoffR=0.0f; | |||
| waveType=2.0f; | |||
| /* reset filter values */ | |||
| activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void WobbleJuicePlugin::activate() | |||
| { | |||
| sinePos = 0.0; | |||
| } | |||
| void WobbleJuicePlugin::run(const float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| //fetch the timepos struct from host; | |||
| const TimePosition& time(getTimePosition()); | |||
| /* sample count for one bar */ | |||
| bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(getSampleRate())); //ONE, two, three, four | |||
| tick = bar/(std::round(division)); //size of one target wob | |||
| phaseOffset = phase*M_PI; //2pi = 1 whole cycle | |||
| /* if rolling then sync to timepos */ | |||
| if (time.playing) | |||
| { | |||
| tickOffset = time.frame-std::floor(time.frame/tick)*tick; //how much after last tick | |||
| if (tickOffset!=0) { | |||
| //TODO: why do we need this?? | |||
| percentage = tickOffset/tick; | |||
| } else { | |||
| percentage = 0; | |||
| } | |||
| sinePos = (M_PI*2)*percentage; | |||
| if (sinePos>2*M_PI) { | |||
| //TODO: can this ever happen?? | |||
| sinePos = 0; | |||
| } | |||
| } | |||
| /* else just keep on wobblin' */ | |||
| else | |||
| { | |||
| sinePos += (M_PI)/(tick/2000); //wtf, but works | |||
| if (sinePos>2*M_PI) { | |||
| sinePos = 0; | |||
| } | |||
| } | |||
| /* phase of 0..1 filter = 500..16k */ | |||
| currentPhaseL = getBlendedPhase(sinePos+phaseOffset, wave); | |||
| currentPhaseR = getBlendedPhase(sinePos-phaseOffset, wave); | |||
| /* logarithmic */ | |||
| cutoffL = std::exp((std::log(range)-std::log(500))*currentPhaseL+std::log(500)); | |||
| cutoffR = std::exp((std::log(range)-std::log(500))*currentPhaseR+std::log(500)); | |||
| //output filtered signal | |||
| filterL.recalc(cutoffL, reso*4, getSampleRate(), drive); | |||
| filterR.recalc(cutoffR, reso*4, getSampleRate(), drive); | |||
| filterL.process(frames, inputs[0], outputs[0]); | |||
| filterR.process(frames, inputs[1], outputs[1]); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new WobbleJuicePlugin(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,142 +0,0 @@ | |||
| /* | |||
| * Wobble Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef WOBBLEJUICEPLUGIN_HPP_INCLUDED | |||
| #define WOBBLEJUICEPLUGIN_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| #include "moogVCF.hxx" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class WobbleJuicePlugin : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramDivision = 0, | |||
| paramReso, | |||
| paramRange, | |||
| paramPhase, | |||
| paramWave, | |||
| paramDrive, | |||
| paramCount | |||
| }; | |||
| float getSinePhase(float x) { | |||
| return ((-std::cos(x)+1)/2); | |||
| } | |||
| float getSawPhase(float x) { | |||
| return (-((2/M_PI * std::atan(1/std::tan(x/2)))-1)/2); | |||
| } | |||
| float getRevSawPhase(float x) { | |||
| return (((2/M_PI * std::atan(1/std::tan(x/2)))+1)/2); | |||
| } | |||
| float getSquarePhase(float x) { | |||
| return (std::round((std::sin(x)+1)/2)); | |||
| } | |||
| //saw, sqr, sin, revSaw | |||
| float getBlendedPhase(float x, float wave) | |||
| { | |||
| //wave = 2; | |||
| if (wave>=1 && wave<2) { | |||
| /* saw vs sqr */ | |||
| waveBlend = wave-1; | |||
| return (getSawPhase(x)*(1-waveBlend) + getSquarePhase(x)*waveBlend); | |||
| } else if (wave>=2 && wave<3) { | |||
| /* sqr vs sin */ | |||
| waveBlend = wave-2; | |||
| return (getSquarePhase(x)*(1-waveBlend) + getSinePhase(x)*waveBlend); | |||
| } else if (wave>=3 && wave<=4) { | |||
| /* sin vs revSaw */ | |||
| waveBlend = wave-3; | |||
| return (getSinePhase(x)*(1-waveBlend) + getRevSawPhase(x)*waveBlend); | |||
| } else { | |||
| return 0.0f; | |||
| } | |||
| } | |||
| WobbleJuicePlugin(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* getLabel() const noexcept override | |||
| { | |||
| return "WobbleJuice"; | |||
| } | |||
| const char* getMaker() const noexcept override | |||
| { | |||
| return "Andre Sklenar"; | |||
| } | |||
| const char* getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| int64_t getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('W', 'b', 'l', 'J'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void initParameter(uint32_t index, Parameter& parameter) override; | |||
| void initProgramName(uint32_t index, String& programName) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float getParameterValue(uint32_t index) const override; | |||
| void setParameterValue(uint32_t index, float value) override; | |||
| void loadProgram(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void activate() override; | |||
| void run(const float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| MoogVCF filterL, filterR; | |||
| float division, reso, range, phase, wave, drive; //parameters | |||
| float bar, tick, tickOffset, percentage, phaseOffset, currentPhaseL, currentPhaseR, posL, posR, cutoffL, cutoffR; | |||
| double sinePos; | |||
| float waveType, waveBlend; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WobbleJuicePlugin) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // WOBBLEJUICE_HPP_INCLUDED | |||
| @@ -1,189 +0,0 @@ | |||
| /* | |||
| * Wobble Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "WobbleJuicePlugin.hpp" | |||
| #include "WobbleJuiceUI.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| WobbleJuiceUI::WobbleJuiceUI() | |||
| : UI(), | |||
| fAboutWindow(this) | |||
| { | |||
| setSize(WobbleJuiceArtwork::backgroundWidth, WobbleJuiceArtwork::backgroundHeight); | |||
| // background | |||
| fImgBackground = Image(WobbleJuiceArtwork::backgroundData, WobbleJuiceArtwork::backgroundWidth, WobbleJuiceArtwork::backgroundHeight, GL_BGR); | |||
| // about | |||
| Image aboutImage(WobbleJuiceArtwork::aboutData, WobbleJuiceArtwork::aboutWidth, WobbleJuiceArtwork::aboutHeight, GL_BGR); | |||
| fAboutWindow.setImage(aboutImage); | |||
| // knobs | |||
| Image knobImage(WobbleJuiceArtwork::knobData, WobbleJuiceArtwork::knobWidth, WobbleJuiceArtwork::knobHeight); | |||
| // knob Division | |||
| fKnobDivision = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobDivision->setId(WobbleJuicePlugin::paramDivision); | |||
| fKnobDivision->setAbsolutePos(222, 74); | |||
| fKnobDivision->setRotationAngle(270); | |||
| fKnobDivision->setRange(1.0f, 16.0f); | |||
| fKnobDivision->setDefault(4.0f); | |||
| fKnobDivision->setStep(1.0f); | |||
| fKnobDivision->setCallback(this); | |||
| // knob Resonance | |||
| fKnobResonance = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobResonance->setId(WobbleJuicePlugin::paramReso); | |||
| fKnobResonance->setAbsolutePos(222, 199); | |||
| fKnobResonance->setRotationAngle(270); | |||
| fKnobResonance->setRange(0.0f, 0.2f); | |||
| fKnobResonance->setDefault(0.1f); | |||
| fKnobResonance->setCallback(this); | |||
| // knob Range | |||
| fKnobRange = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobRange->setId(WobbleJuicePlugin::paramRange); | |||
| fKnobRange->setAbsolutePos(77, 199); | |||
| fKnobRange->setRotationAngle(270); | |||
| fKnobRange->setRange(500.0f, 16000.0f); | |||
| fKnobRange->setDefault(16000.0f); | |||
| fKnobRange->setCallback(this); | |||
| // knob Phase | |||
| fKnobPhase = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobPhase->setId(WobbleJuicePlugin::paramPhase); | |||
| fKnobPhase->setAbsolutePos(362, 74); | |||
| fKnobPhase->setRotationAngle(270); | |||
| fKnobPhase->setRange(-1.0f, 1.0f); | |||
| fKnobPhase->setDefault(0.0f); | |||
| fKnobPhase->setCallback(this); | |||
| // knob Wave | |||
| fKnobWave = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobWave->setId(WobbleJuicePlugin::paramWave); | |||
| fKnobWave->setAbsolutePos(77, 74); | |||
| fKnobWave->setRotationAngle(270); | |||
| fKnobWave->setRange(1.0f, 4.0f); | |||
| fKnobWave->setDefault(2.0f); | |||
| fKnobWave->setCallback(this); | |||
| // knob Drive | |||
| fKnobDrive = new ImageKnob(this, knobImage, ImageKnob::Vertical); | |||
| fKnobDrive->setId(WobbleJuicePlugin::paramDrive); | |||
| fKnobDrive->setAbsolutePos(362, 199); | |||
| fKnobDrive->setRotationAngle(270); | |||
| fKnobDrive->setRange(0.0f, 1.0f); | |||
| fKnobDrive->setDefault(0.5f); | |||
| fKnobDrive->setCallback(this); | |||
| // about button | |||
| Image aboutImageNormal(WobbleJuiceArtwork::aboutButtonNormalData, WobbleJuiceArtwork::aboutButtonNormalWidth, WobbleJuiceArtwork::aboutButtonNormalHeight); | |||
| Image aboutImageHover(WobbleJuiceArtwork::aboutButtonHoverData, WobbleJuiceArtwork::aboutButtonHoverWidth, WobbleJuiceArtwork::aboutButtonHoverHeight); | |||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | |||
| fButtonAbout->setAbsolutePos(390, 20); | |||
| fButtonAbout->setCallback(this); | |||
| // set default values | |||
| programLoaded(0); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void WobbleJuiceUI::parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case WobbleJuicePlugin::paramDivision: | |||
| fKnobDivision->setValue(value); | |||
| break; | |||
| case WobbleJuicePlugin::paramReso: | |||
| fKnobResonance->setValue(value); | |||
| break; | |||
| case WobbleJuicePlugin::paramRange: | |||
| fKnobRange->setValue(value); | |||
| break; | |||
| case WobbleJuicePlugin::paramPhase: | |||
| fKnobPhase->setValue(value); | |||
| break; | |||
| case WobbleJuicePlugin::paramWave: | |||
| fKnobWave->setValue(value); | |||
| break; | |||
| case WobbleJuicePlugin::paramDrive: | |||
| fKnobDrive->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| void WobbleJuiceUI::programLoaded(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fKnobDivision->setValue(4.0f); | |||
| fKnobResonance->setValue(0.1f); | |||
| fKnobRange->setValue(16000.0f); | |||
| fKnobPhase->setValue(0.0f); | |||
| fKnobWave->setValue(2.0f); | |||
| fKnobDrive->setValue(0.5f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void WobbleJuiceUI::imageButtonClicked(ImageButton* button, int) | |||
| { | |||
| if (button != fButtonAbout) | |||
| return; | |||
| fAboutWindow.exec(); | |||
| } | |||
| void WobbleJuiceUI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), true); | |||
| } | |||
| void WobbleJuiceUI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| editParameter(knob->getId(), false); | |||
| } | |||
| void WobbleJuiceUI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| setParameterValue(knob->getId(), value); | |||
| } | |||
| void WobbleJuiceUI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new WobbleJuiceUI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,75 +0,0 @@ | |||
| /* | |||
| * Wobble Juice Plugin | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef WOBBLEJUICEUI_HPP_INCLUDED | |||
| #define WOBBLEJUICEUI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageWidgets.hpp" | |||
| #include "WobbleJuiceArtwork.hpp" | |||
| using DGL_NAMESPACE::Image; | |||
| using DGL_NAMESPACE::ImageAboutWindow; | |||
| using DGL_NAMESPACE::ImageButton; | |||
| using DGL_NAMESPACE::ImageKnob; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class WobbleJuiceUI : public UI, | |||
| public ImageButton::Callback, | |||
| public ImageKnob::Callback | |||
| { | |||
| public: | |||
| WobbleJuiceUI(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void parameterChanged(uint32_t index, float value) override; | |||
| void programLoaded(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageButtonClicked(ImageButton* button, int) override; | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageAboutWindow fAboutWindow; | |||
| ScopedPointer<ImageButton> fButtonAbout; | |||
| ScopedPointer<ImageKnob> fKnobDivision, fKnobResonance, fKnobRange; | |||
| ScopedPointer<ImageKnob> fKnobPhase, fKnobWave, fKnobDrive; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WobbleJuiceUI) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // WOBBLEJUICEUI_HPP_INCLUDED | |||
| @@ -1,76 +0,0 @@ | |||
| /* | |||
| * Moog-like resonant LPF | |||
| * Implemented by Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz . | |||
| * | |||
| * Filter design from http://www.musicdsp.com . | |||
| */ | |||
| #ifndef MOOG_VCF_HXX_INCLUDED | |||
| #define MOOG_VCF_HXX_INCLUDED | |||
| #include <cmath> | |||
| #include <cstdlib> | |||
| class MoogVCF | |||
| { | |||
| public: | |||
| MoogVCF() | |||
| { | |||
| cutoff = 16000; | |||
| res = 0.5; | |||
| f=k=p=scale=r=0; | |||
| y1=y2=y3=y4=oldIn=oldY1=oldY2=oldY3=0; | |||
| in=oldIn=0; | |||
| pureInput=drivenInput=processedInput=0; | |||
| } | |||
| void recalc(float cutoff, float reso, int sr, float nDrive) | |||
| { | |||
| f = 2*cutoff/sr; | |||
| k=2*std::sin(f*M_PI/2)-1; | |||
| p = (k+1)*0.5; | |||
| scale = std::pow(2.71828, (1-p)*1.386249); | |||
| r = reso*scale; | |||
| drive = nDrive; | |||
| } | |||
| void process (long frames, const float* inputs, float* outputs) | |||
| { | |||
| //run the shit | |||
| for (long i=0; i<frames; i++) | |||
| { | |||
| pureInput = inputs[i]; //clean signal | |||
| drivenInput = std::tanh(pureInput*(drive*15+1)) * (drive); //a touch of waveshaping | |||
| processedInput = pureInput*(1-drive) + drivenInput; // combine | |||
| processedInput*=1-drive/3; //reduce gain a little | |||
| /* filter */ | |||
| in = processedInput-r*y4; | |||
| y1 = in*p + oldIn*p - k*y1; | |||
| y2 = y1*p + oldY1*p - k*y2; | |||
| y3 = y2*p + oldY2*p - k*y3; | |||
| y4 = y3*p + oldY3*p - k*y4; | |||
| oldIn = in; | |||
| oldY1 = y1; | |||
| oldY2 = y2; | |||
| oldY3 = y3; | |||
| /* output */ | |||
| outputs[i] = y4; | |||
| } | |||
| } | |||
| private: | |||
| /* vcf filter */ | |||
| float cutoff; //freq in Hz | |||
| float res; //resonance 0..1 | |||
| float drive; //drive 1...2; | |||
| float f, k, p, scale, r; | |||
| float y1, y2, y3, y4, oldY1, oldY2, oldY3; | |||
| float in, oldIn; | |||
| /* waveshaping vars */ | |||
| float pureInput, drivenInput, processedInput; | |||
| }; | |||
| #endif // MOOG_VCF_HXX_INCLUDED | |||
| @@ -1,598 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaDefines.h" | |||
| #define PLUGINVERSION | |||
| #define SOURCE_DIR "/usr/share/zynaddsubfx/examples" | |||
| #undef override | |||
| // ignore some compiler warnings | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Winconsistent-missing-override" | |||
| # pragma clang diagnostic ignored "-Wunused-private-field" | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic push | |||
| # pragma GCC diagnostic ignored "-Wliteral-suffix" | |||
| # if __GNUC__ >= 6 | |||
| # pragma GCC diagnostic ignored "-Wshift-negative-value" | |||
| # pragma GCC diagnostic ignored "-Wmisleading-indentation" | |||
| # endif | |||
| #endif | |||
| // base c-style headers | |||
| #include "zynaddsubfx/tlsf/tlsf.h" | |||
| #include "zynaddsubfx/rtosc/rtosc.h" | |||
| #ifdef SKIP_ZYN_SYNTH | |||
| # define PRId64 P_INT64 | |||
| # define PRIi64 P_INT64 | |||
| # define PRIx64 P_UINT64 | |||
| # define PRId32 "%d" | |||
| # define PRIi32 "%i" | |||
| # define PRIx32 "%x" | |||
| #endif | |||
| // C-code includes | |||
| extern "C" { | |||
| #include "zynaddsubfx/tlsf/tlsf.c" | |||
| #undef TLSF_64BIT | |||
| #undef tlsf_decl | |||
| #undef tlsf_fls_sizet | |||
| #undef tlsf_cast | |||
| #undef tlsf_min | |||
| #undef tlsf_max | |||
| #undef tlsf_assert | |||
| #undef _tlsf_glue2 | |||
| #undef _tlsf_glue | |||
| #undef tlsf_static_assert | |||
| #undef tlsf_insist | |||
| #include "zynaddsubfx/rtosc/dispatch.c" | |||
| #include "zynaddsubfx/rtosc/rtosc.c" | |||
| #ifdef CARLA_OS_WIN | |||
| # include "zynaddsubfx/rtosc/pretty-format.c" | |||
| #endif | |||
| } | |||
| // rtosc includes | |||
| #include "zynaddsubfx/rtosc/cpp/automations.cpp" | |||
| #include "zynaddsubfx/rtosc/cpp/midimapper.cpp" | |||
| #include "zynaddsubfx/rtosc/cpp/miditable.cpp" | |||
| #undef RTOSC_INVALID_MIDI | |||
| #undef MAX_UNHANDLED_PATH | |||
| #include "zynaddsubfx/rtosc/cpp/ports.cpp" | |||
| #undef __builtin_expect | |||
| #include "zynaddsubfx/rtosc/cpp/subtree-serialize.cpp" | |||
| #include "zynaddsubfx/rtosc/cpp/thread-link.cpp" | |||
| #undef off_t | |||
| #include "zynaddsubfx/rtosc/cpp/undo-history.cpp" | |||
| // zynaddsubfx includes | |||
| #include "zynaddsubfx/version.cpp" | |||
| #ifndef SKIP_ZYN_SYNTH | |||
| #include "zynaddsubfx/Containers/MultiPseudoStack.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Containers/NotePool.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Containers/ScratchString.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Bank.cpp" | |||
| #undef INSTRUMENT_EXTENSION | |||
| #undef FORCE_BANK_DIR_FILE | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #define INSTRUMENT_EXTENSION INSTRUMENT_EXTENSION_DB | |||
| #include "zynaddsubfx/Misc/BankDb.cpp" | |||
| #undef INSTRUMENT_EXTENSION | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/CallbackRepeater.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Config.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Master.cpp" | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Microtonal.cpp" | |||
| #undef MAX_LINE_SIZE | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/MiddleWare.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Part.cpp" | |||
| #undef CLONE | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/PresetExtractor.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Recorder.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/WavFile.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/ADnoteParameters.cpp" | |||
| #undef EXPAND | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/Controller.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/EnvelopeParams.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/LFOParams.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/PADnoteParameters.cpp" | |||
| #undef PC | |||
| #undef P_C | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/SUBnoteParameters.cpp" | |||
| #undef doPaste | |||
| #undef doPPaste | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/ADnote.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/Envelope.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/LFO.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/ModFilter.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/OscilGen.cpp" | |||
| #undef PC | |||
| #undef DIFF | |||
| #undef PRESERVE | |||
| #undef RESTORE | |||
| #undef FUNC | |||
| #undef FILTER | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/PADnote.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/Resonance.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/SUBnote.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/SynthNote.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Synth/WatchPoint.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/UI/ConnectionDummy.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/globals.cpp" | |||
| #endif // ! SKIP_ZYN_SYNTH | |||
| #include "zynaddsubfx/DSP/AnalogFilter.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/DSP/FFTwrapper.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/DSP/Filter.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/DSP/FormantFilter.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/DSP/SVFilter.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/DSP/Unison.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/Alienwah.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/Chorus.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/Distorsion.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/DynamicFilter.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/Echo.cpp" | |||
| #undef MAX_DELAY | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/Effect.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/EffectLFO.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/EffectMgr.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/EQ.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/Phaser.cpp" | |||
| #undef PHASER_LFO_SHAPE | |||
| #undef ONE_ | |||
| #undef ZERO_ | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Effects/Reverb.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Allocator.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/Util.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/WaveShapeSmps.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Misc/XMLwrapper.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/FilterParams.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/Presets.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/PresetsArray.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #include "zynaddsubfx/Params/PresetsStore.cpp" | |||
| #undef rBegin | |||
| #undef rObject | |||
| #undef rStdString | |||
| #undef rStdStringCb | |||
| #undef rChangeCb | |||
| #define rChangeCb | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic pop | |||
| #elif defined(__GNUC__) && (__GNUC__ >= 6) | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| #ifndef SKIP_ZYN_SYNTH | |||
| // Dummy variables and functions for linking purposes | |||
| namespace zyncarla { | |||
| class WavFile; | |||
| namespace Nio { | |||
| void masterSwap(Master*){} | |||
| bool setSource(std::string){return true;} | |||
| bool setSink(std::string){return true;} | |||
| std::set<std::string> getSources(void){return std::set<std::string>();} | |||
| std::set<std::string> getSinks(void){return std::set<std::string>();} | |||
| std::string getSource(void){return "";} | |||
| std::string getSink(void){return "";} | |||
| void waveNew(WavFile*){} | |||
| void waveStart(){} | |||
| void waveStop(){} | |||
| } | |||
| } | |||
| #endif // ! SKIP_ZYN_SYNTH | |||
| #ifdef CARLA_OS_WIN | |||
| rtosc_version rtosc_current_version() | |||
| { | |||
| return ((rtosc_version) { 0, 0, 0 } ); | |||
| } | |||
| void rtosc_version_print_to_12byte_str(const rtosc_version* v, | |||
| char* _12bytes) | |||
| { | |||
| snprintf(_12bytes, 12, "%u.%u.%u", | |||
| (unsigned)v->major, (unsigned)v->minor, (unsigned)v->revision); | |||
| } | |||
| #endif | |||
| @@ -1,273 +0,0 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaString.hpp" | |||
| #include "CarlaPipeUtils.hpp" | |||
| #define PLUGINVERSION | |||
| #define SOURCE_DIR "/usr/share/zynaddsubfx" | |||
| #undef override | |||
| #ifdef NTK_GUI | |||
| # include <dlfcn.h> | |||
| static CarlaString getResourceDir() | |||
| { | |||
| Dl_info exeInfo; | |||
| dladdr((void*)getResourceDir, &exeInfo); | |||
| CarlaString filename(exeInfo.dli_fname); | |||
| return filename.truncate(filename.rfind("-ui")); | |||
| } | |||
| CarlaString gUiPixmapPath(getResourceDir()); | |||
| #endif | |||
| // base c-style headers | |||
| #include "zynaddsubfx/rtosc/rtosc.h" | |||
| // rtosc c includes | |||
| extern "C" { | |||
| #include "zynaddsubfx/rtosc/dispatch.c" | |||
| #include "zynaddsubfx/rtosc/rtosc.c" | |||
| } | |||
| // ignore some compiler warnings | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Winconsistent-missing-override" | |||
| # pragma clang diagnostic ignored "-Wunused-private-field" | |||
| #elif defined(__GNUC__) && (__GNUC__ >= 6) | |||
| # pragma GCC diagnostic push | |||
| # pragma GCC diagnostic ignored "-Wmisleading-indentation" | |||
| # if (__GNUC__ >= 7) | |||
| # pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |||
| # endif | |||
| #endif | |||
| // rtosc c++ includes | |||
| #include "zynaddsubfx/rtosc/cpp/midimapper.cpp" | |||
| #include "zynaddsubfx/rtosc/cpp/miditable.cpp" | |||
| #undef RTOSC_INVALID_MIDI | |||
| #undef MAX_UNHANDLED_PATH | |||
| #include "zynaddsubfx/rtosc/cpp/ports.cpp" | |||
| #undef __builtin_expect | |||
| #include "zynaddsubfx/rtosc/cpp/subtree-serialize.cpp" | |||
| #include "zynaddsubfx/rtosc/cpp/thread-link.cpp" | |||
| #undef off_t | |||
| #undef static | |||
| #include "zynaddsubfx/rtosc/cpp/undo-history.cpp" | |||
| // zynaddsubfx ui includes | |||
| #include "zynaddsubfx/UI/NioUI.cpp" | |||
| #include "zynaddsubfx/UI/WidgetPDial.cpp" | |||
| #include "zynaddsubfx/UI/ADnoteUI.cpp" | |||
| #include "zynaddsubfx/UI/BankUI.cpp" | |||
| #include "zynaddsubfx/UI/BankView.cpp" | |||
| #include "zynaddsubfx/UI/ConfigUI.cpp" | |||
| // #include "zynaddsubfx/UI/Connection.cpp" | |||
| #include "zynaddsubfx/UI/EffUI.cpp" | |||
| #include "zynaddsubfx/UI/EnvelopeFreeEdit.cpp" | |||
| #include "zynaddsubfx/UI/EnvelopeUI.cpp" | |||
| #include "zynaddsubfx/UI/FilterUI.cpp" | |||
| #include "zynaddsubfx/UI/Fl_EQGraph.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Button.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Check.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Choice.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Counter.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Dial.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_DialF.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Input.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_ListView.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Numeric_Input.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Output.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Pane.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Roller.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Slider.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_TSlider.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Value.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_VSlider.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Osc_Widget.cpp" | |||
| #include "zynaddsubfx/UI/Fl_Resonance_Graph.cpp" | |||
| #include "zynaddsubfx/UI/FormantFilterGraph.cpp" | |||
| #include "zynaddsubfx/UI/LFOUI.cpp" | |||
| #include "zynaddsubfx/UI/MasterUI.cpp" | |||
| #include "zynaddsubfx/UI/MicrotonalUI.cpp" | |||
| #include "zynaddsubfx/UI/OscilGenUI.cpp" | |||
| #include "zynaddsubfx/UI/PADnoteUI.cpp" | |||
| #include "zynaddsubfx/UI/PartNameButton.cpp" | |||
| #include "zynaddsubfx/UI/PartUI.cpp" | |||
| #include "zynaddsubfx/UI/PresetsUI.cpp" | |||
| #include "zynaddsubfx/UI/ResonanceUI.cpp" | |||
| #include "zynaddsubfx/UI/SUBnoteUI.cpp" | |||
| #include "zynaddsubfx/UI/TipWin.cpp" | |||
| #include "zynaddsubfx/UI/VirKeyboard.cpp" | |||
| #include "zynaddsubfx/UI/guimain.cpp" | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic pop | |||
| #elif defined(__GNUC__) && (__GNUC__ >= 6) | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| class ZynPipeClient : public CarlaPipeClient | |||
| { | |||
| public: | |||
| ZynPipeClient() noexcept | |||
| : CarlaPipeClient(), | |||
| fQuitReceived(false) {} | |||
| ~ZynPipeClient() noexcept override | |||
| { | |||
| if (fQuitReceived) | |||
| return; | |||
| writeExitingMessageAndWait(); | |||
| } | |||
| protected: | |||
| bool msgReceived(const char* const msg) noexcept override | |||
| { | |||
| if (std::strcmp(msg, "control") == 0) | |||
| { | |||
| uint index; | |||
| float value; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); | |||
| // TODO | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "program") == 0) | |||
| { | |||
| uint i; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(i), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(i), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(i), true); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "show") == 0) | |||
| { | |||
| try { | |||
| GUI::raiseUi(gui, "/show", "i", 1); | |||
| } CARLA_SAFE_EXCEPTION("msgReceived show"); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "hide") == 0) | |||
| { | |||
| try { | |||
| GUI::raiseUi(gui, "/hide", ""); | |||
| } CARLA_SAFE_EXCEPTION("msgReceived hide"); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "focus") == 0) | |||
| { | |||
| try { | |||
| GUI::raiseUi(gui, "/focus", ""); | |||
| } CARLA_SAFE_EXCEPTION("msgReceived focus"); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "uiTitle") == 0) | |||
| { | |||
| const char* uiTitle; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uiTitle), true); | |||
| try { | |||
| GUI::raiseUi(gui, "/ui/title", "s", uiTitle); | |||
| } CARLA_SAFE_EXCEPTION("msgReceived uiTitle"); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "quit") == 0) | |||
| { | |||
| fQuitReceived = true; | |||
| try { | |||
| GUI::raiseUi(gui, "/close-ui", ""); | |||
| } CARLA_SAFE_EXCEPTION("msgReceived quit"); | |||
| return true; | |||
| } | |||
| carla_stderr("ZynPipeClient::msgReceived : %s", msg); | |||
| return false; | |||
| } | |||
| private: | |||
| bool fQuitReceived; | |||
| }; | |||
| int main(int argc, const char* argv[]) | |||
| { | |||
| ZynPipeClient pipe; | |||
| const char* uiTitle = nullptr; | |||
| if (argc > 1) | |||
| { | |||
| sendtourl = argv[1]; | |||
| uiTitle = argv[2]; | |||
| if (! pipe.initPipeClient(argv)) | |||
| return 1; | |||
| server = lo_server_new_with_proto(NULL, LO_UDP, liblo_error_cb); | |||
| lo_server_add_method(server, NULL, NULL, handler_function, 0); | |||
| } | |||
| std::thread lo_watch(watch_lo); | |||
| gui = GUI::createUi(new UI_Interface(), &Pexitprogram); | |||
| if (argc == 1) | |||
| { | |||
| // testing only | |||
| GUI::raiseUi(gui, "/show", "i", 1); | |||
| } | |||
| else | |||
| { | |||
| // full thing | |||
| isPlugin = true; | |||
| MasterUI::menu_mastermenu[11].hide(); // file -> nio settings | |||
| } | |||
| if (uiTitle != nullptr && uiTitle[0] != '\0') | |||
| GUI::raiseUi(gui, "/ui/title", "s", uiTitle); | |||
| for (; Pexitprogram == 0;) | |||
| { | |||
| pipe.idlePipe(); | |||
| GUI::tickUi(gui); | |||
| for (; lo_buffer.hasNext();) | |||
| raiseUi(gui, lo_buffer.read()); | |||
| } | |||
| GUI::destroyUi(gui); | |||
| gui = nullptr; | |||
| lo_watch.join(); | |||
| return 0; | |||
| } | |||
| #include "CarlaPipeUtils.cpp" | |||
| #include "water/misc/Time.cpp" | |||
| // -------------------------------------------------------------------------------------------- | |||
| @@ -1,121 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| MultiPseudoStack.cpp - Multiple-Writer Lock Free Datastructure | |||
| Copyright (C) 2016 Mark McCurry | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include "MultiPseudoStack.h" | |||
| #include <cassert> | |||
| #include <cstdio> | |||
| #define INVALID ((int32_t)0xffffffff) | |||
| #define MAX ((int32_t)0x7fffffff) | |||
| namespace zyncarla { | |||
| QueueListItem::QueueListItem(void) | |||
| :memory(0), size(0) | |||
| { | |||
| } | |||
| LockFreeQueue::LockFreeQueue(qli_t *data_, int n) | |||
| :data(data_), elms(n), next_r(0), next_w(0), avail(0) | |||
| { | |||
| tag = new std::atomic<uint32_t>[n]; | |||
| for(int i=0; i<n; ++i) | |||
| tag[i] = INVALID; | |||
| } | |||
| LockFreeQueue::~LockFreeQueue(void) | |||
| { | |||
| delete [] tag; | |||
| } | |||
| qli_t *LockFreeQueue::read(void) { | |||
| retry: | |||
| int8_t free_elms = avail.load(); | |||
| if(free_elms <= 0) | |||
| return 0; | |||
| int32_t next_tag = next_r.load(); | |||
| int32_t next_next_tag = (next_tag+1)&MAX; | |||
| assert(next_tag != INVALID); | |||
| for(int i=0; i<elms; ++i) { | |||
| uint32_t elm_tag = tag[i].load(); | |||
| //attempt to remove tagged element | |||
| //if and only if it's next | |||
| if(((uint32_t)next_tag) == elm_tag) { | |||
| if(!tag[i].compare_exchange_strong(elm_tag, INVALID)) | |||
| goto retry; | |||
| //Ok, now there is no element that can be removed from the list | |||
| //Effectively there's mutual exclusion over other readers here | |||
| //Set the next element | |||
| int sane_read = next_r.compare_exchange_strong(next_tag, next_next_tag); | |||
| assert(sane_read && "No double read on a single tag"); | |||
| //Decrement available elements | |||
| int32_t free_elms_next = avail.load(); | |||
| while(!avail.compare_exchange_strong(free_elms_next, free_elms_next-1)); | |||
| //printf("r%d ", free_elms_next-1); | |||
| return &data[i]; | |||
| } | |||
| } | |||
| goto retry; | |||
| } | |||
| //Insert Node Q | |||
| void LockFreeQueue::write(qli_t *Q) { | |||
| retry: | |||
| if(!Q) | |||
| return; | |||
| int32_t write_tag = next_w.load(); | |||
| int32_t next_write_tag = (write_tag+1)&MAX; | |||
| if(!next_w.compare_exchange_strong(write_tag, next_write_tag)) | |||
| goto retry; | |||
| uint32_t invalid_tag = INVALID; | |||
| //Update tag | |||
| int sane_write = tag[Q-data].compare_exchange_strong(invalid_tag, write_tag); | |||
| assert(sane_write); | |||
| //Increment available elements | |||
| int32_t free_elms = avail.load(); | |||
| while(!avail.compare_exchange_strong(free_elms, free_elms+1)) | |||
| assert(free_elms <= 32); | |||
| //printf("w%d ", free_elms+1); | |||
| } | |||
| MultiQueue::MultiQueue(void) | |||
| :pool(new qli_t[32]), m_free(pool, 32), m_msgs(pool, 32) | |||
| { | |||
| //32 instances of 2kBi memory chunks | |||
| for(int i=0; i<32; ++i) { | |||
| qli_t &ptr = pool[i]; | |||
| ptr.size = 2048; | |||
| ptr.memory = new char[2048]; | |||
| free(&ptr); | |||
| } | |||
| } | |||
| MultiQueue::~MultiQueue(void) | |||
| { | |||
| for(int i=0; i<32; ++i) | |||
| delete [] pool[i].memory; | |||
| delete [] pool; | |||
| } | |||
| } | |||
| @@ -1,66 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| MultiPseudoStack.h - Multiple-Writer Lock Free Datastructure | |||
| Copyright (C) 2016 Mark McCurry | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #pragma once | |||
| #include <atomic> | |||
| #include <cassert> | |||
| namespace zyncarla { | |||
| //XXX rename this thing | |||
| typedef struct QueueListItem qli_t; | |||
| struct QueueListItem | |||
| { | |||
| QueueListItem(void); | |||
| char *memory; | |||
| uint32_t size; | |||
| }; | |||
| //Many reader many writer | |||
| class LockFreeQueue | |||
| { | |||
| qli_t *const data; | |||
| const int elms; | |||
| std::atomic<uint32_t> *tag; | |||
| std::atomic<int32_t> next_r; | |||
| std::atomic<int32_t> next_w; | |||
| std::atomic<int32_t> avail; | |||
| public: | |||
| LockFreeQueue(qli_t *data_, int n); | |||
| ~LockFreeQueue(void); | |||
| qli_t *read(void); | |||
| void write(qli_t *Q); | |||
| }; | |||
| /* | |||
| * Many reader Many writer capiable queue | |||
| * - lock free | |||
| * - allocation free (post initialization) | |||
| */ | |||
| class MultiQueue | |||
| { | |||
| qli_t *pool; | |||
| LockFreeQueue m_free; | |||
| LockFreeQueue m_msgs; | |||
| public: | |||
| MultiQueue(void); | |||
| ~MultiQueue(void); | |||
| void dump(void); | |||
| qli_t *alloc(void) { return m_free.read(); } | |||
| void free(qli_t *q) { m_free.write(q); } | |||
| void write(qli_t *q) { m_msgs.write(q); } | |||
| qli_t *read(void) { return m_msgs.read(); } | |||
| }; | |||
| } | |||
| @@ -1,436 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| NotePool.cpp - Pool of Synthesizer Engines And Note Instances | |||
| Copyright (C) 2016 Mark McCurry | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include "NotePool.h" | |||
| #include "../Misc/Allocator.h" | |||
| #include "../Synth/SynthNote.h" | |||
| #include <cstring> | |||
| #include <cassert> | |||
| #include <iostream> | |||
| #define SUSTAIN_BIT 0x04 | |||
| #define NOTE_MASK 0x03 | |||
| namespace zyncarla { | |||
| enum NoteStatus { | |||
| KEY_OFF = 0x00, | |||
| KEY_PLAYING = 0x01, | |||
| KEY_RELEASED_AND_SUSTAINED = 0x02, | |||
| KEY_RELEASED = 0x03 | |||
| }; | |||
| NotePool::NotePool(void) | |||
| :needs_cleaning(0) | |||
| { | |||
| memset(ndesc, 0, sizeof(ndesc)); | |||
| memset(sdesc, 0, sizeof(sdesc)); | |||
| } | |||
| bool NotePool::NoteDescriptor::playing(void) const | |||
| { | |||
| return (status&NOTE_MASK) == KEY_PLAYING; | |||
| } | |||
| bool NotePool::NoteDescriptor::sustained(void) const | |||
| { | |||
| return (status&NOTE_MASK) == KEY_RELEASED_AND_SUSTAINED; | |||
| } | |||
| bool NotePool::NoteDescriptor::released(void) const | |||
| { | |||
| return (status&NOTE_MASK) == KEY_RELEASED; | |||
| } | |||
| bool NotePool::NoteDescriptor::off(void) const | |||
| { | |||
| return (status&NOTE_MASK) == KEY_OFF; | |||
| } | |||
| void NotePool::NoteDescriptor::setStatus(uint8_t s) | |||
| { | |||
| status &= ~NOTE_MASK; | |||
| status |= (NOTE_MASK&s); | |||
| } | |||
| void NotePool::NoteDescriptor::doSustain(void) | |||
| { | |||
| setStatus(KEY_RELEASED_AND_SUSTAINED); | |||
| } | |||
| bool NotePool::NoteDescriptor::canSustain(void) const | |||
| { | |||
| return !(status & SUSTAIN_BIT); | |||
| } | |||
| void NotePool::NoteDescriptor::makeUnsustainable(void) | |||
| { | |||
| status |= SUSTAIN_BIT; | |||
| } | |||
| NotePool::activeNotesIter NotePool::activeNotes(NoteDescriptor &n) | |||
| { | |||
| const int off_d1 = &n-ndesc; | |||
| int off_d2 = 0; | |||
| assert(off_d1 <= POLYPHONY); | |||
| for(int i=0; i<off_d1; ++i) | |||
| off_d2 += ndesc[i].size; | |||
| return NotePool::activeNotesIter{sdesc+off_d2,sdesc+off_d2+n.size}; | |||
| } | |||
| bool NotePool::NoteDescriptor::operator==(NoteDescriptor nd) | |||
| { | |||
| return age == nd.age && note == nd.note && sendto == nd.sendto && size == nd.size && status == nd.status; | |||
| } | |||
| //return either the first unused descriptor or the last valid descriptor which | |||
| //matches note/sendto | |||
| static int getMergeableDescriptor(uint8_t note, uint8_t sendto, bool legato, | |||
| NotePool::NoteDescriptor *ndesc) | |||
| { | |||
| int desc_id = 0; | |||
| for(int i=0; i<POLYPHONY; ++i, ++desc_id) | |||
| if(ndesc[desc_id].off()) | |||
| break; | |||
| if(desc_id != 0) { | |||
| auto &nd = ndesc[desc_id-1]; | |||
| if(nd.age == 0 && nd.note == note && nd.sendto == sendto | |||
| && nd.playing() && nd.legatoMirror == legato && nd.canSustain()) | |||
| return desc_id-1; | |||
| } | |||
| //Out of free descriptors | |||
| if(desc_id >= POLYPHONY || !ndesc[desc_id].off()) { | |||
| return -1; | |||
| } | |||
| return desc_id; | |||
| } | |||
| NotePool::activeDescIter NotePool::activeDesc(void) | |||
| { | |||
| cleanup(); | |||
| return activeDescIter{*this}; | |||
| } | |||
| NotePool::constActiveDescIter NotePool::activeDesc(void) const | |||
| { | |||
| const_cast<NotePool*>(this)->cleanup(); | |||
| return constActiveDescIter{*this}; | |||
| } | |||
| int NotePool::usedNoteDesc(void) const | |||
| { | |||
| if(needs_cleaning) | |||
| const_cast<NotePool*>(this)->cleanup(); | |||
| int cnt = 0; | |||
| for(int i=0; i<POLYPHONY; ++i) | |||
| cnt += (ndesc[i].size != 0); | |||
| return cnt; | |||
| } | |||
| int NotePool::usedSynthDesc(void) const | |||
| { | |||
| if(needs_cleaning) | |||
| const_cast<NotePool*>(this)->cleanup(); | |||
| int cnt = 0; | |||
| for(int i=0; i<POLYPHONY*EXPECTED_USAGE; ++i) | |||
| cnt += (bool)sdesc[i].note; | |||
| return cnt; | |||
| } | |||
| void NotePool::insertNote(uint8_t note, uint8_t sendto, SynthDescriptor desc, bool legato) | |||
| { | |||
| //Get first free note descriptor | |||
| int desc_id = getMergeableDescriptor(note, sendto, legato, ndesc); | |||
| assert(desc_id != -1); | |||
| ndesc[desc_id].note = note; | |||
| ndesc[desc_id].sendto = sendto; | |||
| ndesc[desc_id].size += 1; | |||
| ndesc[desc_id].status = KEY_PLAYING; | |||
| ndesc[desc_id].legatoMirror = legato; | |||
| //Get first free synth descriptor | |||
| int sdesc_id = 0; | |||
| while(sdesc[sdesc_id].note && sdesc_id < POLYPHONY*EXPECTED_USAGE) | |||
| sdesc_id++; | |||
| assert(sdesc_id < POLYPHONY*EXPECTED_USAGE); | |||
| sdesc[sdesc_id] = desc; | |||
| }; | |||
| void NotePool::upgradeToLegato(void) | |||
| { | |||
| for(auto &d:activeDesc()) | |||
| if(d.playing()) | |||
| for(auto &s:activeNotes(d)) | |||
| insertLegatoNote(d.note, d.sendto, s); | |||
| } | |||
| void NotePool::insertLegatoNote(uint8_t note, uint8_t sendto, SynthDescriptor desc) | |||
| { | |||
| assert(desc.note); | |||
| try { | |||
| desc.note = desc.note->cloneLegato(); | |||
| insertNote(note, sendto, desc, true); | |||
| } catch (std::bad_alloc &ba) { | |||
| std::cerr << "failed to insert legato note: " << ba.what() << std::endl; | |||
| } | |||
| }; | |||
| //There should only be one pair of notes which are still playing | |||
| void NotePool::applyLegato(LegatoParams &par) | |||
| { | |||
| for(auto &desc:activeDesc()) { | |||
| desc.note = par.midinote; | |||
| for(auto &synth:activeNotes(desc)) | |||
| try { | |||
| synth.note->legatonote(par); | |||
| } catch (std::bad_alloc& ba) { | |||
| std::cerr << "failed to create legato note: " << ba.what() << std::endl; | |||
| } | |||
| } | |||
| } | |||
| void NotePool::makeUnsustainable(uint8_t note) | |||
| { | |||
| for(auto &desc:activeDesc()) { | |||
| if(desc.note == note) { | |||
| desc.makeUnsustainable(); | |||
| if(desc.sustained()) | |||
| release(desc); | |||
| } | |||
| } | |||
| } | |||
| bool NotePool::full(void) const | |||
| { | |||
| for(int i=0; i<POLYPHONY; ++i) | |||
| if(ndesc[i].off()) | |||
| return false; | |||
| return true; | |||
| } | |||
| bool NotePool::synthFull(int sdesc_count) const | |||
| { | |||
| int actually_free=sizeof(sdesc)/sizeof(sdesc[0]); | |||
| for(const auto &desc:activeDesc()) { | |||
| actually_free -= desc.size; | |||
| } | |||
| return actually_free < sdesc_count; | |||
| } | |||
| //Note that isn't KEY_PLAYING or KEY_RELASED_AND_SUSTAINING | |||
| bool NotePool::existsRunningNote(void) const | |||
| { | |||
| //printf("runing note # =%d\n", getRunningNotes()); | |||
| return getRunningNotes(); | |||
| } | |||
| int NotePool::getRunningNotes(void) const | |||
| { | |||
| bool running[256] = {0}; | |||
| for(auto &desc:activeDesc()) { | |||
| //printf("note!(%d)\n", desc.note); | |||
| if(desc.playing() || desc.sustained()) | |||
| running[desc.note] = true; | |||
| } | |||
| int running_count = 0; | |||
| for(int i=0; i<256; ++i) | |||
| running_count += running[i]; | |||
| return running_count; | |||
| } | |||
| void NotePool::enforceKeyLimit(int limit) | |||
| { | |||
| int notes_to_kill = getRunningNotes() - limit; | |||
| if(notes_to_kill <= 0) | |||
| return; | |||
| NoteDescriptor *to_kill = NULL; | |||
| unsigned oldest = 0; | |||
| for(auto &nd : activeDesc()) { | |||
| if(to_kill == NULL) { | |||
| //There must be something to kill | |||
| oldest = nd.age; | |||
| to_kill = &nd; | |||
| } else if(to_kill->released() && nd.playing()) { | |||
| //Prefer to kill off a running note | |||
| oldest = nd.age; | |||
| to_kill = &nd; | |||
| } else if(nd.age > oldest && !(to_kill->playing() && nd.released())) { | |||
| //Get an older note when it doesn't move from running to released | |||
| oldest = nd.age; | |||
| to_kill = &nd; | |||
| } | |||
| } | |||
| if(to_kill) { | |||
| auto &tk = *to_kill; | |||
| if(tk.released() || tk.sustained()) | |||
| kill(*to_kill); | |||
| else | |||
| entomb(*to_kill); | |||
| } | |||
| } | |||
| void NotePool::releasePlayingNotes(void) | |||
| { | |||
| for(auto &d:activeDesc()) { | |||
| if(d.playing() || d.sustained()) { | |||
| d.setStatus(KEY_RELEASED); | |||
| for(auto s:activeNotes(d)) | |||
| s.note->releasekey(); | |||
| } | |||
| } | |||
| } | |||
| void NotePool::release(NoteDescriptor &d) | |||
| { | |||
| d.setStatus(KEY_RELEASED); | |||
| for(auto s:activeNotes(d)) | |||
| s.note->releasekey(); | |||
| } | |||
| void NotePool::killAllNotes(void) | |||
| { | |||
| for(auto &d:activeDesc()) | |||
| kill(d); | |||
| } | |||
| void NotePool::killNote(uint8_t note) | |||
| { | |||
| for(auto &d:activeDesc()) { | |||
| if(d.note == note) | |||
| kill(d); | |||
| } | |||
| } | |||
| void NotePool::kill(NoteDescriptor &d) | |||
| { | |||
| d.setStatus(KEY_OFF); | |||
| for(auto &s:activeNotes(d)) | |||
| kill(s); | |||
| } | |||
| void NotePool::kill(SynthDescriptor &s) | |||
| { | |||
| //printf("Kill synth...\n"); | |||
| s.note->memory.dealloc(s.note); | |||
| needs_cleaning = true; | |||
| } | |||
| void NotePool::entomb(NoteDescriptor &d) | |||
| { | |||
| d.setStatus(KEY_RELEASED); | |||
| for(auto &s:activeNotes(d)) | |||
| s.note->entomb(); | |||
| } | |||
| const char *getStatus(int status_bits) | |||
| { | |||
| switch(status_bits) | |||
| { | |||
| case 0: return "OFF "; | |||
| case 1: return "PLAY"; | |||
| case 2: return "SUST"; | |||
| case 3: return "RELA"; | |||
| default: return "INVD"; | |||
| } | |||
| } | |||
| void NotePool::cleanup(void) | |||
| { | |||
| if(!needs_cleaning) | |||
| return; | |||
| needs_cleaning = false; | |||
| int new_length[POLYPHONY] = {0}; | |||
| int cur_length[POLYPHONY] = {0}; | |||
| //printf("Cleanup Start\n"); | |||
| //dump(); | |||
| //Identify the current length of all segments | |||
| //and the lengths discarding invalid entries | |||
| int last_valid_desc = 0; | |||
| for(int i=0; i<POLYPHONY; ++i) | |||
| if(!ndesc[i].off()) | |||
| last_valid_desc = i; | |||
| //Find the real numbers of allocated notes | |||
| { | |||
| int cum_old = 0; | |||
| for(int i=0; i<=last_valid_desc; ++i) { | |||
| cur_length[i] = ndesc[i].size; | |||
| for(int j=0; j<ndesc[i].size; ++j) | |||
| new_length[i] += (bool)sdesc[cum_old++].note; | |||
| } | |||
| } | |||
| //Move the note descriptors | |||
| { | |||
| int cum_new = 0; | |||
| for(int i=0; i<=last_valid_desc; ++i) { | |||
| ndesc[i].size = new_length[i]; | |||
| if(new_length[i] != 0) | |||
| ndesc[cum_new++] = ndesc[i]; | |||
| else | |||
| ndesc[i].setStatus(KEY_OFF); | |||
| } | |||
| memset(ndesc+cum_new, 0, sizeof(*ndesc)*(POLYPHONY-cum_new)); | |||
| } | |||
| //Move the synth descriptors | |||
| { | |||
| int total_notes=0; | |||
| for(int i=0; i<=last_valid_desc; ++i) | |||
| total_notes+=cur_length[i]; | |||
| int cum_new = 0; | |||
| for(int i=0; i<total_notes; ++i) | |||
| if(sdesc[i].note) | |||
| sdesc[cum_new++] = sdesc[i]; | |||
| memset(sdesc+cum_new, 0, sizeof(*sdesc)*(POLYPHONY*EXPECTED_USAGE-cum_new)); | |||
| } | |||
| //printf("Cleanup Done\n"); | |||
| //dump(); | |||
| } | |||
| void NotePool::dump(void) | |||
| { | |||
| printf("NotePool::dump<\n"); | |||
| const char *format = | |||
| " Note %d:%d age(%d) note(%d) sendto(%d) status(%s) legato(%d) type(%d) kit(%d) ptr(%p)\n"; | |||
| int note_id=0; | |||
| int descriptor_id=0; | |||
| for(auto &d:activeDesc()) { | |||
| descriptor_id += 1; | |||
| for(auto &s:activeNotes(d)) { | |||
| note_id += 1; | |||
| printf(format, | |||
| note_id, descriptor_id, | |||
| d.age, d.note, d.sendto, | |||
| getStatus(d.status), d.legatoMirror, s.type, s.kit, s.note); | |||
| } | |||
| } | |||
| printf(">NotePool::dump\n"); | |||
| } | |||
| } | |||
| @@ -1,151 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| NotePool.h - Pool of Synthesizer Engines And Note Instances | |||
| Copyright (C) 2016 Mark McCurry | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #pragma once | |||
| #include <stdint.h> | |||
| #include <functional> | |||
| #include "../globals.h" | |||
| //Expected upper bound of synths given that max polyphony is hit | |||
| #define EXPECTED_USAGE 3 | |||
| namespace zyncarla { | |||
| struct LegatoParams; | |||
| class NotePool | |||
| { | |||
| public: | |||
| typedef uint8_t note_t; | |||
| //Currently this wastes a ton of bits due ot the legatoMirror flag | |||
| struct NoteDescriptor { | |||
| //acceptable overlap after 2 minutes | |||
| //run time at 48kHz 8 samples per buffer | |||
| //19 bit minimum | |||
| uint32_t age; | |||
| uint8_t note; | |||
| uint8_t sendto; | |||
| //max of 16 kit elms and 3 kit items per | |||
| uint8_t size; | |||
| uint8_t status; | |||
| bool legatoMirror; | |||
| bool operator==(NoteDescriptor); | |||
| //status checks | |||
| bool playing(void) const; | |||
| bool off(void) const; | |||
| bool sustained(void) const; | |||
| bool released(void) const; | |||
| //status transitions | |||
| void setStatus(uint8_t s); | |||
| void doSustain(void); | |||
| bool canSustain(void) const; | |||
| void makeUnsustainable(void); | |||
| }; | |||
| //To be pedantic this wastes 2 or 6 bytes per descriptor | |||
| //depending on 32bit/64bit alignment rules | |||
| struct SynthDescriptor { | |||
| SynthNote *note; | |||
| uint8_t type; | |||
| uint8_t kit; | |||
| }; | |||
| //Pool of notes | |||
| NoteDescriptor ndesc[POLYPHONY]; | |||
| SynthDescriptor sdesc[POLYPHONY*EXPECTED_USAGE]; | |||
| bool needs_cleaning; | |||
| //Iterators | |||
| struct activeNotesIter { | |||
| SynthDescriptor *begin() {return _b;}; | |||
| SynthDescriptor *end() {return _e;}; | |||
| SynthDescriptor *_b; | |||
| SynthDescriptor *_e; | |||
| }; | |||
| struct activeDescIter { | |||
| activeDescIter(NotePool &_np):np(_np) | |||
| { | |||
| int off=0; | |||
| for(int i=0; i<POLYPHONY; ++i, ++off) | |||
| if(np.ndesc[i].status == 0) | |||
| break; | |||
| _end = np.ndesc+off; | |||
| } | |||
| NoteDescriptor *begin() {return np.ndesc;}; | |||
| NoteDescriptor *end() { return _end; }; | |||
| NoteDescriptor *_end; | |||
| NotePool &np; | |||
| }; | |||
| struct constActiveDescIter { | |||
| constActiveDescIter(const NotePool &_np):np(_np) | |||
| { | |||
| int off=0; | |||
| for(int i=0; i<POLYPHONY; ++i, ++off) | |||
| if(np.ndesc[i].status == 0) | |||
| break; | |||
| _end = np.ndesc+off; | |||
| } | |||
| const NoteDescriptor *begin() const {return np.ndesc;}; | |||
| const NoteDescriptor *end() const { return _end; }; | |||
| const NoteDescriptor *_end; | |||
| const NotePool &np; | |||
| }; | |||
| activeNotesIter activeNotes(NoteDescriptor &n); | |||
| activeDescIter activeDesc(void); | |||
| constActiveDescIter activeDesc(void) const; | |||
| //Counts of descriptors used for tests | |||
| int usedNoteDesc(void) const; | |||
| int usedSynthDesc(void) const; | |||
| NotePool(void); | |||
| //Operations | |||
| void insertNote(uint8_t note, uint8_t sendto, SynthDescriptor desc, bool legato=false); | |||
| void insertLegatoNote(uint8_t note, uint8_t sendto, SynthDescriptor desc); | |||
| void upgradeToLegato(void); | |||
| void applyLegato(LegatoParams &par); | |||
| void makeUnsustainable(uint8_t note); | |||
| bool full(void) const; | |||
| bool synthFull(int sdesc_count) const; | |||
| //Note that isn't KEY_PLAYING or KEY_RELASED_AND_SUSTAINING | |||
| bool existsRunningNote(void) const; | |||
| int getRunningNotes(void) const; | |||
| void enforceKeyLimit(int limit); | |||
| void releasePlayingNotes(void); | |||
| void releaseNote(note_t note); | |||
| void release(NoteDescriptor &d); | |||
| void killAllNotes(void); | |||
| void killNote(note_t note); | |||
| void kill(NoteDescriptor &d); | |||
| void kill(SynthDescriptor &s); | |||
| void entomb(NoteDescriptor &d); | |||
| void cleanup(void); | |||
| void dump(void); | |||
| }; | |||
| } | |||
| @@ -1,43 +0,0 @@ | |||
| #include "ScratchString.h" | |||
| #include <cstring> | |||
| #include <cstdio> | |||
| namespace zyncarla { | |||
| ScratchString::ScratchString(void) | |||
| { | |||
| memset(c_str, 0, sizeof(c_str)); | |||
| } | |||
| ScratchString::ScratchString(int num) | |||
| { | |||
| snprintf(c_str, SCRATCH_SIZE, "%d", num); | |||
| } | |||
| ScratchString::ScratchString(unsigned char num) | |||
| { | |||
| snprintf(c_str, SCRATCH_SIZE, "%d", num); | |||
| } | |||
| ScratchString::ScratchString(const char *str) | |||
| { | |||
| if(str) | |||
| strncpy(c_str, str, SCRATCH_SIZE); | |||
| else | |||
| memset(c_str, 0, sizeof(c_str)); | |||
| } | |||
| ScratchString ScratchString::operator+(const ScratchString s) | |||
| { | |||
| ScratchString ss; | |||
| strncpy(ss.c_str, c_str, SCRATCH_SIZE); | |||
| strncat(ss.c_str, s.c_str, SCRATCH_SIZE-strlen(c_str)); | |||
| return ss; | |||
| } | |||
| //ScratchString::operator const char*() const | |||
| //{ | |||
| // return c_str; | |||
| //} | |||
| } | |||
| @@ -1,22 +0,0 @@ | |||
| #pragma once | |||
| #define SCRATCH_SIZE 128 | |||
| namespace zyncarla { | |||
| //Fixed Size String Substitute | |||
| struct ScratchString | |||
| { | |||
| ScratchString(void); | |||
| ScratchString(int num); | |||
| ScratchString(unsigned char num); | |||
| ScratchString(const char *str); | |||
| ScratchString operator+(const ScratchString s); | |||
| //operator const char*() const; | |||
| char c_str[SCRATCH_SIZE]; | |||
| }; | |||
| } | |||
| @@ -1,429 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| AnalogFilter.cpp - Several analog filters (lowpass, highpass...) | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Copyright (C) 2010-2010 Mark McCurry | |||
| Author: Nasca Octavian Paul | |||
| Mark McCurry | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include <cstring> //memcpy | |||
| #include <cmath> | |||
| #include <cassert> | |||
| #include "../Misc/Util.h" | |||
| #include "AnalogFilter.h" | |||
| namespace zyncarla { | |||
| AnalogFilter::AnalogFilter(unsigned char Ftype, | |||
| float Ffreq, | |||
| float Fq, | |||
| unsigned char Fstages, | |||
| unsigned int srate, int bufsize) | |||
| :Filter(srate, bufsize), | |||
| type(Ftype), | |||
| stages(Fstages), | |||
| freq(Ffreq), | |||
| q(Fq), | |||
| gain(1.0), | |||
| abovenq(false), | |||
| oldabovenq(false) | |||
| { | |||
| for(int i = 0; i < 3; ++i) | |||
| coeff.c[i] = coeff.d[i] = oldCoeff.c[i] = oldCoeff.d[i] = 0.0f; | |||
| if(stages >= MAX_FILTER_STAGES) | |||
| stages = MAX_FILTER_STAGES; | |||
| cleanup(); | |||
| firsttime = false; | |||
| setfreq_and_q(Ffreq, Fq); | |||
| firsttime = true; | |||
| coeff.d[0] = 0; //this is not used | |||
| outgain = 1.0f; | |||
| } | |||
| AnalogFilter::~AnalogFilter() | |||
| {} | |||
| void AnalogFilter::cleanup() | |||
| { | |||
| for(int i = 0; i < MAX_FILTER_STAGES + 1; ++i) { | |||
| history[i].x1 = 0.0f; | |||
| history[i].x2 = 0.0f; | |||
| history[i].y1 = 0.0f; | |||
| history[i].y2 = 0.0f; | |||
| oldHistory[i] = history[i]; | |||
| } | |||
| needsinterpolation = false; | |||
| } | |||
| AnalogFilter::Coeff AnalogFilter::computeCoeff(int type, float cutoff, float q, | |||
| int stages, float gain, float fs, int &order) | |||
| { | |||
| AnalogFilter::Coeff coeff; | |||
| bool zerocoefs = false; //this is used if the freq is too high | |||
| const float samplerate_f = fs; | |||
| const float halfsamplerate_f = fs/2; | |||
| //do not allow frequencies bigger than samplerate/2 | |||
| float freq = cutoff; | |||
| if(freq > (halfsamplerate_f - 500.0f)) { | |||
| freq = halfsamplerate_f - 500.0f; | |||
| zerocoefs = true; | |||
| } | |||
| if(freq < 0.1f) | |||
| freq = 0.1f; | |||
| //do not allow bogus Q | |||
| if(q < 0.0f) | |||
| q = 0.0f; | |||
| float tmpq, tmpgain; | |||
| if(stages == 0) { | |||
| tmpq = q; | |||
| tmpgain = gain; | |||
| } else { | |||
| tmpq = (q > 1.0f) ? powf(q, 1.0f / (stages + 1)) : q; | |||
| tmpgain = powf(gain, 1.0f / (stages + 1)); | |||
| } | |||
| //Alias Terms | |||
| float *c = coeff.c; | |||
| float *d = coeff.d; | |||
| //General Constants | |||
| const float omega = 2 * PI * freq / samplerate_f; | |||
| const float sn = sinf(omega), cs = cosf(omega); | |||
| float alpha, beta; | |||
| //most of theese are implementations of | |||
| //the "Cookbook formulae for audio EQ" by Robert Bristow-Johnson | |||
| //The original location of the Cookbook is: | |||
| //http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt | |||
| float tmp; | |||
| float tgp1; | |||
| float tgm1; | |||
| switch(type) { | |||
| case 0: //LPF 1 pole | |||
| if(!zerocoefs) | |||
| tmp = expf(-2.0f * PI * freq / samplerate_f); | |||
| else | |||
| tmp = 0.0f; | |||
| c[0] = 1.0f - tmp; | |||
| c[1] = 0.0f; | |||
| c[2] = 0.0f; | |||
| d[1] = tmp; | |||
| d[2] = 0.0f; | |||
| order = 1; | |||
| break; | |||
| case 1: //HPF 1 pole | |||
| if(!zerocoefs) | |||
| tmp = expf(-2.0f * PI * freq / samplerate_f); | |||
| else | |||
| tmp = 0.0f; | |||
| c[0] = (1.0f + tmp) / 2.0f; | |||
| c[1] = -(1.0f + tmp) / 2.0f; | |||
| c[2] = 0.0f; | |||
| d[1] = tmp; | |||
| d[2] = 0.0f; | |||
| order = 1; | |||
| break; | |||
| case 2: //LPF 2 poles | |||
| if(!zerocoefs) { | |||
| alpha = sn / (2.0f * tmpq); | |||
| tmp = 1 + alpha; | |||
| c[1] = (1.0f - cs) / tmp; | |||
| c[0] = c[2] = c[1] / 2.0f; | |||
| d[1] = -2.0f * cs / tmp * -1.0f; | |||
| d[2] = (1.0f - alpha) / tmp * -1.0f; | |||
| } | |||
| else { | |||
| c[0] = 1.0f; | |||
| c[1] = c[2] = d[1] = d[2] = 0.0f; | |||
| } | |||
| order = 2; | |||
| break; | |||
| case 3: //HPF 2 poles | |||
| if(!zerocoefs) { | |||
| alpha = sn / (2.0f * tmpq); | |||
| tmp = 1 + alpha; | |||
| c[0] = (1.0f + cs) / 2.0f / tmp; | |||
| c[1] = -(1.0f + cs) / tmp; | |||
| c[2] = (1.0f + cs) / 2.0f / tmp; | |||
| d[1] = -2.0f * cs / tmp * -1.0f; | |||
| d[2] = (1.0f - alpha) / tmp * -1.0f; | |||
| } | |||
| else | |||
| c[0] = c[1] = c[2] = d[1] = d[2] = 0.0f; | |||
| order = 2; | |||
| break; | |||
| case 4: //BPF 2 poles | |||
| if(!zerocoefs) { | |||
| alpha = sn / (2.0f * tmpq); | |||
| tmp = 1.0f + alpha; | |||
| c[0] = alpha / tmp *sqrtf(tmpq + 1.0f); | |||
| c[1] = 0.0f; | |||
| c[2] = -alpha / tmp *sqrtf(tmpq + 1.0f); | |||
| d[1] = -2.0f * cs / tmp * -1.0f; | |||
| d[2] = (1.0f - alpha) / tmp * -1.0f; | |||
| } | |||
| else | |||
| c[0] = c[1] = c[2] = d[1] = d[2] = 0.0f; | |||
| order = 2; | |||
| break; | |||
| case 5: //NOTCH 2 poles | |||
| if(!zerocoefs) { | |||
| alpha = sn / (2.0f * sqrtf(tmpq)); | |||
| tmp = 1.0f + alpha; | |||
| c[0] = 1.0f / tmp; | |||
| c[1] = -2.0f * cs / tmp; | |||
| c[2] = 1.0f / tmp; | |||
| d[1] = -2.0f * cs / tmp * -1.0f; | |||
| d[2] = (1.0f - alpha) / tmp * -1.0f; | |||
| } | |||
| else { | |||
| c[0] = 1.0f; | |||
| c[1] = c[2] = d[1] = d[2] = 0.0f; | |||
| } | |||
| order = 2; | |||
| break; | |||
| case 6: //PEAK (2 poles) | |||
| if(!zerocoefs) { | |||
| tmpq *= 3.0f; | |||
| alpha = sn / (2.0f * tmpq); | |||
| tmp = 1.0f + alpha / tmpgain; | |||
| c[0] = (1.0f + alpha * tmpgain) / tmp; | |||
| c[1] = (-2.0f * cs) / tmp; | |||
| c[2] = (1.0f - alpha * tmpgain) / tmp; | |||
| d[1] = -2.0f * cs / tmp * -1.0f; | |||
| d[2] = (1.0f - alpha / tmpgain) / tmp * -1.0f; | |||
| } | |||
| else { | |||
| c[0] = 1.0f; | |||
| c[1] = c[2] = d[1] = d[2] = 0.0f; | |||
| } | |||
| order = 2; | |||
| break; | |||
| case 7: //Low Shelf - 2 poles | |||
| if(!zerocoefs) { | |||
| tmpq = sqrtf(tmpq); | |||
| beta = sqrtf(tmpgain) / tmpq; | |||
| tgp1 = tmpgain + 1.0f; | |||
| tgm1 = tmpgain - 1.0f; | |||
| tmp = tgp1 + tgm1 * cs + beta * sn; | |||
| c[0] = tmpgain * (tgp1 - tgm1 * cs + beta * sn) / tmp; | |||
| c[1] = 2.0f * tmpgain * (tgm1 - tgp1 * cs) / tmp; | |||
| c[2] = tmpgain * (tgp1 - tgm1 * cs - beta * sn) / tmp; | |||
| d[1] = -2.0f * (tgm1 + tgp1 * cs) / tmp * -1.0f; | |||
| d[2] = (tgp1 + tgm1 * cs - beta * sn) / tmp * -1.0f; | |||
| } | |||
| else { | |||
| c[0] = tmpgain; | |||
| c[1] = c[2] = d[1] = d[2] = 0.0f; | |||
| } | |||
| order = 2; | |||
| break; | |||
| case 8: //High Shelf - 2 poles | |||
| if(!zerocoefs) { | |||
| tmpq = sqrtf(tmpq); | |||
| beta = sqrtf(tmpgain) / tmpq; | |||
| tgp1 = tmpgain + 1.0f; | |||
| tgm1 = tmpgain - 1.0f; | |||
| tmp = tgp1 - tgm1 * cs + beta * sn; | |||
| c[0] = tmpgain * (tgp1 + tgm1 * cs + beta * sn) / tmp; | |||
| c[1] = -2.0f * tmpgain * (tgm1 + tgp1 * cs) / tmp; | |||
| c[2] = tmpgain * (tgp1 + tgm1 * cs - beta * sn) / tmp; | |||
| d[1] = 2.0f * (tgm1 - tgp1 * cs) / tmp * -1.0f; | |||
| d[2] = (tgp1 - tgm1 * cs - beta * sn) / tmp * -1.0f; | |||
| } | |||
| else { | |||
| c[0] = 1.0f; | |||
| c[1] = c[2] = d[1] = d[2] = 0.0f; | |||
| } | |||
| order = 2; | |||
| break; | |||
| default: //wrong type | |||
| assert(false && "wrong type for a filter"); | |||
| break; | |||
| } | |||
| return coeff; | |||
| } | |||
| void AnalogFilter::computefiltercoefs(void) | |||
| { | |||
| coeff = AnalogFilter::computeCoeff(type, freq, q, stages, gain, | |||
| samplerate_f, order); | |||
| } | |||
| void AnalogFilter::setfreq(float frequency) | |||
| { | |||
| if(frequency < 0.1f) | |||
| frequency = 0.1f; | |||
| float rap = freq / frequency; | |||
| if(rap < 1.0f) | |||
| rap = 1.0f / rap; | |||
| oldabovenq = abovenq; | |||
| abovenq = frequency > (halfsamplerate_f - 500.0f); | |||
| bool nyquistthresh = (abovenq ^ oldabovenq); | |||
| //if the frequency is changed fast, it needs interpolation | |||
| if((rap > 3.0f) || nyquistthresh) { //(now, filter and coeficients backup) | |||
| oldCoeff = coeff; | |||
| for(int i = 0; i < MAX_FILTER_STAGES + 1; ++i) | |||
| oldHistory[i] = history[i]; | |||
| if(!firsttime) | |||
| needsinterpolation = true; | |||
| } | |||
| freq = frequency; | |||
| computefiltercoefs(); | |||
| firsttime = false; | |||
| } | |||
| void AnalogFilter::setfreq_and_q(float frequency, float q_) | |||
| { | |||
| q = q_; | |||
| setfreq(frequency); | |||
| } | |||
| void AnalogFilter::setq(float q_) | |||
| { | |||
| q = q_; | |||
| computefiltercoefs(); | |||
| } | |||
| void AnalogFilter::settype(int type_) | |||
| { | |||
| type = type_; | |||
| computefiltercoefs(); | |||
| } | |||
| void AnalogFilter::setgain(float dBgain) | |||
| { | |||
| gain = dB2rap(dBgain); | |||
| computefiltercoefs(); | |||
| } | |||
| void AnalogFilter::setstages(int stages_) | |||
| { | |||
| if(stages_ >= MAX_FILTER_STAGES) | |||
| stages_ = MAX_FILTER_STAGES - 1; | |||
| if(stages_ != stages) { | |||
| stages = stages_; | |||
| cleanup(); | |||
| computefiltercoefs(); | |||
| } | |||
| } | |||
| inline void AnalogBiquadFilterA(const float coeff[5], float &src, float work[4]) | |||
| { | |||
| work[3] = src*coeff[0] | |||
| + work[0]*coeff[1] | |||
| + work[1]*coeff[2] | |||
| + work[2]*coeff[3] | |||
| + work[3]*coeff[4]; | |||
| work[1] = src; | |||
| src = work[3]; | |||
| } | |||
| inline void AnalogBiquadFilterB(const float coeff[5], float &src, float work[4]) | |||
| { | |||
| work[2] = src*coeff[0] | |||
| + work[1]*coeff[1] | |||
| + work[0]*coeff[2] | |||
| + work[3]*coeff[3] | |||
| + work[2]*coeff[4]; | |||
| work[0] = src; | |||
| src = work[2]; | |||
| } | |||
| void AnalogFilter::singlefilterout(float *smp, fstage &hist, | |||
| const Coeff &coeff) | |||
| { | |||
| assert((buffersize % 8) == 0); | |||
| if(order == 1) { //First order filter | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1] | |||
| + hist.y1 * coeff.d[1]; | |||
| hist.y1 = y0; | |||
| hist.x1 = smp[i]; | |||
| smp[i] = y0; | |||
| } | |||
| } else if(order == 2) {//Second order filter | |||
| const float coeff_[5] = {coeff.c[0], coeff.c[1], coeff.c[2], coeff.d[1], coeff.d[2]}; | |||
| float work[4] = {hist.x1, hist.x2, hist.y1, hist.y2}; | |||
| for(int i = 0; i < buffersize; i+=8) { | |||
| AnalogBiquadFilterA(coeff_, smp[i + 0], work); | |||
| AnalogBiquadFilterB(coeff_, smp[i + 1], work); | |||
| AnalogBiquadFilterA(coeff_, smp[i + 2], work); | |||
| AnalogBiquadFilterB(coeff_, smp[i + 3], work); | |||
| AnalogBiquadFilterA(coeff_, smp[i + 4], work); | |||
| AnalogBiquadFilterB(coeff_, smp[i + 5], work); | |||
| AnalogBiquadFilterA(coeff_, smp[i + 6], work); | |||
| AnalogBiquadFilterB(coeff_, smp[i + 7], work); | |||
| } | |||
| hist.x1 = work[0]; | |||
| hist.x2 = work[1]; | |||
| hist.y1 = work[2]; | |||
| hist.y2 = work[3]; | |||
| } | |||
| } | |||
| void AnalogFilter::filterout(float *smp) | |||
| { | |||
| for(int i = 0; i < stages + 1; ++i) | |||
| singlefilterout(smp, history[i], coeff); | |||
| if(needsinterpolation) { | |||
| //Merge Filter at old coeff with new coeff | |||
| float ismp[buffersize]; | |||
| memcpy(ismp, smp, bufferbytes); | |||
| for(int i = 0; i < stages + 1; ++i) | |||
| singlefilterout(ismp, oldHistory[i], oldCoeff); | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float x = (float)i / buffersize_f; | |||
| smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; | |||
| } | |||
| needsinterpolation = false; | |||
| } | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] *= outgain; | |||
| } | |||
| float AnalogFilter::H(float freq) | |||
| { | |||
| float fr = freq / samplerate_f * PI * 2.0f; | |||
| float x = coeff.c[0], y = 0.0f; | |||
| for(int n = 1; n < 3; ++n) { | |||
| x += cosf(n * fr) * coeff.c[n]; | |||
| y -= sinf(n * fr) * coeff.c[n]; | |||
| } | |||
| float h = x * x + y * y; | |||
| x = 1.0f; | |||
| y = 0.0f; | |||
| for(int n = 1; n < 3; ++n) { | |||
| x -= cosf(n * fr) * coeff.d[n]; | |||
| y += sinf(n * fr) * coeff.d[n]; | |||
| } | |||
| h = h / (x * x + y * y); | |||
| return powf(h, (stages + 1.0f) / 2.0f); | |||
| } | |||
| } | |||
| @@ -1,84 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| Analog Filter.h - Several analog filters (lowpass, highpass...) | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Copyright (C) 2010-2010 Mark McCurry | |||
| Author: Nasca Octavian Paul | |||
| Mark McCurry | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #ifndef ANALOG_FILTER_H | |||
| #define ANALOG_FILTER_H | |||
| #include "../globals.h" | |||
| #include "Filter.h" | |||
| namespace zyncarla { | |||
| /**Implementation of Several analog filters (lowpass, highpass...) | |||
| * Implemented with IIR filters | |||
| * Coefficients generated with "Cookbook formulae for audio EQ"*/ | |||
| class AnalogFilter:public Filter | |||
| { | |||
| public: | |||
| AnalogFilter(unsigned char Ftype, float Ffreq, float Fq, | |||
| unsigned char Fstages, unsigned int srate, int bufsize); | |||
| ~AnalogFilter(); | |||
| void filterout(float *smp); | |||
| void setfreq(float frequency); | |||
| void setfreq_and_q(float frequency, float q_); | |||
| void setq(float q_); | |||
| void settype(int type_); | |||
| void setgain(float dBgain); | |||
| void setstages(int stages_); | |||
| void cleanup(); | |||
| float H(float freq); //Obtains the response for a given frequency | |||
| struct Coeff { | |||
| float c[3], //Feed Forward | |||
| d[3]; //Feed Back | |||
| } coeff, oldCoeff; | |||
| static Coeff computeCoeff(int type, float cutoff, float q, int stages, | |||
| float gain, float fs, int &order); | |||
| private: | |||
| struct fstage { | |||
| float x1, x2; //Input History | |||
| float y1, y2; //Output History | |||
| } history[MAX_FILTER_STAGES + 1], oldHistory[MAX_FILTER_STAGES + 1]; | |||
| //old coeffs are used for interpolation when paremeters change quickly | |||
| //Apply IIR filter to Samples, with coefficients, and past history | |||
| void singlefilterout(float *smp, fstage &hist, const Coeff &coeff); | |||
| //Update coeff and order | |||
| void computefiltercoefs(void); | |||
| int type; //The type of the filter (LPF1,HPF1,LPF2,HPF2...) | |||
| int stages; //how many times the filter is applied (0->1,1->2,etc.) | |||
| float freq; //Frequency given in Hz | |||
| float q; //Q factor (resonance or Q factor) | |||
| float gain; //the gain of the filter (if are shelf/peak) filters | |||
| int order; //the order of the filter (number of poles) | |||
| bool needsinterpolation, //Interpolation between coeff changes | |||
| firsttime; //First Iteration of filter | |||
| bool abovenq, //if the frequency is above the nyquist | |||
| oldabovenq; //if the last time was above nyquist | |||
| //(used to see if it needs interpolation) | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -1,97 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| FFTwrapper.c - A wrapper for Fast Fourier Transforms | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include <cmath> | |||
| #include <cassert> | |||
| #include <cstring> | |||
| #include <pthread.h> | |||
| #include "FFTwrapper.h" | |||
| namespace zyncarla { | |||
| static pthread_mutex_t *mutex = NULL; | |||
| FFTwrapper::FFTwrapper(int fftsize_) | |||
| { | |||
| //first one will spawn the mutex (yeah this may be a race itself) | |||
| if(!mutex) { | |||
| mutex = new pthread_mutex_t; | |||
| pthread_mutex_init(mutex, NULL); | |||
| } | |||
| fftsize = fftsize_; | |||
| time = new fftw_real[fftsize]; | |||
| fft = new fftw_complex[fftsize + 1]; | |||
| pthread_mutex_lock(mutex); | |||
| planfftw = fftw_plan_dft_r2c_1d(fftsize, | |||
| time, | |||
| fft, | |||
| FFTW_ESTIMATE); | |||
| planfftw_inv = fftw_plan_dft_c2r_1d(fftsize, | |||
| fft, | |||
| time, | |||
| FFTW_ESTIMATE); | |||
| pthread_mutex_unlock(mutex); | |||
| } | |||
| FFTwrapper::~FFTwrapper() | |||
| { | |||
| pthread_mutex_lock(mutex); | |||
| fftw_destroy_plan(planfftw); | |||
| fftw_destroy_plan(planfftw_inv); | |||
| pthread_mutex_unlock(mutex); | |||
| delete [] time; | |||
| delete [] fft; | |||
| } | |||
| void FFTwrapper::smps2freqs(const float *smps, fft_t *freqs) | |||
| { | |||
| //Load data | |||
| for(int i = 0; i < fftsize; ++i) | |||
| time[i] = static_cast<double>(smps[i]); | |||
| //DFT | |||
| fftw_execute(planfftw); | |||
| //Grab data | |||
| memcpy((void *)freqs, (const void *)fft, fftsize * sizeof(double)); | |||
| } | |||
| void FFTwrapper::freqs2smps(const fft_t *freqs, float *smps) | |||
| { | |||
| //Load data | |||
| memcpy((void *)fft, (const void *)freqs, fftsize * sizeof(double)); | |||
| //clear unused freq channel | |||
| fft[fftsize / 2][0] = 0.0f; | |||
| fft[fftsize / 2][1] = 0.0f; | |||
| //IDFT | |||
| fftw_execute(planfftw_inv); | |||
| //Grab data | |||
| for(int i = 0; i < fftsize; ++i) | |||
| smps[i] = static_cast<float>(time[i]); | |||
| } | |||
| void FFT_cleanup() | |||
| { | |||
| fftw_cleanup(); | |||
| pthread_mutex_destroy(mutex); | |||
| delete mutex; | |||
| mutex = NULL; | |||
| } | |||
| } | |||
| @@ -1,66 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| FFTwrapper.h - A wrapper for Fast Fourier Transforms | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #ifndef FFT_WRAPPER_H | |||
| #define FFT_WRAPPER_H | |||
| #include <fftw3.h> | |||
| #include <complex> | |||
| #include "../globals.h" | |||
| namespace zyncarla { | |||
| /**A wrapper for the FFTW library (Fast Fourier Transforms)*/ | |||
| class FFTwrapper | |||
| { | |||
| public: | |||
| /**Constructor | |||
| * @param fftsize The size of samples to be fed to fftw*/ | |||
| FFTwrapper(int fftsize_); | |||
| /**Destructor*/ | |||
| ~FFTwrapper(); | |||
| /**Convert Samples to Frequencies using Fourier Transform | |||
| * @param smps Pointer to Samples to be converted; has length fftsize_ | |||
| * @param freqs Structure FFTFREQS which stores the frequencies*/ | |||
| void smps2freqs(const float *smps, fft_t *freqs); | |||
| void freqs2smps(const fft_t *freqs, float *smps); | |||
| private: | |||
| int fftsize; | |||
| fftw_real *time; | |||
| fftw_complex *fft; | |||
| fftw_plan planfftw, planfftw_inv; | |||
| }; | |||
| /* | |||
| * The "std::polar" template has no clear definition for the range of | |||
| * the input parameters, and some C++ standard library implementations | |||
| * don't accept negative amplitude among others. Define our own | |||
| * FFTpolar template, which works like we expect it to. | |||
| */ | |||
| template<class _Tp> | |||
| std::complex<_Tp> | |||
| FFTpolar(const _Tp& __rho, const _Tp& __theta = _Tp(0)) | |||
| { | |||
| _Tp __x = __rho * cos(__theta); | |||
| if (std::isnan(__x)) | |||
| __x = 0; | |||
| _Tp __y = __rho * sin(__theta); | |||
| if (std::isnan(__y)) | |||
| __y = 0; | |||
| return std::complex<_Tp>(__x, __y); | |||
| } | |||
| void FFT_cleanup(); | |||
| } | |||
| #endif | |||
| @@ -1,71 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| Filter.cpp - Filters, uses analog,formant,etc. filters | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include <cmath> | |||
| #include <cstdio> | |||
| #include <cassert> | |||
| #include "Filter.h" | |||
| #include "AnalogFilter.h" | |||
| #include "FormantFilter.h" | |||
| #include "SVFilter.h" | |||
| #include "../Params/FilterParams.h" | |||
| #include "../Misc/Allocator.h" | |||
| namespace zyncarla { | |||
| Filter::Filter(unsigned int srate, int bufsize) | |||
| : outgain(1.0f), | |||
| samplerate(srate), | |||
| buffersize(bufsize) | |||
| { | |||
| alias(); | |||
| } | |||
| Filter *Filter::generate(Allocator &memory, const FilterParams *pars, | |||
| unsigned int srate, int bufsize) | |||
| { | |||
| assert(srate != 0); | |||
| assert(bufsize != 0); | |||
| unsigned char Ftype = pars->Ptype; | |||
| unsigned char Fstages = pars->Pstages; | |||
| Filter *filter; | |||
| switch(pars->Pcategory) { | |||
| case 1: | |||
| filter = memory.alloc<FormantFilter>(pars, &memory, srate, bufsize); | |||
| break; | |||
| case 2: | |||
| filter = memory.alloc<SVFilter>(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize); | |||
| filter->outgain = dB2rap(pars->getgain()); | |||
| if(filter->outgain > 1.0f) | |||
| filter->outgain = sqrt(filter->outgain); | |||
| break; | |||
| default: | |||
| filter = memory.alloc<AnalogFilter>(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize); | |||
| if((Ftype >= 6) && (Ftype <= 8)) | |||
| filter->setgain(pars->getgain()); | |||
| else | |||
| filter->outgain = dB2rap(pars->getgain()); | |||
| break; | |||
| } | |||
| return filter; | |||
| } | |||
| float Filter::getrealfreq(float freqpitch) | |||
| { | |||
| return powf(2.0f, freqpitch + 9.96578428f); //log2(1000)=9.95748f | |||
| } | |||
| } | |||
| @@ -1,60 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| Filter.h - Filters, uses analog,formant,etc. filters | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #ifndef FILTER_H | |||
| #define FILTER_H | |||
| #include "../globals.h" | |||
| namespace zyncarla { | |||
| class Filter | |||
| { | |||
| public: | |||
| static float getrealfreq(float freqpitch); | |||
| static Filter *generate(Allocator &memory, const FilterParams *pars, | |||
| unsigned int srate, int bufsize); | |||
| Filter(unsigned int srate, int bufsize); | |||
| virtual ~Filter() {} | |||
| virtual void filterout(float *smp) = 0; | |||
| virtual void setfreq(float frequency) = 0; | |||
| virtual void setfreq_and_q(float frequency, float q_) = 0; | |||
| virtual void setq(float q_) = 0; | |||
| virtual void setgain(float dBgain) = 0; | |||
| protected: | |||
| float outgain; | |||
| // current setup | |||
| unsigned int samplerate; | |||
| int buffersize; | |||
| // alias for above terms | |||
| float samplerate_f; | |||
| float halfsamplerate_f; | |||
| float buffersize_f; | |||
| int bufferbytes; | |||
| inline void alias() | |||
| { | |||
| samplerate_f = samplerate; | |||
| halfsamplerate_f = samplerate_f / 2.0f; | |||
| buffersize_f = buffersize; | |||
| bufferbytes = buffersize * sizeof(float); | |||
| } | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -1,221 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| FormantFilter.cpp - formant filters | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include <cmath> | |||
| #include <cstdio> | |||
| #include "../Misc/Util.h" | |||
| #include "../Misc/Allocator.h" | |||
| #include "FormantFilter.h" | |||
| #include "AnalogFilter.h" | |||
| #include "../Params/FilterParams.h" | |||
| namespace zyncarla { | |||
| FormantFilter::FormantFilter(const FilterParams *pars, Allocator *alloc, unsigned int srate, int bufsize) | |||
| :Filter(srate, bufsize), memory(*alloc) | |||
| { | |||
| numformants = pars->Pnumformants; | |||
| for(int i = 0; i < numformants; ++i) | |||
| formant[i] = memory.alloc<AnalogFilter>(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages, srate, bufsize); | |||
| cleanup(); | |||
| for(int j = 0; j < FF_MAX_VOWELS; ++j) | |||
| for(int i = 0; i < numformants; ++i) { | |||
| formantpar[j][i].freq = pars->getformantfreq( | |||
| pars->Pvowels[j].formants[i].freq); | |||
| formantpar[j][i].amp = pars->getformantamp( | |||
| pars->Pvowels[j].formants[i].amp); | |||
| formantpar[j][i].q = pars->getformantq( | |||
| pars->Pvowels[j].formants[i].q); | |||
| } | |||
| for(int i = 0; i < FF_MAX_FORMANTS; ++i) | |||
| oldformantamp[i] = 1.0f; | |||
| for(int i = 0; i < numformants; ++i) { | |||
| currentformants[i].freq = 1000.0f; | |||
| currentformants[i].amp = 1.0f; | |||
| currentformants[i].q = 2.0f; | |||
| } | |||
| formantslowness = powf(1.0f - (pars->Pformantslowness / 128.0f), 3.0f); | |||
| sequencesize = pars->Psequencesize; | |||
| if(sequencesize == 0) | |||
| sequencesize = 1; | |||
| for(int k = 0; k < sequencesize; ++k) | |||
| sequence[k].nvowel = pars->Psequence[k].nvowel; | |||
| vowelclearness = powf(10.0f, (pars->Pvowelclearness - 32.0f) / 48.0f); | |||
| sequencestretch = powf(0.1f, (pars->Psequencestretch - 32.0f) / 48.0f); | |||
| if(pars->Psequencereversed) | |||
| sequencestretch *= -1.0f; | |||
| outgain = dB2rap(pars->getgain()); | |||
| oldinput = -1.0f; | |||
| Qfactor = pars->getq(); | |||
| oldQfactor = Qfactor; | |||
| firsttime = 1; | |||
| } | |||
| FormantFilter::~FormantFilter() | |||
| { | |||
| for(int i = 0; i < numformants; ++i) | |||
| memory.dealloc(formant[i]); | |||
| } | |||
| void FormantFilter::cleanup() | |||
| { | |||
| for(int i = 0; i < numformants; ++i) | |||
| formant[i]->cleanup(); | |||
| } | |||
| inline float log_2(float x) | |||
| { | |||
| return logf(x) / logf(2.0f); | |||
| } | |||
| void FormantFilter::setpos(float frequency) | |||
| { | |||
| int p1, p2; | |||
| //Convert form real freq[Hz] | |||
| const float input = log_2(frequency) - 9.96578428f; //log2(1000)=9.95748f. | |||
| if(firsttime != 0) | |||
| slowinput = input; | |||
| else | |||
| slowinput = slowinput | |||
| * (1.0f - formantslowness) + input * formantslowness; | |||
| if((fabsf(oldinput - input) < 0.001f) && (fabsf(slowinput - input) < 0.001f) | |||
| && (fabsf(Qfactor - oldQfactor) < 0.001f)) { | |||
| // oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente | |||
| firsttime = 0; | |||
| return; | |||
| } | |||
| else | |||
| oldinput = input; | |||
| float pos = input * sequencestretch; | |||
| pos -= floorf(pos); | |||
| F2I(pos * sequencesize, p2); | |||
| p1 = p2 - 1; | |||
| if(p1 < 0) | |||
| p1 += sequencesize; | |||
| pos = pos * sequencesize; | |||
| pos -= floorf(pos); | |||
| pos = | |||
| (atanf((pos * 2.0f | |||
| - 1.0f) | |||
| * vowelclearness) / atanf(vowelclearness) + 1.0f) * 0.5f; | |||
| p1 = sequence[p1].nvowel; | |||
| p2 = sequence[p2].nvowel; | |||
| if(firsttime != 0) { | |||
| for(int i = 0; i < numformants; ++i) { | |||
| currentformants[i].freq = | |||
| formantpar[p1][i].freq | |||
| * (1.0f - pos) + formantpar[p2][i].freq * pos; | |||
| currentformants[i].amp = | |||
| formantpar[p1][i].amp | |||
| * (1.0f - pos) + formantpar[p2][i].amp * pos; | |||
| currentformants[i].q = | |||
| formantpar[p1][i].q * (1.0f - pos) + formantpar[p2][i].q * pos; | |||
| formant[i]->setfreq_and_q(currentformants[i].freq, | |||
| currentformants[i].q * Qfactor); | |||
| oldformantamp[i] = currentformants[i].amp; | |||
| } | |||
| firsttime = 0; | |||
| } | |||
| else | |||
| for(int i = 0; i < numformants; ++i) { | |||
| currentformants[i].freq = | |||
| currentformants[i].freq * (1.0f - formantslowness) | |||
| + (formantpar[p1][i].freq | |||
| * (1.0f - pos) + formantpar[p2][i].freq * pos) | |||
| * formantslowness; | |||
| currentformants[i].amp = | |||
| currentformants[i].amp * (1.0f - formantslowness) | |||
| + (formantpar[p1][i].amp * (1.0f - pos) | |||
| + formantpar[p2][i].amp * pos) * formantslowness; | |||
| currentformants[i].q = currentformants[i].q | |||
| * (1.0f - formantslowness) | |||
| + (formantpar[p1][i].q * (1.0f - pos) | |||
| + formantpar[p2][i].q | |||
| * pos) * formantslowness; | |||
| formant[i]->setfreq_and_q(currentformants[i].freq, | |||
| currentformants[i].q * Qfactor); | |||
| } | |||
| oldQfactor = Qfactor; | |||
| } | |||
| void FormantFilter::setfreq(float frequency) | |||
| { | |||
| setpos(frequency); | |||
| } | |||
| void FormantFilter::setq(float q_) | |||
| { | |||
| Qfactor = q_; | |||
| for(int i = 0; i < numformants; ++i) | |||
| formant[i]->setq(Qfactor * currentformants[i].q); | |||
| } | |||
| void FormantFilter::setgain(float /*dBgain*/) | |||
| {} | |||
| void FormantFilter::setfreq_and_q(float frequency, float q_) | |||
| { | |||
| Qfactor = q_; | |||
| setpos(frequency); | |||
| } | |||
| void FormantFilter::filterout(float *smp) | |||
| { | |||
| float inbuffer[buffersize]; | |||
| memcpy(inbuffer, smp, bufferbytes); | |||
| memset(smp, 0, bufferbytes); | |||
| for(int j = 0; j < numformants; ++j) { | |||
| float tmpbuf[buffersize]; | |||
| for(int i = 0; i < buffersize; ++i) | |||
| tmpbuf[i] = inbuffer[i] * outgain; | |||
| formant[j]->filterout(tmpbuf); | |||
| if(ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j], currentformants[j].amp)) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] += tmpbuf[i] | |||
| * INTERPOLATE_AMPLITUDE(oldformantamp[j], | |||
| currentformants[j].amp, | |||
| i, | |||
| buffersize); | |||
| else | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] += tmpbuf[i] * currentformants[j].amp; | |||
| oldformantamp[j] = currentformants[j].amp; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,61 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| FormantFilter.h - formant filter | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #ifndef FORMANT_FILTER_H | |||
| #define FORMANT_FILTER_H | |||
| #include "../globals.h" | |||
| #include "Filter.h" | |||
| namespace zyncarla { | |||
| class FormantFilter:public Filter | |||
| { | |||
| public: | |||
| FormantFilter(const FilterParams *pars, Allocator *alloc, unsigned int srate, int bufsize); | |||
| ~FormantFilter(); | |||
| void filterout(float *smp); | |||
| void setfreq(float frequency); | |||
| void setfreq_and_q(float frequency, float q_); | |||
| void setq(float q_); | |||
| void setgain(float dBgain); | |||
| void cleanup(void); | |||
| private: | |||
| void setpos(float input); | |||
| class AnalogFilter * formant[FF_MAX_FORMANTS]; | |||
| struct { | |||
| float freq, amp, q; //frequency,amplitude,Q | |||
| } formantpar[FF_MAX_VOWELS][FF_MAX_FORMANTS], | |||
| currentformants[FF_MAX_FORMANTS]; | |||
| struct { | |||
| unsigned char nvowel; | |||
| } sequence [FF_MAX_SEQUENCE]; | |||
| float oldformantamp[FF_MAX_FORMANTS]; | |||
| int sequencesize, numformants, firsttime; | |||
| float oldinput, slowinput; | |||
| float Qfactor, formantslowness, oldQfactor; | |||
| float vowelclearness, sequencestretch; | |||
| Allocator &memory; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -1,235 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| SVFilter.cpp - Several state-variable filters | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include <cmath> | |||
| #include <cstdio> | |||
| #include <cstring> | |||
| #include <cassert> | |||
| #include "../Misc/Util.h" | |||
| #include "SVFilter.h" | |||
| #define errx(...) {} | |||
| #define warnx(...) {} | |||
| #ifndef errx | |||
| #include <err.h> | |||
| #endif | |||
| namespace zyncarla { | |||
| SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq, | |||
| unsigned char Fstages, unsigned int srate, int bufsize) | |||
| :Filter(srate, bufsize), | |||
| type(Ftype), | |||
| stages(Fstages), | |||
| freq(Ffreq), | |||
| q(Fq), | |||
| gain(1.0f), | |||
| needsinterpolation(false), | |||
| firsttime(true) | |||
| { | |||
| if(stages >= MAX_FILTER_STAGES) | |||
| stages = MAX_FILTER_STAGES; | |||
| outgain = 1.0f; | |||
| cleanup(); | |||
| setfreq_and_q(Ffreq, Fq); | |||
| } | |||
| SVFilter::~SVFilter() | |||
| {} | |||
| void SVFilter::cleanup() | |||
| { | |||
| for(int i = 0; i < MAX_FILTER_STAGES + 1; ++i) | |||
| st[i].low = st[i].high = st[i].band = st[i].notch = 0.0f; | |||
| oldabovenq = false; | |||
| abovenq = false; | |||
| } | |||
| SVFilter::response::response(float b0, float b1, float b2, | |||
| float a0, float a1 ,float a2) | |||
| { | |||
| a[0] = a0; | |||
| a[1] = a1; | |||
| a[2] = a2; | |||
| b[0] = b0; | |||
| b[1] = b1; | |||
| b[2] = b2; | |||
| } | |||
| SVFilter::response SVFilter::computeResponse(int type, | |||
| float freq, float pq, int stages, float gain, float fs) | |||
| { | |||
| typedef SVFilter::response res; | |||
| float f = freq / fs * 4.0; | |||
| if(f > 0.99999f) | |||
| f = 0.99999f; | |||
| float q = 1.0f - atanf(sqrtf(pq)) * 2.0f / PI; | |||
| q = powf(q, 1.0f / (stages + 1)); | |||
| float qrt = sqrtf(q); | |||
| float g = powf(gain, 1.0 / (stages + 1)); | |||
| if(type == 0) { //Low | |||
| return res{0, g*f*f*qrt, 0, | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| if(type == 1) {//High | |||
| //g *= qrt/(1+f*q); | |||
| g *= qrt; | |||
| return res{g, -2*g, g, | |||
| //1, (f*f-2*f*q-2)/(1+f*q), 1}; | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| if(type == 2) {//Band | |||
| g *= f*qrt; | |||
| return res{g, -g, 0, | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| if(type == 3 || true) {//Notch | |||
| g *= qrt; | |||
| return res{g, -2*g+g*f*f, g, | |||
| 1, (q*f+f*f-2), (1-q*f)}; | |||
| } | |||
| } | |||
| void SVFilter::computefiltercoefs(void) | |||
| { | |||
| par.f = freq / samplerate_f * 4.0f; | |||
| if(par.f > 0.99999f) | |||
| par.f = 0.99999f; | |||
| par.q = 1.0f - atanf(sqrtf(q)) * 2.0f / PI; | |||
| par.q = powf(par.q, 1.0f / (stages + 1)); | |||
| par.q_sqrt = sqrtf(par.q); | |||
| } | |||
| void SVFilter::setfreq(float frequency) | |||
| { | |||
| if(frequency < 0.1f) | |||
| frequency = 0.1f; | |||
| float rap = freq / frequency; | |||
| if(rap < 1.0f) | |||
| rap = 1.0f / rap; | |||
| oldabovenq = abovenq; | |||
| abovenq = frequency > (samplerate_f / 2 - 500.0f); | |||
| bool nyquistthresh = (abovenq ^ oldabovenq); | |||
| //if the frequency is changed fast, it needs interpolation | |||
| if((rap > 3.0f) || nyquistthresh) { //(now, filter and coefficients backup) | |||
| if(!firsttime) | |||
| needsinterpolation = true; | |||
| ipar = par; | |||
| } | |||
| freq = frequency; | |||
| computefiltercoefs(); | |||
| firsttime = false; | |||
| } | |||
| void SVFilter::setfreq_and_q(float frequency, float q_) | |||
| { | |||
| q = q_; | |||
| setfreq(frequency); | |||
| } | |||
| void SVFilter::setq(float q_) | |||
| { | |||
| q = q_; | |||
| computefiltercoefs(); | |||
| } | |||
| void SVFilter::settype(int type_) | |||
| { | |||
| type = type_; | |||
| computefiltercoefs(); | |||
| } | |||
| void SVFilter::setgain(float dBgain) | |||
| { | |||
| gain = dB2rap(dBgain); | |||
| computefiltercoefs(); | |||
| } | |||
| void SVFilter::setstages(int stages_) | |||
| { | |||
| if(stages_ >= MAX_FILTER_STAGES) | |||
| stages_ = MAX_FILTER_STAGES - 1; | |||
| stages = stages_; | |||
| cleanup(); | |||
| computefiltercoefs(); | |||
| } | |||
| void SVFilter::singlefilterout(float *smp, fstage &x, parameters &par) | |||
| { | |||
| float *out = NULL; | |||
| switch(type) { | |||
| case 0: | |||
| out = &x.low; | |||
| break; | |||
| case 1: | |||
| out = &x.high; | |||
| break; | |||
| case 2: | |||
| out = &x.band; | |||
| break; | |||
| case 3: | |||
| out = &x.notch; | |||
| break; | |||
| default: | |||
| out = &x.low; | |||
| warnx("Impossible SVFilter type encountered [%d]", type); | |||
| } | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| x.low = x.low + par.f * x.band; | |||
| x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band; | |||
| x.band = par.f * x.high + x.band; | |||
| x.notch = x.high + x.low; | |||
| smp[i] = *out; | |||
| } | |||
| } | |||
| // simplifying the responses | |||
| // xl = xl*z(-1) + pf*xb*z(-1) | |||
| // xh = pq1*x - xl - pq*xb*z(-1) | |||
| // xb = pf*xh + xb*z(-1) | |||
| // xn = xh + xl | |||
| // | |||
| // xl = pf*xb*z(-1)/(1-z(-1)) | |||
| // xb = pf*xh/(1-z(-1)) | |||
| // xl = pf*pfxh*z(-1)/(1-z(-1))^2 | |||
| void SVFilter::filterout(float *smp) | |||
| { | |||
| for(int i = 0; i < stages + 1; ++i) | |||
| singlefilterout(smp, st[i], par); | |||
| if(needsinterpolation) { | |||
| float ismp[buffersize]; | |||
| memcpy(ismp, smp, bufferbytes); | |||
| for(int i = 0; i < stages + 1; ++i) | |||
| singlefilterout(ismp, st[i], ipar); | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float x = i / buffersize_f; | |||
| smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; | |||
| } | |||
| needsinterpolation = false; | |||
| } | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] *= outgain; | |||
| } | |||
| } | |||
| @@ -1,74 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| SV Filter.h - Several state-variable filters | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #ifndef SV_FILTER_H | |||
| #define SV_FILTER_H | |||
| #include "../globals.h" | |||
| #include "Filter.h" | |||
| namespace zyncarla { | |||
| class SVFilter:public Filter | |||
| { | |||
| public: | |||
| SVFilter(unsigned char Ftype, | |||
| float Ffreq, | |||
| float Fq, | |||
| unsigned char Fstages, | |||
| unsigned int srate, int bufsize); | |||
| ~SVFilter(); | |||
| void filterout(float *smp); | |||
| void setfreq(float frequency); | |||
| void setfreq_and_q(float frequency, float q_); | |||
| void setq(float q_); | |||
| void settype(int type_); | |||
| void setgain(float dBgain); | |||
| void setstages(int stages_); | |||
| void cleanup(); | |||
| struct response { | |||
| response(float b0, float b1, float b2, | |||
| float a0, float a1 ,float a2); | |||
| float a[3]; | |||
| float b[3]; | |||
| }; | |||
| static response computeResponse(int type, | |||
| float freq, float pq, int stages, float g, float fs); | |||
| private: | |||
| struct fstage { | |||
| float low, high, band, notch; | |||
| } st[MAX_FILTER_STAGES + 1]; | |||
| struct parameters { | |||
| float f, q, q_sqrt; | |||
| } par, ipar; | |||
| void singlefilterout(float *smp, fstage &x, parameters &par); | |||
| void computefiltercoefs(void); | |||
| int type; // The type of the filter (LPF1,HPF1,LPF2,HPF2...) | |||
| int stages; // how many times the filter is applied (0->1,1->2,etc.) | |||
| float freq; // Frequency given in Hz | |||
| float q; // Q factor (resonance or Q factor) | |||
| float gain; // the gain of the filter (if are shelf/peak) filters | |||
| bool abovenq, //if the frequency is above the nyquist | |||
| oldabovenq; | |||
| bool needsinterpolation, firsttime; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -1,202 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| Unison.cpp - Unison effect (multivoice chorus) | |||
| Copyright (C) 2002-2009 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include <cmath> | |||
| #include <cstring> | |||
| #include "../Misc/Allocator.h" | |||
| #include "Unison.h" | |||
| #include "globals.h" | |||
| #define errx(...) {} | |||
| #define warnx(...) {} | |||
| #ifndef errx | |||
| #include <err.h> | |||
| #endif | |||
| namespace zyncarla { | |||
| Unison::Unison(Allocator *alloc_, int update_period_samples_, float max_delay_sec_, float srate_f) | |||
| :unison_size(0), | |||
| base_freq(1.0f), | |||
| uv(NULL), | |||
| update_period_samples(update_period_samples_), | |||
| update_period_sample_k(0), | |||
| max_delay((int)(srate_f * max_delay_sec_) + 1), | |||
| delay_k(0), | |||
| first_time(false), | |||
| delay_buffer(NULL), | |||
| unison_amplitude_samples(0.0f), | |||
| unison_bandwidth_cents(10.0f), | |||
| samplerate_f(srate_f), | |||
| alloc(*alloc_) | |||
| { | |||
| if(max_delay < 10) | |||
| max_delay = 10; | |||
| delay_buffer = alloc.valloc<float>(max_delay); | |||
| memset(delay_buffer, 0, max_delay * sizeof(float)); | |||
| setSize(1); | |||
| } | |||
| Unison::~Unison() { | |||
| alloc.devalloc(delay_buffer); | |||
| alloc.devalloc(uv); | |||
| } | |||
| void Unison::setSize(int new_size) | |||
| { | |||
| if(new_size < 1) | |||
| new_size = 1; | |||
| unison_size = new_size; | |||
| alloc.devalloc(uv); | |||
| uv = alloc.valloc<UnisonVoice>(unison_size); | |||
| first_time = true; | |||
| updateParameters(); | |||
| } | |||
| void Unison::setBaseFrequency(float freq) | |||
| { | |||
| base_freq = freq; | |||
| updateParameters(); | |||
| } | |||
| void Unison::setBandwidth(float bandwidth) | |||
| { | |||
| if(bandwidth < 0) | |||
| bandwidth = 0.0f; | |||
| if(bandwidth > 1200.0f) | |||
| bandwidth = 1200.0f; | |||
| /* If the bandwidth is too small, the audio may cancel itself out | |||
| * (due to the sign change of the outputs) | |||
| * TODO figure out the acceptable lower bound and codify it | |||
| */ | |||
| unison_bandwidth_cents = bandwidth; | |||
| updateParameters(); | |||
| } | |||
| void Unison::updateParameters(void) | |||
| { | |||
| if(!uv) | |||
| return; | |||
| float increments_per_second = samplerate_f | |||
| / (float) update_period_samples; | |||
| // printf("#%g, %g\n",increments_per_second,base_freq); | |||
| for(int i = 0; i < unison_size; ++i) { | |||
| float base = powf(UNISON_FREQ_SPAN, SYNTH_T::numRandom() * 2.0f - 1.0f); | |||
| uv[i].relative_amplitude = base; | |||
| float period = base / base_freq; | |||
| float m = 4.0f / (period * increments_per_second); | |||
| if(SYNTH_T::numRandom() < 0.5f) | |||
| m = -m; | |||
| uv[i].step = m; | |||
| // printf("%g %g\n",uv[i].relative_amplitude,period); | |||
| } | |||
| float max_speed = powf(2.0f, unison_bandwidth_cents / 1200.0f); | |||
| unison_amplitude_samples = 0.125f * (max_speed - 1.0f) | |||
| * samplerate_f / base_freq; | |||
| //If functions exceed this limit, they should have requested a bigguer delay | |||
| //and thus are buggy | |||
| if(unison_amplitude_samples >= max_delay - 1) { | |||
| warnx("BUG: Unison amplitude samples too big"); | |||
| warnx("Unision max_delay should be larger"); | |||
| unison_amplitude_samples = max_delay - 2; | |||
| } | |||
| updateUnisonData(); | |||
| } | |||
| void Unison::process(int bufsize, float *inbuf, float *outbuf) | |||
| { | |||
| if(!uv) | |||
| return; | |||
| if(!outbuf) | |||
| outbuf = inbuf; | |||
| float volume = 1.0f / sqrtf(unison_size); | |||
| float xpos_step = 1.0f / (float) update_period_samples; | |||
| float xpos = (float) update_period_sample_k * xpos_step; | |||
| for(int i = 0; i < bufsize; ++i) { | |||
| if(update_period_sample_k++ >= update_period_samples) { | |||
| updateUnisonData(); | |||
| update_period_sample_k = 0; | |||
| xpos = 0.0f; | |||
| } | |||
| xpos += xpos_step; | |||
| float in = inbuf[i], out = 0.0f; | |||
| float sign = 1.0f; | |||
| for(int k = 0; k < unison_size; ++k) { | |||
| float vpos = uv[k].realpos1 * (1.0f - xpos) + uv[k].realpos2 * xpos; //optimize | |||
| float pos = (float)(delay_k + max_delay) - vpos - 1.0f; | |||
| int posi; | |||
| F2I(pos, posi); //optimize! | |||
| int posi_next = posi + 1; | |||
| if(posi >= max_delay) | |||
| posi -= max_delay; | |||
| if(posi_next >= max_delay) | |||
| posi_next -= max_delay; | |||
| float posf = pos - floorf(pos); | |||
| out += ((1.0f - posf) * delay_buffer[posi] + posf | |||
| * delay_buffer[posi_next]) * sign; | |||
| sign = -sign; | |||
| } | |||
| outbuf[i] = out * volume; | |||
| // printf("%d %g\n",i,outbuf[i]); | |||
| delay_buffer[delay_k] = in; | |||
| delay_k = (++delay_k < max_delay) ? delay_k : 0; | |||
| } | |||
| } | |||
| void Unison::updateUnisonData() | |||
| { | |||
| if(!uv) | |||
| return; | |||
| for(int k = 0; k < unison_size; ++k) { | |||
| float pos = uv[k].position; | |||
| float step = uv[k].step; | |||
| pos += step; | |||
| if(pos <= -1.0f) { | |||
| pos = -1.0f; | |||
| step = -step; | |||
| } | |||
| else | |||
| if(pos >= 1.0f) { | |||
| pos = 1.0f; | |||
| step = -step; | |||
| } | |||
| float vibratto_val = (pos - 0.333333333f * pos * pos * pos) * 1.5f; //make the vibratto lfo smoother | |||
| //Relative amplitude is utilized, so the delay may be larger than the | |||
| //whole buffer, if the buffer is too small, this indicates a buggy call | |||
| //to Unison() | |||
| float newval = 1.0f + 0.5f | |||
| * (vibratto_val + 1.0f) * unison_amplitude_samples | |||
| * uv[k].relative_amplitude; | |||
| if(first_time) | |||
| uv[k].realpos1 = uv[k].realpos2 = newval; | |||
| else { | |||
| uv[k].realpos1 = uv[k].realpos2; | |||
| uv[k].realpos2 = newval; | |||
| } | |||
| uv[k].position = pos; | |||
| uv[k].step = step; | |||
| } | |||
| first_time = false; | |||
| } | |||
| } | |||
| @@ -1,76 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| Unison.h - Unison effect (multivoice chorus) | |||
| Copyright (C) 2002-2009 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #ifndef UNISON_H | |||
| #define UNISON_H | |||
| #include "../Misc/Util.h" | |||
| //how much the unison frequencies varies (always >= 1.0) | |||
| #define UNISON_FREQ_SPAN 2.0f | |||
| namespace zyncarla { | |||
| class Allocator; | |||
| class Unison | |||
| { | |||
| public: | |||
| Unison(Allocator *alloc_, int update_period_samples_, float max_delay_sec_, float srate_f); | |||
| ~Unison(); | |||
| void setSize(int new_size); | |||
| void setBaseFrequency(float freq); | |||
| void setBandwidth(float bandwidth_cents); | |||
| void process(int bufsize, float *inbuf, float *outbuf = NULL); | |||
| private: | |||
| void updateParameters(void); | |||
| void updateUnisonData(void); | |||
| int unison_size; | |||
| float base_freq; | |||
| struct UnisonVoice { | |||
| float step; //base LFO | |||
| float position; | |||
| float realpos1; //the position regarding samples | |||
| float realpos2; | |||
| float relative_amplitude; | |||
| float lin_fpos; | |||
| float lin_ffreq; | |||
| UnisonVoice() { | |||
| position = RND * 1.8f - 0.9f; | |||
| realpos1 = 0.0f; | |||
| realpos2 = 0.0f; | |||
| step = 0.0f; | |||
| relative_amplitude = 1.0f; | |||
| } | |||
| } *uv; | |||
| int update_period_samples; | |||
| int update_period_sample_k; | |||
| int max_delay, delay_k; | |||
| bool first_time; | |||
| float *delay_buffer; | |||
| float unison_amplitude_samples; | |||
| float unison_bandwidth_cents; | |||
| // current setup | |||
| float samplerate_f; | |||
| Allocator &alloc; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -1,272 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| Alienwah.cpp - "AlienWah" effect | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #include <cmath> | |||
| #include <rtosc/port-sugar.h> | |||
| #include <rtosc/ports.h> | |||
| #include "../Misc/Allocator.h" | |||
| #include "Alienwah.h" | |||
| namespace zyncarla { | |||
| using std::complex; | |||
| #define rObject Alienwah | |||
| #define rBegin [](const char *msg, rtosc::RtData &d) { | |||
| #define rEnd } | |||
| rtosc::Ports Alienwah::ports = { | |||
| {"preset::i", rProp(parameter) | |||
| rOptions(wah 1, wah 2, wah 3, wah 4) | |||
| rDoc("Instrument Presets"), 0, | |||
| rBegin; | |||
| rObject *o = (rObject*)d.obj; | |||
| if(rtosc_narguments(msg)) | |||
| o->setpreset(rtosc_argument(msg, 0).i); | |||
| else | |||
| d.reply(d.loc, "i", o->Ppreset); | |||
| rEnd}, | |||
| rEffParVol(rDefault(127), rPresetsAt(3, 93)), | |||
| rEffParPan(), | |||
| rEffPar(Pfreq, 2, rShort("freq") rPresets(70, 73, 63, 25), | |||
| "Effect Frequency"), | |||
| rEffPar(Pfreqrnd, 3, rShort("rand"), rPreset(1, 106) rDefault(0), | |||
| "Frequency Randomness"), | |||
| rEffPar(PLFOtype, 4, rShort("shape"), | |||
| rOptions(sine, triangle), rPresets(sine, sine, triangle, triangle), | |||
| "LFO Shape"), | |||
| rEffPar(PStereo, 5, rShort("stereo"), rPresets(62, 101, 100, 66), | |||
| "Stereo Mode"), | |||
| rEffPar(Pdepth, 6, rShort("depth"), rPresets(60, 60, 112, 101), | |||
| "LFO Depth"), | |||
| rEffPar(Pfeedback, 7, rShort("fb"), rPreset(3, 11), rDefault(105), | |||
| "Feedback"), | |||
| rEffPar(Pdelay, 8, rLinear(1,100), rPresets(25, 17, 31, 47), | |||
| rShort("delay"), "Delay"), | |||
| rEffPar(Plrcross, 9, rShort("l/r"), rDefault(0), "Left/Right Crossover"), | |||
| rEffPar(Pphase, 10, rShort("phase"), rDefault(64), rPreset(2, 42), | |||
| rPreset(3, 86), "Phase"), | |||
| }; | |||
| #undef rBegin | |||
| #undef rEnd | |||
| #undef rObject | |||
| Alienwah::Alienwah(EffectParams pars) | |||
| :Effect(pars), | |||
| lfo(pars.srate, pars.bufsize), | |||
| oldl(NULL), | |||
| oldr(NULL) | |||
| { | |||
| setpreset(Ppreset); | |||
| cleanup(); | |||
| oldclfol = complex<float>(fb, 0.0f); | |||
| oldclfor = complex<float>(fb, 0.0f); | |||
| } | |||
| Alienwah::~Alienwah() | |||
| { | |||
| memory.devalloc(oldl); | |||
| memory.devalloc(oldr); | |||
| } | |||
| //Apply the effect | |||
| void Alienwah::out(const Stereo<float *> &smp) | |||
| { | |||
| float lfol, lfor; //Left/Right LFOs | |||
| complex<float> clfol, clfor; | |||
| /**\todo Rework, as optimization can be used when the new complex type is | |||
| * utilized. | |||
| * Before all calculations needed to be done with individual float, | |||
| * but now they can be done together*/ | |||
| lfo.effectlfoout(&lfol, &lfor); | |||
| lfol *= depth * PI * 2.0f; | |||
| lfor *= depth * PI * 2.0f; | |||
| clfol = complex<float>(cosf(lfol + phase) * fb, sinf(lfol + phase) * fb); //rework | |||
| clfor = complex<float>(cosf(lfor + phase) * fb, sinf(lfor + phase) * fb); //rework | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float x = ((float) i) / buffersize_f; | |||
| float x1 = 1.0f - x; | |||
| //left | |||
| complex<float> tmp = clfol * x + oldclfol * x1; | |||
| complex<float> out = tmp * oldl[oldk]; | |||
| out += (1 - fabs(fb)) * smp.l[i] * pangainL; | |||
| oldl[oldk] = out; | |||
| float l = out.real() * 10.0f * (fb + 0.1f); | |||
| //right | |||
| tmp = clfor * x + oldclfor * x1; | |||
| out = tmp * oldr[oldk]; | |||
| out += (1 - fabs(fb)) * smp.r[i] * pangainR; | |||
| oldr[oldk] = out; | |||
| float r = out.real() * 10.0f * (fb + 0.1f); | |||
| if(++oldk >= Pdelay) | |||
| oldk = 0; | |||
| //LRcross | |||
| efxoutl[i] = l * (1.0f - lrcross) + r * lrcross; | |||
| efxoutr[i] = r * (1.0f - lrcross) + l * lrcross; | |||
| } | |||
| oldclfol = clfol; | |||
| oldclfor = clfor; | |||
| } | |||
| //Cleanup the effect | |||
| void Alienwah::cleanup(void) | |||
| { | |||
| for(int i = 0; i < Pdelay; ++i) { | |||
| oldl[i] = complex<float>(0.0f, 0.0f); | |||
| oldr[i] = complex<float>(0.0f, 0.0f); | |||
| } | |||
| oldk = 0; | |||
| } | |||
| //Parameter control | |||
| void Alienwah::setdepth(unsigned char _Pdepth) | |||
| { | |||
| Pdepth = _Pdepth; | |||
| depth = Pdepth / 127.0f; | |||
| } | |||
| void Alienwah::setfb(unsigned char _Pfb) | |||
| { | |||
| Pfb = _Pfb; | |||
| fb = fabs((Pfb - 64.0f) / 64.1f); | |||
| fb = sqrtf(fb); | |||
| if(fb < 0.4f) | |||
| fb = 0.4f; | |||
| if(Pfb < 64) | |||
| fb = -fb; | |||
| } | |||
| void Alienwah::setvolume(unsigned char _Pvolume) | |||
| { | |||
| Pvolume = _Pvolume; | |||
| outvolume = Pvolume / 127.0f; | |||
| if(insertion == 0) | |||
| volume = 1.0f; | |||
| else | |||
| volume = outvolume; | |||
| } | |||
| void Alienwah::setphase(unsigned char _Pphase) | |||
| { | |||
| Pphase = _Pphase; | |||
| phase = (Pphase - 64.0f) / 64.0f * PI; | |||
| } | |||
| void Alienwah::setdelay(unsigned char _Pdelay) | |||
| { | |||
| memory.devalloc(oldl); | |||
| memory.devalloc(oldr); | |||
| Pdelay = limit<int>(_Pdelay, 1, MAX_ALIENWAH_DELAY); | |||
| oldl = memory.valloc<complex<float>>(Pdelay); | |||
| oldr = memory.valloc<complex<float>>(Pdelay); | |||
| cleanup(); | |||
| } | |||
| void Alienwah::setpreset(unsigned char npreset) | |||
| { | |||
| const int PRESET_SIZE = 11; | |||
| const int NUM_PRESETS = 4; | |||
| unsigned char presets[NUM_PRESETS][PRESET_SIZE] = { | |||
| //AlienWah1 | |||
| {127, 64, 70, 0, 0, 62, 60, 105, 25, 0, 64}, | |||
| //AlienWah2 | |||
| {127, 64, 73, 106, 0, 101, 60, 105, 17, 0, 64}, | |||
| //AlienWah3 | |||
| {127, 64, 63, 0, 1, 100, 112, 105, 31, 0, 42}, | |||
| //AlienWah4 | |||
| {93, 64, 25, 0, 1, 66, 101, 11, 47, 0, 86} | |||
| }; | |||
| if(npreset >= NUM_PRESETS) | |||
| npreset = NUM_PRESETS - 1; | |||
| for(int n = 0; n < PRESET_SIZE; ++n) | |||
| changepar(n, presets[npreset][n]); | |||
| if(insertion == 0) | |||
| changepar(0, presets[npreset][0] / 2); //lower the volume if this is system effect | |||
| Ppreset = npreset; | |||
| } | |||
| void Alienwah::changepar(int npar, unsigned char value) | |||
| { | |||
| switch(npar) { | |||
| case 0: | |||
| setvolume(value); | |||
| break; | |||
| case 1: | |||
| setpanning(value); | |||
| break; | |||
| case 2: | |||
| lfo.Pfreq = value; | |||
| lfo.updateparams(); | |||
| break; | |||
| case 3: | |||
| lfo.Prandomness = value; | |||
| lfo.updateparams(); | |||
| break; | |||
| case 4: | |||
| lfo.PLFOtype = value; | |||
| lfo.updateparams(); | |||
| break; | |||
| case 5: | |||
| lfo.Pstereo = value; | |||
| lfo.updateparams(); | |||
| break; | |||
| case 6: | |||
| setdepth(value); | |||
| break; | |||
| case 7: | |||
| setfb(value); | |||
| break; | |||
| case 8: | |||
| setdelay(value); | |||
| break; | |||
| case 9: | |||
| setlrcross(value); | |||
| break; | |||
| case 10: | |||
| setphase(value); | |||
| break; | |||
| } | |||
| } | |||
| unsigned char Alienwah::getpar(int npar) const | |||
| { | |||
| switch(npar) { | |||
| case 0: return Pvolume; | |||
| case 1: return Ppanning; | |||
| case 2: return lfo.Pfreq; | |||
| case 3: return lfo.Prandomness; | |||
| case 4: return lfo.PLFOtype; | |||
| case 5: return lfo.Pstereo; | |||
| case 6: return Pdepth; | |||
| case 7: return Pfb; | |||
| case 8: return Pdelay; | |||
| case 9: return Plrcross; | |||
| case 10: return Pphase; | |||
| default: return 0; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,65 +0,0 @@ | |||
| /* | |||
| ZynAddSubFX - a software synthesizer | |||
| Alienwah.h - "AlienWah" effect | |||
| Copyright (C) 2002-2005 Nasca Octavian Paul | |||
| Author: Nasca Octavian Paul | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| */ | |||
| #ifndef ALIENWAH_H | |||
| #define ALIENWAH_H | |||
| #include "Effect.h" | |||
| #include "EffectLFO.h" | |||
| #include <complex> | |||
| #define MAX_ALIENWAH_DELAY 100 | |||
| namespace zyncarla { | |||
| /**"AlienWah" Effect*/ | |||
| class Alienwah:public Effect | |||
| { | |||
| public: | |||
| Alienwah(EffectParams pars); | |||
| ~Alienwah(); | |||
| void out(const Stereo<float *> &smp); | |||
| void setpreset(unsigned char npreset); | |||
| void changepar(int npar, unsigned char value); | |||
| unsigned char getpar(int npar) const; | |||
| void cleanup(void); | |||
| static rtosc::Ports ports; | |||
| private: | |||
| //Alienwah Parameters | |||
| EffectLFO lfo; //lfo-ul Alienwah | |||
| unsigned char Pvolume; | |||
| unsigned char Pdepth; //the depth of the Alienwah | |||
| unsigned char Pfb; //feedback | |||
| unsigned char Pdelay; | |||
| unsigned char Pphase; | |||
| //Control Parameters | |||
| void setvolume(unsigned char _Pvolume); | |||
| void setdepth(unsigned char _Pdepth); | |||
| void setfb(unsigned char _Pfb); | |||
| void setdelay(unsigned char _Pdelay); | |||
| void setphase(unsigned char _Pphase); | |||
| //Internal Values | |||
| float fb, depth, phase; | |||
| std::complex<float> *oldl, *oldr; | |||
| std::complex<float> oldclfol, oldclfor; | |||
| int oldk; | |||
| }; | |||
| } | |||
| #endif | |||