| @@ -496,6 +496,11 @@ ifeq ($(HAVE_PM_DEPS),true) | |||
| @echo "ProjectM: $(ANS_YES)" | |||
| else | |||
| @echo "ProjectM: $(ANS_NO) $(mS)ProjectM missing$(mE)" | |||
| endif | |||
| ifneq ($(WIN32),true) | |||
| @echo "Carla-Rack: $(ANS_YES)" | |||
| else | |||
| @echo "Carla-Rack: $(ANS_NO) $(mS)Not available for Windows$(mE)" | |||
| endif | |||
| @echo "DPF Stuff: $(ANS_YES)" | |||
| ifeq ($(HAVE_JUCE),true) | |||
| @@ -104,10 +104,20 @@ OBJS += \ | |||
| # distrho-stereoenhancer.cpp.o | |||
| OBJS += \ | |||
| distrho-groovejuice.cpp.o \ | |||
| distrho-powerjuice.cpp.o \ | |||
| distrho-segmentjuice.cpp.o \ | |||
| distrho-vectorjuice.cpp.o \ | |||
| distrho-wobblejuice.cpp.o | |||
| # distrho-powerjuice.cpp.o | |||
| OBJS += \ | |||
| distrho-zamcomp.cpp.o \ | |||
| distrho-zamcompx2.cpp.o \ | |||
| distrho-zameq2.cpp.o \ | |||
| distrho-zamsynth.cpp.o \ | |||
| distrho-zamtube.cpp.o \ | |||
| distrho-zamulticomp.cpp.o \ | |||
| distrho-zamulticompx2.cpp.o | |||
| ifeq ($(HAVE_JUCE),true) | |||
| # -------------------------------------------------------------- | |||
| @@ -254,6 +264,9 @@ distrho-pingpongpan.cpp.o: distrho-pingpongpan.cpp pingpongpan/*.cpp pingpongpan | |||
| distrho-stereoenhancer.cpp.o: distrho-stereoenhancer.cpp stereoenhancer/*.cpp stereoenhancer/*.h stereoenhancer/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Istereoenhancer -DDISTRHO_NAMESPACE=DISTRHO_StereoEnhancer -c -o $@ | |||
| distrho-groovejuice.cpp.o: distrho-groovejuice.cpp groovejuice/*.cpp groovejuice/*.h groovejuice/*.hpp groovejuice/*.hxx ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Igroovejuice -DDISTRHO_NAMESPACE=DISTRHO_GrooveJuice -c -o $@ | |||
| distrho-powerjuice.cpp.o: distrho-powerjuice.cpp powerjuice/*.cpp powerjuice/*.h powerjuice/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Ipowerjuice -DDISTRHO_NAMESPACE=DISTRHO_PowerJuice -c -o $@ | |||
| @@ -266,6 +279,27 @@ distrho-vectorjuice.cpp.o: distrho-vectorjuice.cpp vectorjuice/*.cpp vectorjuice | |||
| distrho-wobblejuice.cpp.o: distrho-wobblejuice.cpp wobblejuice/*.cpp wobblejuice/*.h wobblejuice/*.hpp wobblejuice/*.hxx ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Iwobblejuice -DDISTRHO_NAMESPACE=DISTRHO_WobbleJuice -c -o $@ | |||
| distrho-zamcomp.cpp.o: distrho-zamcomp.cpp zamcomp/*.cpp zamcomp/*.h zamcomp/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Izamcomp -DDISTRHO_NAMESPACE=DISTRHO_ZamComp -c -o $@ | |||
| distrho-zamcompx2.cpp.o: distrho-zamcompx2.cpp zamcompx2/*.cpp zamcompx2/*.h zamcompx2/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Izamcompx2 -DDISTRHO_NAMESPACE=DISTRHO_ZamCompX2 -c -o $@ | |||
| distrho-zameq2.cpp.o: distrho-zameq2.cpp zameq2/*.cpp zameq2/*.h zameq2/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Izameq2 -DDISTRHO_NAMESPACE=DISTRHO_ZamEQ2 -c -o $@ | |||
| distrho-zamsynth.cpp.o: distrho-zamsynth.cpp zamsynth/*.cpp zamsynth/*.h zamsynth/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Izamsynth -DDISTRHO_NAMESPACE=DISTRHO_ZamSynth -c -o $@ | |||
| distrho-zamtube.cpp.o: distrho-zamtube.cpp zamtube/*.cpp zamtube/*.h zamtube/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Izamtube -DDISTRHO_NAMESPACE=DISTRHO_ZamTube -c -o $@ | |||
| distrho-zamulticomp.cpp.o: distrho-zamulticomp.cpp zamulticomp/*.cpp zamulticomp/*.h zamulticomp/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Izamulticomp -DDISTRHO_NAMESPACE=DISTRHO_ZaMultiComp -c -o $@ | |||
| distrho-zamulticompx2.cpp.o: distrho-zamulticompx2.cpp zamulticompx2/*.cpp zamulticompx2/*.h zamulticompx2/*.hpp ../distrho/* $(CXXDEPS) | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -I../dgl -Izamulticompx2 -DDISTRHO_NAMESPACE=DISTRHO_ZaMultiCompX2 -c -o $@ | |||
| juce-patchbay.cpp.o: juce-patchbay.cpp | |||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| @@ -48,6 +48,14 @@ extern void carla_register_native_plugin_segmentjuice(); | |||
| extern void carla_register_native_plugin_vectorjuice(); | |||
| extern void carla_register_native_plugin_wobblejuice(); | |||
| extern void carla_register_native_plugin_zamcomp(); | |||
| extern void carla_register_native_plugin_zamcompx2(); | |||
| extern void carla_register_native_plugin_zameq2(); | |||
| extern void carla_register_native_plugin_zamsynth(); | |||
| extern void carla_register_native_plugin_zamtube(); | |||
| extern void carla_register_native_plugin_zamulticomp(); | |||
| extern void carla_register_native_plugin_zamulticompx2(); | |||
| #ifdef HAVE_JUCE | |||
| // JUCE based plugins | |||
| extern void carla_register_native_plugin_jucepatchbay(); | |||
| @@ -112,6 +120,14 @@ void carla_register_all_plugins() | |||
| carla_register_native_plugin_vectorjuice(); | |||
| carla_register_native_plugin_wobblejuice(); | |||
| carla_register_native_plugin_zamcomp(); | |||
| carla_register_native_plugin_zamcompx2(); | |||
| carla_register_native_plugin_zameq2(); | |||
| carla_register_native_plugin_zamsynth(); | |||
| carla_register_native_plugin_zamtube(); | |||
| carla_register_native_plugin_zamulticomp(); | |||
| carla_register_native_plugin_zamulticompx2(); | |||
| #ifdef HAVE_JUCE | |||
| // JUCE based plugins | |||
| carla_register_native_plugin_jucepatchbay(); | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "groovejuice/GrooveJuiceArtwork.cpp" | |||
| #include "groovejuice/GrooveJuicePlugin.cpp" | |||
| #include "groovejuice/GrooveJuiceUI.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor groovejuiceDesc = { | |||
| /* category */ PLUGIN_CATEGORY_SYNTH, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_IS_SYNTH|PLUGIN_HAS_UI|PLUGIN_USES_TIME|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ GrooveJuicePlugin::paramCount-12, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "groovejuice", | |||
| /* maker */ "Andre Sklenar", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_groovejuice() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&groovejuiceDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -15,9 +15,6 @@ | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // include some carla code first | |||
| #include "CarlaShmUtils.hpp" | |||
| // Plugin Code | |||
| #include "powerjuice/PowerJuiceArtwork.cpp" | |||
| #include "powerjuice/PowerJuicePlugin.cpp" | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "zamcomp/ZamCompArtwork.cpp" | |||
| #include "zamcomp/ZamCompPlugin.cpp" | |||
| #include "zamcomp/ZamCompUI.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor zamcompDesc = { | |||
| /* category */ PLUGIN_CATEGORY_DYNAMICS, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_HAS_UI|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ ZamCompPlugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "zamcomp", | |||
| /* maker */ "Damien Zammit", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zamcomp() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&zamcompDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "zamcompx2/ZamCompX2Artwork.cpp" | |||
| #include "zamcompx2/ZamCompX2Plugin.cpp" | |||
| #include "zamcompx2/ZamCompX2UI.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor zamcompx2Desc = { | |||
| /* category */ PLUGIN_CATEGORY_DYNAMICS, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_HAS_UI|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ ZamCompX2Plugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "zamcompx2", | |||
| /* maker */ "Damien Zammit", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zamcompx2() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&zamcompx2Desc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "zameq2/ZamEQ2Artwork.cpp" | |||
| #include "zameq2/ZamEQ2Plugin.cpp" | |||
| #include "zameq2/ZamEQ2UI.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor zameq2Desc = { | |||
| /* category */ PLUGIN_CATEGORY_EQ, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_HAS_UI|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ ZamEQ2Plugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "zameq2", | |||
| /* maker */ "Damien Zammit", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zameq2() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&zameq2Desc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "zamsynth/ZamSynthArtwork.cpp" | |||
| #include "zamsynth/ZamSynthPlugin.cpp" | |||
| #include "zamsynth/ZamSynthUI.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor zamsynthDesc = { | |||
| /* category */ PLUGIN_CATEGORY_SYNTH, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_IS_SYNTH|PLUGIN_HAS_UI|PLUGIN_USES_STATE|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ ZamSynthPlugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "zamsynth", | |||
| /* maker */ "Damien Zammit", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zamsynth() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&zamsynthDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,61 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "zamtube/ZamTubeArtwork.cpp" | |||
| #include "zamtube/ZamTubePlugin.cpp" | |||
| #include "zamtube/ZamTubeUI.cpp" | |||
| #include "zamtube/wdf.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor zamtubeDesc = { | |||
| /* category */ PLUGIN_CATEGORY_DYNAMICS, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_HAS_UI|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ ZamTubePlugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "zamtube", | |||
| /* maker */ "Damien Zammit", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zamtube() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&zamtubeDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,60 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "zamulticomp/ZaMultiCompArtwork.cpp" | |||
| #include "zamulticomp/ZaMultiCompPlugin.cpp" | |||
| #include "zamulticomp/ZaMultiCompUI.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor zamulticompDesc = { | |||
| /* category */ PLUGIN_CATEGORY_DYNAMICS, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_HAS_UI|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ ZaMultiCompPlugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "zamulticomp", | |||
| /* maker */ "Damien Zammit", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zamulticomp() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&zamulticompDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,63 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2014 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. | |||
| */ | |||
| // Plugin Code | |||
| #include "zamulticompx2/ZaMultiCompX2Artwork.cpp" | |||
| #include "zamulticompx2/ZaMultiCompX2Plugin.cpp" | |||
| #include "zamulticompx2/ZaMultiCompX2UI.cpp" | |||
| // DISTRHO Code | |||
| #define DISTRHO_PLUGIN_TARGET_CARLA | |||
| #include "DistrhoPluginMain.cpp" | |||
| #include "DistrhoUIMain.cpp" | |||
| // FIXME | |||
| #include "ImageToggle.cpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor zamulticompx2Desc = { | |||
| /* category */ PLUGIN_CATEGORY_DYNAMICS, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_HAS_UI|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ DISTRHO_PLUGIN_NUM_INPUTS, | |||
| /* audioOuts */ DISTRHO_PLUGIN_NUM_OUTPUTS, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ ZaMultiCompX2Plugin::paramCount, | |||
| /* paramOuts */ 0, | |||
| /* name */ DISTRHO_PLUGIN_NAME, | |||
| /* label */ "zamulticompx2", | |||
| /* maker */ "Damien Zammit", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(PluginCarla) | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zamulticompx2() | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| carla_register_native_plugin(&zamulticompx2Desc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,36 @@ | |||
| /* | |||
| * 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 "GrooveJuice" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||
| #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:GrooveJuice" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -0,0 +1,80 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_GROOVEJUICEARTWORK_HPP | |||
| #define BINARY_GROOVEJUICEARTWORK_HPP | |||
| namespace GrooveJuiceArtwork | |||
| { | |||
| 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 = 1328592; | |||
| const unsigned int backgroundWidth = 712; | |||
| const unsigned int backgroundHeight = 622; | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 10404; | |||
| const unsigned int knobWidth = 51; | |||
| const unsigned int knobHeight = 51; | |||
| extern const char* knob2Data; | |||
| const unsigned int knob2DataSize = 14400; | |||
| const unsigned int knob2Width = 60; | |||
| const unsigned int knob2Height = 60; | |||
| extern const char* orbitData; | |||
| const unsigned int orbitDataSize = 4096; | |||
| const unsigned int orbitWidth = 32; | |||
| const unsigned int orbitHeight = 32; | |||
| extern const char* pageButtonHoverData; | |||
| const unsigned int pageButtonHoverDataSize = 5460; | |||
| const unsigned int pageButtonHoverWidth = 65; | |||
| const unsigned int pageButtonHoverHeight = 21; | |||
| extern const char* pageButtonNormalData; | |||
| const unsigned int pageButtonNormalDataSize = 5460; | |||
| const unsigned int pageButtonNormalWidth = 65; | |||
| const unsigned int pageButtonNormalHeight = 21; | |||
| extern const char* randomizeButtonHoverData; | |||
| const unsigned int randomizeButtonHoverDataSize = 7224; | |||
| const unsigned int randomizeButtonHoverWidth = 86; | |||
| const unsigned int randomizeButtonHoverHeight = 21; | |||
| extern const char* randomizeButtonNormalData; | |||
| const unsigned int randomizeButtonNormalDataSize = 7224; | |||
| const unsigned int randomizeButtonNormalWidth = 86; | |||
| const unsigned int randomizeButtonNormalHeight = 21; | |||
| 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_GROOVEJUICEARTWORK_HPP | |||
| @@ -0,0 +1,621 @@ | |||
| /* | |||
| * 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 "GrooveJuicePlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| GrooveJuicePlugin::GrooveJuicePlugin() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| d_setProgram(0); | |||
| // reset | |||
| d_deactivate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void GrooveJuicePlugin::d_initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramX: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "X"; | |||
| parameter.symbol = "x"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramY: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Y"; | |||
| parameter.symbol = "y"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitSpeedX: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Speed X"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 4.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 128.0f; | |||
| break; | |||
| case paramOrbitSpeedY: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Speed Y"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 4.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 128.0f; | |||
| break; | |||
| case paramOrbitSizeX: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Size X"; | |||
| parameter.symbol = "osl"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitSizeY: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Size Y"; | |||
| parameter.symbol = "osr"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSubOrbitSpeed: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "SubOrbit Speed"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 32.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 128.0f; | |||
| break; | |||
| case paramSubOrbitSize: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "SubOrbit Size"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSubOrbitSmooth: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "SubOrbit Wave"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitWaveX: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Wave X"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 3.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| case paramOrbitPhaseX: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Phase X"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitPhaseY: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Phase Y"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitWaveY: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Orbit Wave Y"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 3.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| case paramOrbitOutX: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "Orbit X"; | |||
| parameter.symbol = "orx"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramOrbitOutY: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "Orbit Y"; | |||
| parameter.symbol = "ory"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSubOrbitOutX: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "SubOrbit X"; | |||
| parameter.symbol = "sorx"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSubOrbitOutY: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "SubOrbit Y"; | |||
| parameter.symbol = "sory"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramW1Out: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramW2Out: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramMOut: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramCOut: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramROut: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramSOut: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramReOut: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| case paramShOut: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = ""; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| } | |||
| if (index>=17 && index<17+64) { | |||
| //int x = (index-17)%8; | |||
| //int y = (x+1)/(index-17) | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "synth"; | |||
| parameter.symbol = ""; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = 0.5f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| } | |||
| } | |||
| void GrooveJuicePlugin::d_initProgramName(uint32_t index, d_string& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float GrooveJuicePlugin::d_getParameterValue(uint32_t index) const | |||
| { | |||
| if (index<17 || index>=17+64) { | |||
| 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 paramSubOrbitSpeed: | |||
| return subOrbitSpeed; | |||
| case paramSubOrbitSize: | |||
| return subOrbitSize; | |||
| case paramOrbitOutX: | |||
| return orbitX; | |||
| case paramOrbitOutY: | |||
| return orbitY; | |||
| case paramSubOrbitOutX: | |||
| return subOrbitX; | |||
| case paramSubOrbitOutY: | |||
| return subOrbitY; | |||
| case paramSubOrbitSmooth: | |||
| return subOrbitSmooth; | |||
| case paramOrbitWaveX: | |||
| return orbitWaveX; | |||
| case paramOrbitWaveY: | |||
| return orbitWaveY; | |||
| case paramOrbitPhaseX: | |||
| return orbitPhaseY; | |||
| case paramOrbitPhaseY: | |||
| return orbitPhaseY; | |||
| case paramW1Out: | |||
| return synthSound[0]; | |||
| case paramW2Out: | |||
| return synthSound[1]; | |||
| case paramMOut: | |||
| return synthSound[2]; | |||
| case paramCOut: | |||
| return synthSound[3]; | |||
| case paramROut: | |||
| return synthSound[4]; | |||
| case paramSOut: | |||
| return synthSound[5]; | |||
| case paramReOut: | |||
| return synthSound[6]; | |||
| case paramShOut: | |||
| return synthSound[7]; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } else { | |||
| int num = (index-17); //synth params begin on #17 | |||
| int x = num%8; //synth param | |||
| //synth page | |||
| int y = (num-(num%8))/8; | |||
| return synthData[x][y]; | |||
| } | |||
| } | |||
| void GrooveJuicePlugin::d_setParameterValue(uint32_t index, float value) | |||
| { | |||
| if (index<17) { | |||
| switch (index) | |||
| { | |||
| case paramX: | |||
| x = value; | |||
| break; | |||
| case paramY: | |||
| y = value; | |||
| break; | |||
| case paramOrbitSpeedX: | |||
| orbitSpeedX = value; | |||
| resetPhase(); | |||
| break; | |||
| case paramOrbitSpeedY: | |||
| orbitSpeedY = value; | |||
| resetPhase(); | |||
| break; | |||
| case paramOrbitSizeX: | |||
| orbitSizeX = value; | |||
| break; | |||
| case paramOrbitSizeY: | |||
| orbitSizeY = value; | |||
| break; | |||
| case paramSubOrbitSpeed: | |||
| subOrbitSpeed = value; | |||
| resetPhase(); | |||
| break; | |||
| case paramSubOrbitSize: | |||
| subOrbitSize = value; | |||
| break; | |||
| case paramSubOrbitSmooth: | |||
| subOrbitSmooth = value; | |||
| break; | |||
| case paramOrbitWaveX: | |||
| orbitWaveX = value; | |||
| break; | |||
| case paramOrbitWaveY: | |||
| orbitWaveY = value; | |||
| break; | |||
| case paramOrbitPhaseX: | |||
| orbitPhaseX = value; | |||
| resetPhase(); | |||
| break; | |||
| case paramOrbitPhaseY: | |||
| orbitPhaseY = value; | |||
| resetPhase(); | |||
| break; | |||
| } | |||
| } else { | |||
| int num = (index-17); //synth params begin on #17 | |||
| int x = num%8; //synth param | |||
| //synth page | |||
| int y = (num-(num%8))/8; | |||
| synthData[x][y] = value; | |||
| } | |||
| } | |||
| void GrooveJuicePlugin::d_setProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default parameter values */ | |||
| x = 0.5f; | |||
| y = 0.5f; | |||
| orbitSpeedX = 4.0f; | |||
| orbitSpeedY = 4.0f; | |||
| orbitSizeX = 0.5f; | |||
| orbitSizeY = 0.5f; | |||
| subOrbitSize = 0.5f; | |||
| subOrbitSpeed = 32.0f; | |||
| orbitWaveX = 3.0f; | |||
| orbitWaveY = 3.0f; | |||
| subOrbitSmooth = 0.5f; | |||
| orbitPhaseX = 0.0f; | |||
| orbitPhaseY = 0.0f; | |||
| /* 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; | |||
| synthL.setSampleRate(d_getSampleRate()); | |||
| synthR.setSampleRate(d_getSampleRate()); | |||
| //parameter smoothing | |||
| for (int i=0; i<2; i++) { | |||
| sA[i] = 0.99f; | |||
| sB[i] = 1.f - sA[i]; | |||
| sZ[i] = 0; | |||
| } | |||
| for (int x=0; x<8; x++) | |||
| for (int y=0; y<8; y++) | |||
| synthData[x][y] = 0.5; | |||
| /* reset filter values */ | |||
| d_activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void GrooveJuicePlugin::d_activate() | |||
| { | |||
| //sinePos = 0; | |||
| } | |||
| void GrooveJuicePlugin::d_deactivate() | |||
| { | |||
| // all values to zero | |||
| } | |||
| void GrooveJuicePlugin::d_run(float**, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) | |||
| { | |||
| float out1, out2, tX, tY; | |||
| /* | |||
| 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)))); | |||
| */ | |||
| for (uint32_t i = 0; i<frames; i++) { | |||
| animate(); | |||
| tX = subOrbitX; | |||
| tY = subOrbitY; | |||
| //sum values | |||
| float c = 0.41421f; //mid segment | |||
| float d = c/1.41f; //side segments | |||
| float distances[8]; | |||
| distances[0] = distance(d, 0, tX, tY); | |||
| distances[1] = distance(c+d, 0, tX, tY); | |||
| distances[2] = distance(1, d, tX, tY); | |||
| distances[3] = distance(1, c+d, tX, tY); | |||
| distances[4] = distance(d, 1, tX, tY); | |||
| distances[5] = distance(c+d, 1, tX, tY); | |||
| distances[6] = distance(0, d, tX, tY); | |||
| distances[7] = distance(0, c+d, tX, tY); | |||
| //std::cout << distances[0] << " "; | |||
| //std::cout << tX << std::endl; | |||
| for (int x=0; x<8; x++) { | |||
| float targetValue = 0; | |||
| for (int y=0; y<8; y++) { | |||
| targetValue += synthData[x][y]*(distances[y]); | |||
| } | |||
| synthSound[x] = tN(targetValue); | |||
| } | |||
| //printf("wave1: %f\n", synthSound[0]); | |||
| //std::cout << synthSound[0] << std::endl; | |||
| synthL.setWave(0, synthSound[0]); | |||
| synthR.setWave(0, synthSound[0]); | |||
| synthL.setWave(1, synthSound[1]); | |||
| synthR.setWave(1, synthSound[1]); | |||
| synthL.setMix(synthSound[2]); | |||
| synthR.setMix(synthSound[2]); | |||
| //synthL.setCut(synthSound[3]); | |||
| //synthR.setCut(synthSound[3]); | |||
| //synthL.setReso(synthSound[4]); | |||
| //synthR.setReso(synthSound[4]); | |||
| //synthL.setDecay(synthSound[5]); | |||
| //synthR.setDecay(synthSound[5]); | |||
| synthL.setSustain(synthSound[5]); | |||
| synthR.setSustain(synthSound[5]); | |||
| synthL.setRelease(synthSound[6]); | |||
| synthR.setRelease(synthSound[6]); | |||
| synthL.setStereo(-0.5); | |||
| synthR.setStereo(0.5); | |||
| synthL.setShape(synthSound[7]); | |||
| synthR.setShape(synthSound[7]); | |||
| float cutoff = std::exp((std::log(16000)-std::log(500))*synthSound[3]+std::log(500)); | |||
| filterL.recalc(cutoff, synthSound[4]*0.8, d_getSampleRate(), synthSound[7]); | |||
| filterR.recalc(cutoff, synthSound[4]*0.8, d_getSampleRate(), synthSound[7]); | |||
| outputs[0][i] = filterL.process(synthL.run()); | |||
| outputs[1][i] = filterR.process(synthL.run()); | |||
| } | |||
| //outputs = buffer; | |||
| for (uint32_t i = 0; i<midiEventCount; i++) { | |||
| int mType = midiEvents[i].buf[0] & 0xF0; | |||
| //int mChan = midiEvents[i].buf[0] & 0x0F; | |||
| int mNum = midiEvents[i].buf[1]; | |||
| if (mType == 0x90) { | |||
| //note on | |||
| synthL.play(mNum); | |||
| synthR.play(mNum); | |||
| } else if (mType == 0x80) { | |||
| //note off | |||
| synthL.stop(mNum); | |||
| synthR.stop(mNum); | |||
| } | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new GrooveJuicePlugin(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,280 @@ | |||
| /* | |||
| * 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 GROOVEJUICEPLUGIN_HPP_INCLUDED | |||
| #define GROOVEJUICEPLUGIN_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| #include <iostream> | |||
| #include "Synth.hxx" | |||
| #include "moogVCF.hxx" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class GrooveJuicePlugin : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramX = 0, | |||
| paramY, | |||
| paramOrbitSizeX, | |||
| paramOrbitSizeY, | |||
| paramOrbitSpeedX, | |||
| paramOrbitSpeedY, | |||
| paramSubOrbitSpeed, | |||
| paramSubOrbitSize, | |||
| paramOrbitWaveX, | |||
| paramOrbitWaveY, | |||
| paramOrbitPhaseX, | |||
| paramOrbitPhaseY, | |||
| paramSubOrbitSmooth, | |||
| paramOrbitOutX, | |||
| paramOrbitOutY, | |||
| paramSubOrbitOutX, | |||
| paramSubOrbitOutY, | |||
| w11, w21, m1, c1, r1, s1, re1, sh1, | |||
| w12, w22, m2, c2, r2, s2, re2, sh2, | |||
| w13, w23, m3, c3, r3, s3, re3, sh3, | |||
| w14, w24, m4, c4, r4, s4, re4, sh4, | |||
| w15, w25, m5, c5, r5, s5, re5, sh5, | |||
| w16, w26, m6, c6, r6, s6, re6, sh6, | |||
| w17, w27, m7, c7, r7, s7, re7, sh7, | |||
| w18, w28, m8, c8, r8, s8, re8, sh8, | |||
| paramW1Out, | |||
| paramW2Out, | |||
| paramMOut, | |||
| paramCOut, | |||
| paramROut, | |||
| paramSOut, | |||
| paramReOut, | |||
| paramShOut, | |||
| paramCount | |||
| }; | |||
| inline 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; | |||
| } | |||
| } | |||
| void resetPhase() | |||
| { | |||
| const TimePos& time = d_getTimePos(); | |||
| if (!time.playing) | |||
| { | |||
| sinePosX = 0; | |||
| sinePosY = 0; | |||
| sinePos = 0; | |||
| } | |||
| } | |||
| float tN (float x) | |||
| { | |||
| if (x>1) x=1; | |||
| if (x<0) x=0; | |||
| return x; | |||
| } | |||
| float distance(float x, float y, float tX, float tY) { | |||
| float result = pow(tN(1-(sqrt((tX - x)*(tX - x) + (tY - y)*(tY - y)))), 3); | |||
| return result; | |||
| } | |||
| void animate() | |||
| { | |||
| //sync orbit with frame, bpm | |||
| const TimePos& time = d_getTimePos(); | |||
| bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(d_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*3)*0.25; | |||
| float tempPhaseY = std::round(orbitPhaseY*3)*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; | |||
| } | |||
| GrooveJuicePlugin(); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* d_getLabel() const noexcept override | |||
| { | |||
| return "GrooveJuice"; | |||
| } | |||
| const char* d_getMaker() const noexcept override | |||
| { | |||
| return "Andre Sklenar"; | |||
| } | |||
| const char* d_getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t d_getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| long d_getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('G', 'r', 'v', 'J'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void d_initParameter(uint32_t index, Parameter& parameter) override; | |||
| void d_initProgramName(uint32_t index, d_string& programName) override; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float d_getParameterValue(uint32_t index) const override; | |||
| void d_setParameterValue(uint32_t index, float value) override; | |||
| void d_setProgram(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| void d_activate() override; | |||
| void d_deactivate() override; | |||
| void d_run(float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| CSynth synthL, synthR; | |||
| MoogVCF filterL, filterR; | |||
| 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]; | |||
| float synthData[8][8]; //as per gui, [param][page] | |||
| float synthSound[8]; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // GROOVEJUICE_HPP_INCLUDED | |||
| @@ -0,0 +1,776 @@ | |||
| /* | |||
| * 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 "GrooveJuiceUI.hpp" | |||
| using DGL::Point; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| GrooveJuiceUI::GrooveJuiceUI() | |||
| : UI(), | |||
| fAboutWindow(this) | |||
| { | |||
| // xy params | |||
| paramX = paramY = 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(GrooveJuiceArtwork::backgroundData, GrooveJuiceArtwork::backgroundWidth, GrooveJuiceArtwork::backgroundHeight, GL_BGR); | |||
| //roundlet | |||
| fImgRoundlet = Image(GrooveJuiceArtwork::roundletData, GrooveJuiceArtwork::roundletWidth, GrooveJuiceArtwork::roundletHeight); | |||
| //orbit | |||
| fImgOrbit = Image(GrooveJuiceArtwork::orbitData, GrooveJuiceArtwork::orbitWidth, GrooveJuiceArtwork::orbitHeight); | |||
| //subOrbit | |||
| fImgSubOrbit = Image(GrooveJuiceArtwork::subOrbitData, GrooveJuiceArtwork::subOrbitWidth, GrooveJuiceArtwork::subOrbitHeight); | |||
| // about | |||
| Image imageAbout(GrooveJuiceArtwork::aboutData, GrooveJuiceArtwork::aboutWidth, GrooveJuiceArtwork::aboutHeight, GL_BGR); | |||
| fAboutWindow.setImage(imageAbout); | |||
| // about button | |||
| Image aboutImageNormal(GrooveJuiceArtwork::aboutButtonNormalData, GrooveJuiceArtwork::aboutButtonNormalWidth, GrooveJuiceArtwork::aboutButtonNormalHeight); | |||
| Image aboutImageHover(GrooveJuiceArtwork::aboutButtonHoverData, GrooveJuiceArtwork::aboutButtonHoverWidth, GrooveJuiceArtwork::aboutButtonHoverHeight); | |||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | |||
| fButtonAbout->setPos(599, 17); | |||
| fButtonAbout->setCallback(this); | |||
| Image pageImageNormal(GrooveJuiceArtwork::pageButtonNormalData, GrooveJuiceArtwork::pageButtonNormalWidth, GrooveJuiceArtwork::pageButtonNormalHeight); | |||
| Image pageImageHover(GrooveJuiceArtwork::pageButtonHoverData, GrooveJuiceArtwork::pageButtonHoverWidth, GrooveJuiceArtwork::pageButtonHoverHeight); | |||
| Image randomizeImageNormal(GrooveJuiceArtwork::randomizeButtonNormalData, GrooveJuiceArtwork::randomizeButtonNormalWidth, GrooveJuiceArtwork::randomizeButtonNormalHeight); | |||
| Image randomizeImageHover(GrooveJuiceArtwork::randomizeButtonHoverData, GrooveJuiceArtwork::randomizeButtonHoverWidth, GrooveJuiceArtwork::randomizeButtonHoverHeight); | |||
| fButtonRandomize = new ImageButton(this, randomizeImageNormal, randomizeImageHover, randomizeImageHover); | |||
| fButtonRandomize -> setPos(313, 586); | |||
| fButtonRandomize -> setCallback(this); | |||
| int oX = 15; | |||
| int oY = 557; | |||
| int mX = 103-oX; | |||
| int mY = 0; | |||
| for (int i=0; i<8; i++) { | |||
| fButtonsPage[i] = new ImageButton(this, pageImageNormal, pageImageHover, pageImageHover); | |||
| fButtonsPage[i]->setPos(oX+mX*i, oY); | |||
| fButtonsPage[i]->setCallback(this); | |||
| } | |||
| // knobs | |||
| Image knobImage(GrooveJuiceArtwork::knobData, GrooveJuiceArtwork::knobWidth, GrooveJuiceArtwork::knobHeight); | |||
| Image knob2Image(GrooveJuiceArtwork::knob2Data, GrooveJuiceArtwork::knob2Width, GrooveJuiceArtwork::knob2Height); | |||
| // knob KnobOrbitSpeedX | |||
| fKnobOrbitSpeedX = new ImageKnob(this, knobImage); | |||
| fKnobOrbitSpeedX->setPos(423, 185); | |||
| fKnobOrbitSpeedX->setStep(1.0f); | |||
| fKnobOrbitSpeedX->setRange(1.0f, 128.0f); | |||
| fKnobOrbitSpeedX->setValue(4.0f); | |||
| fKnobOrbitSpeedX->setRotationAngle(270); | |||
| fKnobOrbitSpeedX->setCallback(this); | |||
| // knob KnobOrbitSpeedY | |||
| fKnobOrbitSpeedY = new ImageKnob(this, knobImage); | |||
| fKnobOrbitSpeedY->setPos(516, 185); | |||
| fKnobOrbitSpeedY->setStep(1.0f); | |||
| fKnobOrbitSpeedY->setRange(1.0f, 128.0f); | |||
| fKnobOrbitSpeedY->setValue(4.0f); | |||
| fKnobOrbitSpeedY->setRotationAngle(270); | |||
| fKnobOrbitSpeedY->setCallback(this); | |||
| // knob KnobOrbitSizeX | |||
| fKnobOrbitSizeX = new ImageKnob(this, knobImage); | |||
| fKnobOrbitSizeX->setPos(423, 73); | |||
| fKnobOrbitSizeX->setRange(0.0f, 1.0f); | |||
| fKnobOrbitSizeX->setValue(0.5f); | |||
| fKnobOrbitSizeX->setRotationAngle(270); | |||
| fKnobOrbitSizeX->setCallback(this); | |||
| // knob KnobOrbitSizeY | |||
| fKnobOrbitSizeY = new ImageKnob(this, knobImage); | |||
| fKnobOrbitSizeY->setPos(516, 73); | |||
| fKnobOrbitSizeY->setRange(0.0f, 1.0f); | |||
| fKnobOrbitSizeY->setValue(0.5f); | |||
| fKnobOrbitSizeY->setRotationAngle(270); | |||
| fKnobOrbitSizeY->setCallback(this); | |||
| // knob KnobSubOrbitSpeed | |||
| fKnobSubOrbitSpeed = new ImageKnob(this, knobImage); | |||
| fKnobSubOrbitSpeed->setPos(620, 185); | |||
| fKnobSubOrbitSpeed->setStep(1.0f); | |||
| fKnobSubOrbitSpeed->setRange(1.0f, 128.0f); | |||
| fKnobSubOrbitSpeed->setValue(32.0f); | |||
| fKnobSubOrbitSpeed->setRotationAngle(270); | |||
| fKnobSubOrbitSpeed->setCallback(this); | |||
| // knob KnobSubOrbitSize | |||
| fKnobSubOrbitSize = new ImageKnob(this, knobImage); | |||
| fKnobSubOrbitSize->setPos(620, 73); | |||
| fKnobSubOrbitSize->setRange(0.0f, 1.0f); | |||
| fKnobSubOrbitSize->setValue(0.5f); | |||
| fKnobSubOrbitSize->setRotationAngle(270); | |||
| fKnobSubOrbitSize->setCallback(this); | |||
| // knob KnobSubOrbitSmooth | |||
| fKnobSubOrbitSmooth = new ImageKnob(this, knobImage); | |||
| fKnobSubOrbitSmooth->setPos(620, 297); | |||
| fKnobSubOrbitSmooth->setRange(0.0f, 1.0f); | |||
| fKnobSubOrbitSmooth->setValue(0.5f); | |||
| fKnobSubOrbitSmooth->setRotationAngle(270); | |||
| fKnobSubOrbitSmooth->setCallback(this); | |||
| // sliders | |||
| Image sliderImage(GrooveJuiceArtwork::sliderData, GrooveJuiceArtwork::sliderWidth, GrooveJuiceArtwork::sliderHeight); | |||
| Point<int> sliderPosStart(410, 284); | |||
| Point<int> sliderPosEnd(410+48, 284); | |||
| // slider OrbitWaveX | |||
| fSliderOrbitWaveX = new ImageSlider(this, sliderImage); | |||
| fSliderOrbitWaveX->setStartPos(sliderPosStart); | |||
| fSliderOrbitWaveX->setEndPos(sliderPosEnd); | |||
| fSliderOrbitWaveX->setRange(1.0f, 4.0f); | |||
| fSliderOrbitWaveX->setStep(1.0f); | |||
| fSliderOrbitWaveX->setValue(3.0f); | |||
| fSliderOrbitWaveX->setCallback(this); | |||
| // slider OrbitWaveY | |||
| sliderPosStart.setX(503); | |||
| sliderPosEnd.setX(503+48); | |||
| fSliderOrbitWaveY = new ImageSlider(this, sliderImage); | |||
| fSliderOrbitWaveY->setStartPos(sliderPosStart); | |||
| fSliderOrbitWaveY->setEndPos(sliderPosEnd); | |||
| fSliderOrbitWaveY->setRange(1.0f, 4.0f); | |||
| fSliderOrbitWaveY->setStep(1.0f); | |||
| fSliderOrbitWaveY->setValue(3.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->setStartPos(sliderPosStart); | |||
| fSliderOrbitPhaseX->setEndPos(sliderPosEnd); | |||
| fSliderOrbitPhaseX->setRange(0.0f, 1.0f); | |||
| //fSliderOrbitPhaseX->setStep(1.0f); // FIXME? | |||
| fSliderOrbitPhaseX->setValue(0.0f); | |||
| fSliderOrbitPhaseX->setCallback(this); | |||
| // slider OrbitPhaseY | |||
| sliderPosStart.setX(503); | |||
| sliderPosEnd.setX(503+48); | |||
| fSliderOrbitPhaseY = new ImageSlider(this, sliderImage); | |||
| fSliderOrbitPhaseY->setStartPos(sliderPosStart); | |||
| fSliderOrbitPhaseY->setEndPos(sliderPosEnd); | |||
| fSliderOrbitPhaseY->setRange(0.0f, 1.0f); | |||
| //fSliderOrbitPhaseY->setStep(1.0f); // FIXME? | |||
| fSliderOrbitPhaseY->setValue(0.0f); | |||
| fSliderOrbitPhaseY->setCallback(this); | |||
| //knobs graphics | |||
| oX = 25; //offset | |||
| oY = 480; | |||
| mX = 113-oX; //margin | |||
| mY = 545-oY; | |||
| oX-=9; | |||
| oY-=9; | |||
| page = 0; | |||
| //synth Knobs | |||
| for (int x=0; x<8; x++) { | |||
| fKnobsSynth[x] = new ImageKnob(this, knob2Image); | |||
| fKnobsSynth[x]->setPos(oX+mX*x, oY); | |||
| //fKnobsSynth[x]->setStep(1.0f); | |||
| fKnobsSynth[x]->setRange(0.0f, 1.0f); | |||
| fKnobsSynth[x]->setValue(0.5f); | |||
| fKnobsSynth[x]->setRotationAngle(270); | |||
| fKnobsSynth[x]->setCallback(this); | |||
| } | |||
| //default synthData | |||
| for (int x=0; x<8; x++) | |||
| for (int y=0; y<8; y++) | |||
| synthData[x][y] = 0.5; | |||
| //default squares | |||
| oX = 20; | |||
| oY = 47; | |||
| mX = 372/8; | |||
| for (int x=0; x<8; x++) { | |||
| for (int y=0; y<8; y++) { | |||
| squares[x][y].timer = 0; | |||
| squares[x][y].maxTimer = d_getSampleRate()/8000; | |||
| squares[x][y].x=oX+mX*x; | |||
| squares[x][y].y=oY+mX*y; | |||
| squares[x][y].size = mX; | |||
| } | |||
| } | |||
| tabOX = 15; | |||
| tabOY = 552; | |||
| tabW = 64; | |||
| tabH = 5; | |||
| tabPosX = tabOX; | |||
| tabTargetPosX = tabPosX; | |||
| tabMarginX = 103-tabOX; | |||
| } | |||
| GrooveJuiceUI::~GrooveJuiceUI() | |||
| { | |||
| delete fButtonAbout; | |||
| //knobs | |||
| delete fKnobOrbitSpeedX; | |||
| delete fKnobOrbitSpeedY; | |||
| delete fKnobOrbitSizeX; | |||
| delete fKnobOrbitSizeY; | |||
| delete fKnobSubOrbitSpeed; | |||
| delete fKnobSubOrbitSize; | |||
| delete fKnobSubOrbitSmooth; | |||
| //sliders | |||
| delete fSliderOrbitWaveX; | |||
| delete fSliderOrbitWaveY; | |||
| delete fSliderOrbitPhaseX; | |||
| delete fSliderOrbitPhaseY; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void GrooveJuiceUI::d_parameterChanged(uint32_t index, float value) | |||
| { | |||
| if (index<17 || index>=17+64) { | |||
| switch (index) | |||
| { | |||
| case GrooveJuicePlugin::paramX: | |||
| if (paramX != value) | |||
| { | |||
| paramX = value; | |||
| fDragValid = false; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case GrooveJuicePlugin::paramY: | |||
| if (paramY != value) | |||
| { | |||
| paramY = value; | |||
| fDragValid = false; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitSizeX: | |||
| fKnobOrbitSizeX->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitSizeY: | |||
| fKnobOrbitSizeY->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitSpeedX: | |||
| fKnobOrbitSpeedX->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitSpeedY: | |||
| fKnobOrbitSpeedY->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramSubOrbitSize: | |||
| fKnobSubOrbitSize->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramSubOrbitSpeed: | |||
| fKnobSubOrbitSpeed->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramSubOrbitSmooth: | |||
| fKnobSubOrbitSmooth->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitWaveX: | |||
| fSliderOrbitWaveX->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitWaveY: | |||
| fSliderOrbitWaveY->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitPhaseX: | |||
| fSliderOrbitPhaseX->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitPhaseY: | |||
| fSliderOrbitPhaseY->setValue(value); | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitOutX: | |||
| if (orbitX != value) | |||
| { | |||
| orbitX = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case GrooveJuicePlugin::paramOrbitOutY: | |||
| if (orbitY != value) | |||
| { | |||
| orbitY = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case GrooveJuicePlugin::paramSubOrbitOutX: | |||
| if (subOrbitX != value) | |||
| { | |||
| subOrbitX = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case GrooveJuicePlugin::paramSubOrbitOutY: | |||
| if (subOrbitY != value) | |||
| { | |||
| subOrbitY = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case GrooveJuicePlugin::paramW1Out: | |||
| synthSound[0] = value; | |||
| repaint(); | |||
| break; | |||
| case GrooveJuicePlugin::paramW2Out: | |||
| synthSound[1] = value; | |||
| repaint(); | |||
| break; | |||
| case GrooveJuicePlugin::paramMOut: | |||
| synthSound[2] = value; | |||
| repaint(); | |||
| break; | |||
| case GrooveJuicePlugin::paramCOut: | |||
| synthSound[3] = value; | |||
| repaint(); | |||
| break; | |||
| case GrooveJuicePlugin::paramROut: | |||
| synthSound[4] = value; | |||
| repaint(); | |||
| break; | |||
| case GrooveJuicePlugin::paramSOut: | |||
| synthSound[5] = value; | |||
| repaint(); | |||
| break; | |||
| case GrooveJuicePlugin::paramReOut: | |||
| synthSound[6] = value; | |||
| repaint(); | |||
| break; | |||
| case GrooveJuicePlugin::paramShOut: | |||
| synthSound[7] = value; | |||
| repaint(); | |||
| break; | |||
| } | |||
| } else { | |||
| //synth param changed | |||
| int num = (index-17); //synth params begin on #17 | |||
| int x = num%8; //synth param | |||
| //synth page | |||
| int y = (num-(num%8))/8; | |||
| synthData[x][y] = value; | |||
| } | |||
| } | |||
| void GrooveJuiceUI::d_programChanged(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| paramX = paramY = 0.5f; | |||
| fKnobOrbitSpeedX->setValue(4.0f); | |||
| fKnobOrbitSpeedY->setValue(4.0f); | |||
| fKnobOrbitSizeX->setValue(1.0f); | |||
| fKnobOrbitSizeY->setValue(1.0f); | |||
| fKnobSubOrbitSize->setValue(1.0f); | |||
| fKnobSubOrbitSpeed->setValue(32.0f); | |||
| fKnobSubOrbitSmooth->setValue(0.5f); | |||
| fSliderOrbitWaveX->setValue(3.0f); | |||
| fSliderOrbitWaveY->setValue(3.0f); | |||
| fSliderOrbitPhaseX->setValue(0.0f); | |||
| fSliderOrbitPhaseY->setValue(0.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void GrooveJuiceUI::imageButtonClicked(ImageButton* button, int) | |||
| { | |||
| if (button == fButtonAbout) | |||
| fAboutWindow.exec(); | |||
| if (button == fButtonRandomize) { | |||
| for (int y=0; y<8; y++) { | |||
| for (int x=0; x<8; x++) { | |||
| synthData[x][y] = getRandom(); | |||
| d_setParameterValue(17+y*8+x, synthData[x][y]); | |||
| } | |||
| } | |||
| for (int x=0; x<8; x++) { | |||
| fKnobsSynth[x]->setValue(synthData[x][page]); | |||
| } | |||
| } | |||
| for (int i=0; i<8; i++) { | |||
| if (button == fButtonsPage[i]) { | |||
| page = i; | |||
| tabTargetPosX = tabOX+page*tabMarginX; | |||
| for (int x=0; x<8; x++) { | |||
| fKnobsSynth[x]->setValue(synthData[x][page]); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void GrooveJuiceUI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobOrbitSpeedX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSpeedX, true); | |||
| else if (knob == fKnobOrbitSpeedY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSpeedY, true); | |||
| else if (knob == fKnobOrbitSizeX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSizeX, true); | |||
| else if (knob == fKnobOrbitSizeY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSizeY, true); | |||
| else if (knob == fKnobSubOrbitSize) | |||
| d_editParameter(GrooveJuicePlugin::paramSubOrbitSize, true); | |||
| else if (knob == fKnobSubOrbitSpeed) | |||
| d_editParameter(GrooveJuicePlugin::paramSubOrbitSpeed, true); | |||
| else if (knob == fKnobSubOrbitSmooth) | |||
| d_editParameter(GrooveJuicePlugin::paramSubOrbitSmooth, true); | |||
| for (int i=0; i<8; i++) { | |||
| if (knob== fKnobsSynth[i]) { | |||
| d_editParameter(i+17+(page*8), true); | |||
| } | |||
| } | |||
| } | |||
| void GrooveJuiceUI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobOrbitSpeedX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSpeedX, false); | |||
| else if (knob == fKnobOrbitSpeedY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSpeedY, false); | |||
| else if (knob == fKnobOrbitSizeX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSizeX, false); | |||
| else if (knob == fKnobOrbitSizeY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitSizeY, false); | |||
| else if (knob == fKnobSubOrbitSize) | |||
| d_editParameter(GrooveJuicePlugin::paramSubOrbitSize, false); | |||
| else if (knob == fKnobSubOrbitSpeed) | |||
| d_editParameter(GrooveJuicePlugin::paramSubOrbitSpeed, false); | |||
| else if (knob == fKnobSubOrbitSmooth) | |||
| d_editParameter(GrooveJuicePlugin::paramSubOrbitSmooth, false); | |||
| for (int i=0; i<8; i++) { | |||
| if (knob== fKnobsSynth[i]) { | |||
| d_editParameter(i+17+page*8, false); | |||
| } | |||
| } | |||
| } | |||
| void GrooveJuiceUI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| if (knob == fKnobOrbitSpeedX) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitSpeedX, value); | |||
| else if (knob == fKnobOrbitSpeedY) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitSpeedY, value); | |||
| else if (knob == fKnobOrbitSizeX) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitSizeX, value); | |||
| else if (knob == fKnobOrbitSizeY) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitSizeY, value); | |||
| else if (knob == fKnobSubOrbitSize) | |||
| d_setParameterValue(GrooveJuicePlugin::paramSubOrbitSize, value); | |||
| else if (knob == fKnobSubOrbitSpeed) | |||
| d_setParameterValue(GrooveJuicePlugin::paramSubOrbitSpeed, value); | |||
| else if (knob == fKnobSubOrbitSmooth) | |||
| d_setParameterValue(GrooveJuicePlugin::paramSubOrbitSmooth, value); | |||
| for (int i=0; i<8; i++) { | |||
| if (knob== fKnobsSynth[i]) { | |||
| synthData[i][page] = value; | |||
| d_setParameterValue(i+17+page*8, value); | |||
| } | |||
| } | |||
| } | |||
| void GrooveJuiceUI::imageSliderDragStarted(ImageSlider* slider) | |||
| { | |||
| if (slider == fSliderOrbitWaveX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitWaveX, true); | |||
| else if (slider == fSliderOrbitWaveY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitWaveY, true); | |||
| else if (slider == fSliderOrbitPhaseX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitPhaseX, true); | |||
| else if (slider == fSliderOrbitPhaseY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitPhaseY, true); | |||
| } | |||
| void GrooveJuiceUI::imageSliderDragFinished(ImageSlider* slider) | |||
| { | |||
| if (slider == fSliderOrbitWaveX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitWaveX, false); | |||
| else if (slider == fSliderOrbitWaveY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitWaveY, false); | |||
| else if (slider == fSliderOrbitPhaseX) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitPhaseX, false); | |||
| else if (slider == fSliderOrbitPhaseY) | |||
| d_editParameter(GrooveJuicePlugin::paramOrbitPhaseY, false); | |||
| } | |||
| void GrooveJuiceUI::imageSliderValueChanged(ImageSlider* slider, float value) | |||
| { | |||
| if (slider == fSliderOrbitWaveX) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitWaveX, value); | |||
| else if (slider == fSliderOrbitWaveY) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitWaveY, value); | |||
| else if (slider == fSliderOrbitPhaseX) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitPhaseX, value); | |||
| else if (slider == fSliderOrbitPhaseY) | |||
| d_setParameterValue(GrooveJuicePlugin::paramOrbitPhaseY, value); | |||
| } | |||
| void GrooveJuiceUI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| /* | |||
| // TESTING - remove later | |||
| // this paints the 'fCanvasArea' so we can clearly see its bounds | |||
| { | |||
| const int x = fCanvasArea.getX(); | |||
| const int y = fCanvasArea.getY(); | |||
| const int w = fCanvasArea.getWidth(); | |||
| const int h = fCanvasArea.getHeight(); | |||
| glColor4f(0.0f, 1.0f, 0.0f, 0.1f); | |||
| glBegin(GL_QUADS); | |||
| glTexCoord2f(0.0f, 0.0f); | |||
| glVertex2i(x, y); | |||
| glTexCoord2f(1.0f, 0.0f); | |||
| glVertex2i(x+w, y); | |||
| glTexCoord2f(1.0f, 1.0f); | |||
| glVertex2i(x+w, y+h); | |||
| glTexCoord2f(0.0f, 1.0f); | |||
| glVertex2i(x, y+h); | |||
| glEnd(); | |||
| // reset color | |||
| glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |||
| } | |||
| */ | |||
| // 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(); | |||
| //draw tab highlight | |||
| tabPosX -= (tabPosX-tabTargetPosX)/3; | |||
| glColor4f(0.5f, 0.5f, 1.0f, 1.0f); | |||
| glBegin(GL_POLYGON); | |||
| glVertex2i(tabPosX, tabOY); | |||
| glVertex2i(tabPosX+tabW, tabOY); | |||
| glVertex2i(tabPosX+tabW, tabOY+tabH); | |||
| glVertex2i(tabPosX, tabOY+tabH); | |||
| glEnd(); | |||
| //draw real knob values | |||
| int kPosX = 6; | |||
| int kPosY = 550; | |||
| int kH = 112; | |||
| int kW = 83; | |||
| int kM = 94-kPosX; | |||
| glColor4f(1.0f, 1.0f, 1.0f, 0.1f); | |||
| for (int i=0; i<8; i++) { | |||
| glBegin(GL_POLYGON); | |||
| glVertex2i(kPosX+kM*i, kPosY); | |||
| glVertex2i(kPosX+kM*i+kW, kPosY); | |||
| glVertex2i(kPosX+kM*i+kW, kPosY-synthSound[i]*kH); | |||
| glVertex2i(kPosX+kM*i, kPosY-synthSound[i]*kH); | |||
| glEnd(); | |||
| } | |||
| /*for (int x=0; x<8; x++) { | |||
| for (int y=0; y<8; y++) { | |||
| if (isWithinSquare(orbitX, orbitY, x/8.0, y/8.0)) { | |||
| if (squares[x][y].timer<squares[x][y].maxTimer) { | |||
| squares[x][y].timer++; | |||
| } | |||
| } else { | |||
| if (squares[x][y].timer>0) { | |||
| squares[x][y].timer--; | |||
| } | |||
| } | |||
| if (squares[x][y].timer>0) { | |||
| //draw this square | |||
| glColor4f(0.0f, 1.0f, 0.0f, squares[x][y].timer/squares[x][y].maxTimer/8); | |||
| //printf("blend: %f\n", squares[x][y].timer/squares[x][y].maxTimer); | |||
| glBegin(GL_POLYGON); | |||
| glVertex2i(squares[x][y].x, squares[x][y].y); | |||
| glVertex2i(squares[x][y].x+squares[x][y].size, squares[x][y].y); | |||
| glVertex2i(squares[x][y].x+squares[x][y].size, squares[x][y].y+squares[x][y].size); | |||
| glVertex2i(squares[x][y].x, squares[x][y].y+squares[x][y].size); | |||
| glEnd(); | |||
| } | |||
| } | |||
| }*/ | |||
| // reset color | |||
| glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |||
| // draw roundlet and orbits | |||
| fImgRoundlet.draw(x, y); | |||
| fImgOrbit.draw(nOrbitX, nOrbitY); | |||
| fImgSubOrbit.draw(nSubOrbitX, nSubOrbitY); | |||
| } | |||
| bool GrooveJuiceUI::onMouse(int button, bool press, int x, int y) | |||
| { | |||
| if (button != 1) | |||
| return false; | |||
| if (press) | |||
| { | |||
| if (! fCanvasArea.contains(x, y)) | |||
| return false; | |||
| fDragging = true; | |||
| fDragValid = true; | |||
| fLastX = x; | |||
| fLastY = y; | |||
| return true; | |||
| } | |||
| else if (fDragging) | |||
| { | |||
| fDragging = false; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| bool GrooveJuiceUI::onMotion(int x, int y) | |||
| { | |||
| if (! fDragging) | |||
| return false; | |||
| 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; | |||
| d_setParameterValue(GrooveJuicePlugin::paramX, paramX); | |||
| repaint(); | |||
| } | |||
| if (newY != paramY) | |||
| { | |||
| paramY = newY; | |||
| d_setParameterValue(GrooveJuicePlugin::paramY, paramY); | |||
| repaint(); | |||
| } | |||
| return true; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new GrooveJuiceUI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,161 @@ | |||
| /* | |||
| * 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 GROOVEJUICEUI_HPP_INCLUDED | |||
| #define GROOVEJUICEUI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "Geometry.hpp" | |||
| #include "ImageAboutWindow.hpp" | |||
| #include "ImageButton.hpp" | |||
| #include "ImageKnob.hpp" | |||
| #include "ImageSlider.hpp" | |||
| #include "GrooveJuiceArtwork.hpp" | |||
| #include "GrooveJuicePlugin.hpp" | |||
| using DGL::Image; | |||
| using DGL::ImageAboutWindow; | |||
| using DGL::ImageButton; | |||
| using DGL::ImageKnob; | |||
| using DGL::ImageSlider; | |||
| using DGL::Rectangle; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class GrooveJuiceUI : public UI, | |||
| public ImageButton::Callback, | |||
| public ImageKnob::Callback, | |||
| public ImageSlider::Callback | |||
| { | |||
| public: | |||
| GrooveJuiceUI(); | |||
| ~GrooveJuiceUI() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| unsigned int d_getWidth() const noexcept override | |||
| { | |||
| return GrooveJuiceArtwork::backgroundWidth; | |||
| } | |||
| unsigned int d_getHeight() const noexcept override | |||
| { | |||
| return GrooveJuiceArtwork::backgroundHeight; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void d_parameterChanged(uint32_t index, float value) override; | |||
| void d_programChanged(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(int button, bool press, int x, int y) override; | |||
| bool onMotion(int x, int y) override; | |||
| private: | |||
| float paramX, paramY; | |||
| Image fImgBackground; | |||
| Image fImgRoundlet; | |||
| Image fImgOrbit; | |||
| Image fImgSubOrbit; | |||
| ImageAboutWindow fAboutWindow; | |||
| //knobs | |||
| ImageKnob* fKnobOrbitSpeedX; | |||
| ImageKnob* fKnobOrbitSpeedY; | |||
| ImageKnob* fKnobOrbitSizeX; | |||
| ImageKnob* fKnobOrbitSizeY; | |||
| ImageKnob* fKnobSubOrbitSpeed; | |||
| ImageKnob* fKnobSubOrbitSize; | |||
| ImageKnob* fKnobSubOrbitSmooth; | |||
| ImageKnob* fKnobsSynth[8]; | |||
| int page; | |||
| struct square { | |||
| float timer; | |||
| float maxTimer; | |||
| int x; | |||
| int y; | |||
| int size; | |||
| } squares[8][8]; | |||
| //sliders | |||
| ImageSlider* fSliderOrbitWaveX; | |||
| ImageSlider* fSliderOrbitWaveY; | |||
| ImageSlider* fSliderOrbitPhaseX; | |||
| ImageSlider* fSliderOrbitPhaseY; | |||
| ImageButton* fButtonAbout; | |||
| ImageButton* fButtonRandomize; | |||
| ImageButton* fButtonsPage[8]; | |||
| int tabOX; | |||
| int tabOY; | |||
| int tabW; | |||
| int tabH; | |||
| float tabPosX; | |||
| float tabTargetPosX; | |||
| int tabMarginX; | |||
| float getRandom() { | |||
| return static_cast <float> (rand()) / static_cast <float> (RAND_MAX); | |||
| } | |||
| // needed for XY canvas handling | |||
| bool fDragging; | |||
| bool fDragValid; | |||
| int fLastX; | |||
| int fLastY; | |||
| Rectangle<int> fCanvasArea; | |||
| float orbitX, orbitY, subOrbitX, subOrbitY; | |||
| float synthData[8][8]; //as per gui, [param][page] | |||
| float synthSound[8]; | |||
| bool isWithinSquare(float x, float y, float sX, float sY) { | |||
| if (x>=sX && x<sX+0.125) | |||
| if (y>=sY && y<sY+0.125) | |||
| return true; | |||
| return false; | |||
| }; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // GROOVEJUICEUI_HPP_INCLUDED | |||
| @@ -0,0 +1,243 @@ | |||
| /* | |||
| * Segment Synthesizer Design | |||
| * Implemented by Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz . | |||
| * | |||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | |||
| */ | |||
| #ifndef SYNTH_HXX_INCLUDED | |||
| #define SYNTH_HXX_INCLUDED | |||
| #include <cmath> | |||
| #include <cstdlib> | |||
| class CSynth | |||
| { | |||
| public: | |||
| CSynth() | |||
| { | |||
| waveBlend = 0; | |||
| freq = 0; | |||
| phaseAccum = 0; | |||
| playing = false; | |||
| cycleSize = 0; | |||
| sampleRate = 0; | |||
| notePlaying = 0; | |||
| env = 0; | |||
| envPhase = 0; | |||
| aCoeff=dCoeff=rCoeff=0; | |||
| stereo = 0; | |||
| shape = 0.5; | |||
| sustain=release=0.5f; | |||
| attack=0.1f; | |||
| sustain=0.0f; | |||
| mAmp = 0.5; | |||
| freqOffset = 0; | |||
| waves[0] = 0; | |||
| waves[1] = 0; | |||
| srand (static_cast <unsigned> (time(0))); | |||
| } | |||
| 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; | |||
| } | |||
| } | |||
| void setWave(int n, float nWave) { | |||
| waves[n] = nWave; | |||
| } | |||
| void setStereo(float nStereo) { | |||
| stereo = nStereo; | |||
| if (playing) { | |||
| freq = 440.0 * pow(2.0, (notePlaying - 69)/12); | |||
| freq += freq*(stereo/12); | |||
| } | |||
| } | |||
| float getRandom() { | |||
| return static_cast <float> (rand()) / static_cast <float> (RAND_MAX); | |||
| } | |||
| void setSustain(float nSustain) { | |||
| sustain = nSustain*4; | |||
| } | |||
| void setDecay(float nDecay) { | |||
| decay = nDecay*sampleRate; | |||
| } | |||
| void setRelease(float nRelease) { | |||
| release = nRelease*sampleRate/4; | |||
| } | |||
| void setShape(float nShape) { | |||
| shape = nShape; | |||
| } | |||
| void setMix(float nMix) { | |||
| mix = nMix; | |||
| } | |||
| void setCut(float nCut) { | |||
| cut = nCut; | |||
| } | |||
| void setReso(float nReso) { | |||
| reso = nReso; | |||
| } | |||
| float getWave(int i) { | |||
| return waves[i]; | |||
| } | |||
| void stop(int note) { | |||
| if (note==notePlaying) { | |||
| envPhase = 2; //release | |||
| } | |||
| } | |||
| void play(float note) { | |||
| notePlaying = note; | |||
| freq = 440.0 * pow(2.0, (notePlaying - 69)/12); | |||
| freq += freq*(freqOffset); | |||
| freq += freq*(stereo/12); | |||
| cycleSize = sampleRate/(freq/4); | |||
| playing = true; | |||
| phaseAccum = getRandom()*cycleSize; | |||
| //phaseAccum = 0; | |||
| env = 0.0f; | |||
| envPhase = 0; | |||
| //env init | |||
| decay = 1*sampleRate; | |||
| aCoeff = 1.0f - expf(-1/attack*16); | |||
| dCoeff = 1.0f - expf(-1/(decay/8)); | |||
| rCoeff = 1.0f - expf(-1/(release)); | |||
| } | |||
| float run() { | |||
| float out = 0; | |||
| if (playing) { | |||
| out = getSinePhase((phaseAccum/cycleSize)*(2*M_PI))*0.5; | |||
| //out += getSinePhase((phaseAccum/cycleSize)*2*(2*M_PI))*amps[0]*0.5; | |||
| //out = getSinePhase((phaseAccum/cycleSize)*2*M_PI); | |||
| //printf("out: %f\n", (waves[0]*3)); | |||
| //printf("out: %f\n", phaseAccum); | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*2*M_PI, (waves[0]*3)+1); | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*4*M_PI, (waves[0]*3)+1)*(sustain/4); | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*8*M_PI, (waves[0]*3)+1)*(sustain/4); | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*16*M_PI, (waves[0]*3)+1)*(sustain/4)/2; | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*6*M_PI, (waves[0]*3)+1)*shape; | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*12*M_PI, (waves[0]*3)+1)*(1-shape)/2; | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*3*M_PI, (waves[0]*3)+1)*(1-mix); | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*4*M_PI, (waves[1]*3)+1); | |||
| out += getBlendedPhase((phaseAccum/cycleSize)*2*M_PI*(getBlendedPhase((phaseAccum/cycleSize)*M_PI, (waves[1]*3)+1)), (waves[1]*3)+1)*mix; | |||
| //printf("out: %f\n", waves[0]*4); | |||
| //std::cout << (waves[0]*3)+1 << std::endl; | |||
| phaseAccum++; | |||
| if (phaseAccum>cycleSize) { | |||
| phaseAccum = 0; | |||
| } | |||
| //calculate amplitude envelope | |||
| if (envPhase==0) { | |||
| //attack phase | |||
| env+=aCoeff * ((1.0/0.63) - env); | |||
| if (env>1.0) envPhase+=2; | |||
| } else if (envPhase==1) { | |||
| //decay and sustain phase | |||
| env+=dCoeff * (sustain/4 - env); | |||
| } else { | |||
| //release phase | |||
| env += rCoeff * (1.0-(1.0/0.63) - env); | |||
| if (env<0.0) { playing = false; env = 0.0; } | |||
| } | |||
| //apply amplitude envelope | |||
| out*=env; | |||
| //apply master volume | |||
| //out*=mAmp*0.5; | |||
| //apply hard clipping | |||
| //if (out>1) out=1; | |||
| //if (out<-1) out=-1; | |||
| if (out!=0) { | |||
| //printf("out: %f\n", out); | |||
| } | |||
| } | |||
| return out; | |||
| } | |||
| void setSampleRate(float sr) { | |||
| sampleRate = sr; | |||
| attack = sampleRate/2; | |||
| decay = sampleRate/2; | |||
| release = sampleRate/2; | |||
| } | |||
| private: | |||
| /* vcf filter */ | |||
| float waves[2]; | |||
| float waveBlend; | |||
| float freq; | |||
| float freqOffset; | |||
| float stereo; | |||
| float mAmp; | |||
| float phaseAccum; | |||
| float cycleSize; | |||
| float sampleRate; | |||
| float notePlaying; | |||
| bool playing; | |||
| float mix; | |||
| float reso; | |||
| float cut; | |||
| float shape; | |||
| float attack, decay, sustain, release; | |||
| float env; | |||
| float envPhase; //0, 1(d+s), 2 | |||
| float aCoeff, dCoeff, rCoeff, gCoeff; | |||
| }; | |||
| #endif // SYNTH_HXX_INCLUDED | |||
| @@ -0,0 +1,76 @@ | |||
| /* | |||
| * 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; | |||
| } | |||
| float process (float input) | |||
| { | |||
| //run the shit | |||
| //for (long i=0; i<frames; i++) | |||
| //{ | |||
| pureInput = input; //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 */ | |||
| return 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,5 +1,5 @@ | |||
| /* | |||
| * Wobble Juice Plugin | |||
| * Power 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 | |||
| @@ -0,0 +1,36 @@ | |||
| /* | |||
| * ZamComp | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_NAME "ZamComp" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 1 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "urn:zamaudio:ZamComp" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -0,0 +1,30 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_ZAMCOMPARTWORK_HPP | |||
| #define BINARY_ZAMCOMPARTWORK_HPP | |||
| namespace ZamCompArtwork | |||
| { | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 7056; | |||
| const unsigned int knobWidth = 42; | |||
| const unsigned int knobHeight = 42; | |||
| extern const char* ledredData; | |||
| const unsigned int ledredDataSize = 484; | |||
| const unsigned int ledredWidth = 11; | |||
| const unsigned int ledredHeight = 11; | |||
| extern const char* ledyellowData; | |||
| const unsigned int ledyellowDataSize = 484; | |||
| const unsigned int ledyellowWidth = 11; | |||
| const unsigned int ledyellowHeight = 11; | |||
| extern const char* zamcompData; | |||
| const unsigned int zamcompDataSize = 256800; | |||
| const unsigned int zamcompWidth = 800; | |||
| const unsigned int zamcompHeight = 107; | |||
| } | |||
| #endif // BINARY_ZAMCOMPARTWORK_HPP | |||
| @@ -0,0 +1,290 @@ | |||
| /* | |||
| * ZamComp mono compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamCompPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamCompPlugin::ZamCompPlugin() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| d_setProgram(0); | |||
| // reset | |||
| d_deactivate(); | |||
| } | |||
| ZamCompPlugin::~ZamCompPlugin() | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramAttack: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Attack"; | |||
| parameter.symbol = "att"; | |||
| parameter.unit = "ms"; | |||
| parameter.ranges.def = 10.0f; | |||
| parameter.ranges.min = 0.1f; | |||
| parameter.ranges.max = 200.0f; | |||
| break; | |||
| case paramRelease: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Release"; | |||
| parameter.symbol = "rel"; | |||
| parameter.unit = "ms"; | |||
| parameter.ranges.def = 80.0f; | |||
| parameter.ranges.min = 50.0f; | |||
| parameter.ranges.max = 500.0f; | |||
| break; | |||
| case paramKnee: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Knee"; | |||
| parameter.symbol = "kn"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 8.0f; | |||
| break; | |||
| case paramRatio: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Ratio"; | |||
| parameter.symbol = "rat"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 4.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramThresh: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Threshold"; | |||
| parameter.symbol = "thr"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -60.0f; | |||
| parameter.ranges.max = 0.0f; | |||
| break; | |||
| case paramMakeup: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Makeup"; | |||
| parameter.symbol = "mak"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -30.0f; | |||
| parameter.ranges.max = 30.0f; | |||
| break; | |||
| case paramGainR: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "Gain Reduction"; | |||
| parameter.symbol = "gr"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 40.0f; | |||
| break; | |||
| case paramOutputLevel: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "Output Level"; | |||
| parameter.symbol = "outlevel"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = -45.0f; | |||
| parameter.ranges.min = -45.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| } | |||
| } | |||
| void ZamCompPlugin::d_initProgramName(uint32_t index, d_string& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float ZamCompPlugin::d_getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramAttack: | |||
| return attack; | |||
| break; | |||
| case paramRelease: | |||
| return release; | |||
| break; | |||
| case paramKnee: | |||
| return knee; | |||
| break; | |||
| case paramRatio: | |||
| return ratio; | |||
| break; | |||
| case paramThresh: | |||
| return thresdb; | |||
| break; | |||
| case paramMakeup: | |||
| return makeup; | |||
| break; | |||
| case paramGainR: | |||
| return gainr; | |||
| break; | |||
| case paramOutputLevel: | |||
| return outlevel; | |||
| break; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void ZamCompPlugin::d_setParameterValue(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramAttack: | |||
| attack = value; | |||
| break; | |||
| case paramRelease: | |||
| release = value; | |||
| break; | |||
| case paramKnee: | |||
| knee = value; | |||
| break; | |||
| case paramRatio: | |||
| ratio = value; | |||
| break; | |||
| case paramThresh: | |||
| thresdb = value; | |||
| break; | |||
| case paramMakeup: | |||
| makeup = value; | |||
| break; | |||
| case paramGainR: | |||
| gainr = value; | |||
| break; | |||
| case paramOutputLevel: | |||
| outlevel = value; | |||
| break; | |||
| } | |||
| } | |||
| void ZamCompPlugin::d_setProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default parameter values */ | |||
| attack = 10.0f; | |||
| release = 80.0f; | |||
| knee = 0.0f; | |||
| ratio = 4.0f; | |||
| thresdb = 0.0f; | |||
| makeup = 0.0f; | |||
| gainr = 0.0f; | |||
| outlevel = -45.f; | |||
| /* Default variable values */ | |||
| /* reset filter values */ | |||
| d_activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void ZamCompPlugin::d_activate() | |||
| { | |||
| } | |||
| void ZamCompPlugin::d_deactivate() | |||
| { | |||
| // all values to zero | |||
| } | |||
| void ZamCompPlugin::d_run(float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| float srate = d_getSampleRate(); | |||
| float width=(knee-0.99f)*6.f; | |||
| float cdb=0.f; | |||
| float attack_coeff = exp(-1000.f/(attack * srate)); | |||
| float release_coeff = exp(-1000.f/(release * srate)); | |||
| float gain = 1.f; | |||
| float xg, xl, yg, yl, y1; | |||
| uint32_t i; | |||
| float max = 0.f; | |||
| for (i = 0; i < frames; i++) { | |||
| yg=0.f; | |||
| xg = (inputs[0][i]==0.f) ? -160.f : to_dB(fabs(inputs[0][i])); | |||
| xg = sanitize_denormal(xg); | |||
| if (2.f*(xg-thresdb)<-width) { | |||
| yg = xg; | |||
| } else if (2.f*fabs(xg-thresdb)<=width) { | |||
| yg = xg + (1.f/ratio-1.f)*(xg-thresdb+width/2.f)*(xg-thresdb+width/2.f)/(2.f*width); | |||
| } else if (2.f*(xg-thresdb)>width) { | |||
| yg = thresdb + (xg-thresdb)/ratio; | |||
| } | |||
| yg = sanitize_denormal(yg); | |||
| xl = xg - yg; | |||
| old_y1 = sanitize_denormal(old_y1); | |||
| old_yl = sanitize_denormal(old_yl); | |||
| y1 = fmaxf(xl, release_coeff * old_y1+(1.f-release_coeff)*xl); | |||
| yl = attack_coeff * old_yl+(1.f-attack_coeff)*y1; | |||
| y1 = sanitize_denormal(y1); | |||
| yl = sanitize_denormal(yl); | |||
| cdb = -yl; | |||
| gain = from_dB(cdb); | |||
| gainr = yl; | |||
| outputs[0][i] = inputs[0][i]; | |||
| outputs[0][i] *= gain * from_dB(makeup); | |||
| max = (fabsf(outputs[0][i]) > max) ? fabsf(outputs[0][i]) : sanitize_denormal(max); | |||
| old_yl = yl; | |||
| old_y1 = y1; | |||
| } | |||
| outlevel = (max == 0.f) ? -45.f : to_dB(max); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new ZamCompPlugin(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,123 @@ | |||
| /* | |||
| * ZamComp mono compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMCOMPPLUGIN_HPP_INCLUDED | |||
| #define ZAMCOMPPLUGIN_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamCompPlugin : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramAttack = 0, | |||
| paramRelease, | |||
| paramKnee, | |||
| paramRatio, | |||
| paramThresh, | |||
| paramMakeup, | |||
| paramGainR, | |||
| paramOutputLevel, | |||
| paramCount | |||
| }; | |||
| ZamCompPlugin(); | |||
| ~ZamCompPlugin() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* d_getLabel() const noexcept override | |||
| { | |||
| return "ZamComp"; | |||
| } | |||
| const char* d_getMaker() const noexcept override | |||
| { | |||
| return "Damien Zammit"; | |||
| } | |||
| const char* d_getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t d_getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| long d_getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('Z', 'C', 'M', 'P'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void d_initParameter(uint32_t index, Parameter& parameter) ; | |||
| void d_initProgramName(uint32_t index, d_string& programName) ; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float d_getParameterValue(uint32_t index) const override; | |||
| void d_setParameterValue(uint32_t index, float value) override; | |||
| void d_setProgram(uint32_t index) ; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| static inline float | |||
| sanitize_denormal(float v) { | |||
| if(!std::isnormal(v)) | |||
| return 0.f; | |||
| return v; | |||
| } | |||
| static inline float | |||
| from_dB(float gdb) { | |||
| return (exp(gdb/20.f*log(10.f))); | |||
| } | |||
| static inline float | |||
| to_dB(float g) { | |||
| return (20.f*log10(g)); | |||
| } | |||
| void d_activate() override; | |||
| void d_deactivate() override; | |||
| void d_run(float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float attack,release,knee,ratio,thresdb,makeup,gainr,outlevel; //parameters | |||
| float old_yl, old_y1; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMCOMP_HPP_INCLUDED | |||
| @@ -0,0 +1,315 @@ | |||
| /* | |||
| * ZamComp mono compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamCompUI.hpp" | |||
| using DGL::Point; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamCompUI::ZamCompUI() | |||
| : UI() | |||
| { | |||
| // background | |||
| fImgBackground = Image(ZamCompArtwork::zamcompData, ZamCompArtwork::zamcompWidth, ZamCompArtwork::zamcompHeight, GL_BGR); | |||
| // led images | |||
| fLedRedImg = Image(ZamCompArtwork::ledredData, ZamCompArtwork::ledredWidth, ZamCompArtwork::ledredHeight); | |||
| fLedYellowImg = Image(ZamCompArtwork::ledyellowData, ZamCompArtwork::ledyellowWidth, ZamCompArtwork::ledyellowHeight); | |||
| // led values | |||
| fLedRedValue = 0.0f; | |||
| fLedYellowValue = 0.0f; | |||
| // knob | |||
| Image knobImage(ZamCompArtwork::knobData, ZamCompArtwork::knobWidth, ZamCompArtwork::knobHeight); | |||
| // knob | |||
| fKnobAttack = new ImageKnob(this, knobImage); | |||
| fKnobAttack->setPos(24, 45); | |||
| fKnobAttack->setRange(0.1f, 200.0f); | |||
| fKnobAttack->setStep(0.1f); | |||
| //fKnobAttack->setLogScale(true); | |||
| //fKnobAttack->setDefault(10.0f); | |||
| fKnobAttack->setRotationAngle(240); | |||
| fKnobAttack->setCallback(this); | |||
| fKnobRelease = new ImageKnob(this, knobImage); | |||
| fKnobRelease->setPos(108, 45); | |||
| fKnobRelease->setRange(50.0f, 500.0f); | |||
| fKnobRelease->setStep(1.0f); | |||
| //fKnobRelease->setDefault(80.0f); | |||
| fKnobRelease->setRotationAngle(240); | |||
| fKnobRelease->setCallback(this); | |||
| fKnobThresh = new ImageKnob(this, knobImage); | |||
| fKnobThresh->setPos(191.5, 45); | |||
| fKnobThresh->setRange(-60.0f, 0.0f); | |||
| fKnobThresh->setStep(1.0f); | |||
| //fKnobThresh->setDefault(0.0f); | |||
| fKnobThresh->setRotationAngle(240); | |||
| fKnobThresh->setCallback(this); | |||
| fKnobRatio = new ImageKnob(this, knobImage); | |||
| fKnobRatio->setPos(270, 45); | |||
| fKnobRatio->setRange(1.0f, 20.0f); | |||
| fKnobRatio->setStep(0.1f); | |||
| //fKnobRatio->setDefault(4.0f); | |||
| fKnobRatio->setRotationAngle(240); | |||
| fKnobRatio->setCallback(this); | |||
| fKnobKnee = new ImageKnob(this, knobImage); | |||
| fKnobKnee->setPos(348.5, 45); | |||
| fKnobKnee->setRange(0.0f, 8.0f); | |||
| fKnobKnee->setStep(0.1f); | |||
| //fKnobKnee->setDefault(0.0f); | |||
| fKnobKnee->setRotationAngle(240); | |||
| fKnobKnee->setCallback(this); | |||
| fKnobMakeup = new ImageKnob(this, knobImage); | |||
| fKnobMakeup->setPos(427.3, 45); | |||
| fKnobMakeup->setRange(-30.0f, 30.0f); | |||
| fKnobMakeup->setStep(1.0f); | |||
| //fKnobMakeup->setDefault(0.0f); | |||
| fKnobMakeup->setRotationAngle(240); | |||
| fKnobMakeup->setCallback(this); | |||
| } | |||
| ZamCompUI::~ZamCompUI() | |||
| { | |||
| delete fKnobAttack; | |||
| delete fKnobRelease; | |||
| delete fKnobThresh; | |||
| delete fKnobRatio; | |||
| delete fKnobKnee; | |||
| delete fKnobMakeup; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void ZamCompUI::d_parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case ZamCompPlugin::paramAttack: | |||
| fKnobAttack->setValue(value); | |||
| break; | |||
| case ZamCompPlugin::paramRelease: | |||
| fKnobRelease->setValue(value); | |||
| break; | |||
| case ZamCompPlugin::paramThresh: | |||
| fKnobThresh->setValue(value); | |||
| break; | |||
| case ZamCompPlugin::paramRatio: | |||
| fKnobRatio->setValue(value); | |||
| break; | |||
| case ZamCompPlugin::paramKnee: | |||
| fKnobKnee->setValue(value); | |||
| break; | |||
| case ZamCompPlugin::paramMakeup: | |||
| fKnobMakeup->setValue(value); | |||
| break; | |||
| case ZamCompPlugin::paramGainR: | |||
| if (fLedRedValue != value) | |||
| { | |||
| fLedRedValue = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case ZamCompPlugin::paramOutputLevel: | |||
| if (fLedYellowValue != value) | |||
| { | |||
| fLedYellowValue = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| void ZamCompUI::d_programChanged(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default values | |||
| fKnobAttack->setDefault(10.0f); | |||
| fKnobRelease->setDefault(80.0f); | |||
| fKnobThresh->setDefault(0.0f); | |||
| fKnobRatio->setDefault(4.0f); | |||
| fKnobKnee->setDefault(0.0f); | |||
| fKnobMakeup->setDefault(0.0f); | |||
| */ | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void ZamCompUI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobAttack) | |||
| d_editParameter(ZamCompPlugin::paramAttack, true); | |||
| else if (knob == fKnobRelease) | |||
| d_editParameter(ZamCompPlugin::paramRelease, true); | |||
| else if (knob == fKnobThresh) | |||
| d_editParameter(ZamCompPlugin::paramThresh, true); | |||
| else if (knob == fKnobRatio) | |||
| d_editParameter(ZamCompPlugin::paramRatio, true); | |||
| else if (knob == fKnobKnee) | |||
| d_editParameter(ZamCompPlugin::paramKnee, true); | |||
| else if (knob == fKnobMakeup) | |||
| d_editParameter(ZamCompPlugin::paramMakeup, true); | |||
| } | |||
| void ZamCompUI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobAttack) | |||
| d_editParameter(ZamCompPlugin::paramAttack, false); | |||
| else if (knob == fKnobRelease) | |||
| d_editParameter(ZamCompPlugin::paramRelease, false); | |||
| else if (knob == fKnobThresh) | |||
| d_editParameter(ZamCompPlugin::paramThresh, false); | |||
| else if (knob == fKnobRatio) | |||
| d_editParameter(ZamCompPlugin::paramRatio, false); | |||
| else if (knob == fKnobKnee) | |||
| d_editParameter(ZamCompPlugin::paramKnee, false); | |||
| else if (knob == fKnobMakeup) | |||
| d_editParameter(ZamCompPlugin::paramMakeup, false); | |||
| } | |||
| void ZamCompUI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| if (knob == fKnobAttack) | |||
| d_setParameterValue(ZamCompPlugin::paramAttack, value); | |||
| else if (knob == fKnobRelease) | |||
| d_setParameterValue(ZamCompPlugin::paramRelease, value); | |||
| else if (knob == fKnobThresh) | |||
| d_setParameterValue(ZamCompPlugin::paramThresh, value); | |||
| else if (knob == fKnobRatio) | |||
| d_setParameterValue(ZamCompPlugin::paramRatio, value); | |||
| else if (knob == fKnobKnee) | |||
| d_setParameterValue(ZamCompPlugin::paramKnee, value); | |||
| else if (knob == fKnobMakeup) | |||
| d_setParameterValue(ZamCompPlugin::paramMakeup, value); | |||
| } | |||
| void ZamCompUI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| // draw leds | |||
| static const float sLedSpacing = 15.5f; | |||
| static const int sLedInitialX = 498; | |||
| static const int sYellowLedStaticY = 16; | |||
| static const int sRedLedStaticY = 45; | |||
| int numRedLeds; | |||
| int numYellowLeds; | |||
| if (fLedRedValue >= 40.f) | |||
| numRedLeds = 12; | |||
| else if (fLedRedValue >= 30.f) | |||
| numRedLeds = 11; | |||
| else if (fLedRedValue >= 20.f) | |||
| numRedLeds = 10; | |||
| else if (fLedRedValue >= 15.f) | |||
| numRedLeds = 9; | |||
| else if (fLedRedValue >= 10.f) | |||
| numRedLeds = 8; | |||
| else if (fLedRedValue >= 8.f) | |||
| numRedLeds = 7; | |||
| else if (fLedRedValue >= 6.f) | |||
| numRedLeds = 6; | |||
| else if (fLedRedValue >= 5.f) | |||
| numRedLeds = 5; | |||
| else if (fLedRedValue >= 4.f) | |||
| numRedLeds = 4; | |||
| else if (fLedRedValue >= 3.f) | |||
| numRedLeds = 3; | |||
| else if (fLedRedValue >= 2.f) | |||
| numRedLeds = 2; | |||
| else if (fLedRedValue >= 1.f) | |||
| numRedLeds = 1; | |||
| else numRedLeds = 0; | |||
| for (int i=numRedLeds; i>0; --i) | |||
| fLedRedImg.draw(sLedInitialX + (12 - i)*sLedSpacing, sRedLedStaticY); | |||
| if (fLedYellowValue >= 20.f) | |||
| numYellowLeds = 19; | |||
| else if (fLedYellowValue >= 10.f) | |||
| numYellowLeds = 18; | |||
| else if (fLedYellowValue >= 8.f) | |||
| numYellowLeds = 17; | |||
| else if (fLedYellowValue >= 4.f) | |||
| numYellowLeds = 16; | |||
| else if (fLedYellowValue >= 2.f) | |||
| numYellowLeds = 15; | |||
| else if (fLedYellowValue >= 1.f) | |||
| numYellowLeds = 14; | |||
| else if (fLedYellowValue >= 0.f) | |||
| numYellowLeds = 13; | |||
| else if (fLedYellowValue >= -1.f) | |||
| numYellowLeds = 12; | |||
| else if (fLedYellowValue >= -2.f) | |||
| numYellowLeds = 11; | |||
| else if (fLedYellowValue >= -3.f) | |||
| numYellowLeds = 10; | |||
| else if (fLedYellowValue >= -4.f) | |||
| numYellowLeds = 9; | |||
| else if (fLedYellowValue >= -5.f) | |||
| numYellowLeds = 8; | |||
| else if (fLedYellowValue >= -6.f) | |||
| numYellowLeds = 7; | |||
| else if (fLedYellowValue >= -8.f) | |||
| numYellowLeds = 6; | |||
| else if (fLedYellowValue >= -10.f) | |||
| numYellowLeds = 5; | |||
| else if (fLedYellowValue >= -15.f) | |||
| numYellowLeds = 4; | |||
| else if (fLedYellowValue >= -20.f) | |||
| numYellowLeds = 3; | |||
| else if (fLedYellowValue >= -30.f) | |||
| numYellowLeds = 2; | |||
| else if (fLedYellowValue >= -40.f) | |||
| numYellowLeds = 1; | |||
| else numYellowLeds = 0; | |||
| if (numYellowLeds > 12) { | |||
| for (int i=12; i<numYellowLeds; ++i) | |||
| fLedRedImg.draw(sLedInitialX + i*sLedSpacing, sYellowLedStaticY); | |||
| for (int i=0; i<12; ++i) | |||
| fLedYellowImg.draw(sLedInitialX + i*sLedSpacing, sYellowLedStaticY); | |||
| } else { | |||
| for (int i=0; i<numYellowLeds; ++i) | |||
| fLedYellowImg.draw(sLedInitialX + i*sLedSpacing, sYellowLedStaticY); | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new ZamCompUI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,90 @@ | |||
| /* | |||
| * ZamComp mono compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMCOMPUI_HPP_INCLUDED | |||
| #define ZAMCOMPUI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageKnob.hpp" | |||
| #include "ZamCompArtwork.hpp" | |||
| #include "ZamCompPlugin.hpp" | |||
| using DGL::Image; | |||
| using DGL::ImageKnob; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamCompUI : public UI, | |||
| public ImageKnob::Callback | |||
| { | |||
| public: | |||
| ZamCompUI(); | |||
| ~ZamCompUI() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| unsigned int d_getWidth() const noexcept override | |||
| { | |||
| return ZamCompArtwork::zamcompWidth; | |||
| } | |||
| unsigned int d_getHeight() const noexcept override | |||
| { | |||
| return ZamCompArtwork::zamcompHeight; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void d_parameterChanged(uint32_t index, float value) override; | |||
| void d_programChanged(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageKnob* fKnobAttack; | |||
| ImageKnob* fKnobRelease; | |||
| ImageKnob* fKnobThresh; | |||
| ImageKnob* fKnobRatio; | |||
| ImageKnob* fKnobKnee; | |||
| ImageKnob* fKnobMakeup; | |||
| Image fLedRedImg; | |||
| float fLedRedValue; | |||
| Image fLedYellowImg; | |||
| float fLedYellowValue; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMCOMPUI_HPP_INCLUDED | |||
| @@ -0,0 +1,36 @@ | |||
| /* | |||
| * ZamCompX2 | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_NAME "ZamCompX2" | |||
| #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 0 | |||
| #define DISTRHO_PLUGIN_URI "urn:zamaudio:ZamCompX2" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -0,0 +1,67 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 DGL_IMAGE_TOGGLE_HPP_INCLUDED | |||
| #define DGL_IMAGE_TOGGLE_HPP_INCLUDED | |||
| #include "Image.hpp" | |||
| #include "Widget.hpp" | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| class ImageToggle : public Widget | |||
| { | |||
| public: | |||
| class Callback | |||
| { | |||
| public: | |||
| virtual ~Callback() {} | |||
| virtual void imageToggleClicked(ImageToggle* imageToggle, int button) = 0; | |||
| }; | |||
| ImageToggle(Window& parent, const Image& image); | |||
| ImageToggle(Widget* widget, const Image& image); | |||
| ImageToggle(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown); | |||
| ImageToggle(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown); | |||
| ImageToggle(const ImageToggle& imageToggle); | |||
| void setCallback(Callback* callback); | |||
| float getValue() override; | |||
| void setValue(float value) override; | |||
| protected: | |||
| void onDisplay() override; | |||
| bool onMouse(int button, bool press, int x, int y) override; | |||
| bool onMotion(int x, int y) override; | |||
| private: | |||
| Image fImageNormal; | |||
| Image fImageHover; | |||
| Image fImageDown; | |||
| Image* fCurImage; | |||
| int fCurButton; | |||
| Callback* fCallback; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| #endif // DGL_IMAGE_TOGGLE_HPP_INCLUDED | |||
| @@ -0,0 +1,55 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_ZAMCOMPX2ARTWORK_HPP | |||
| #define BINARY_ZAMCOMPX2ARTWORK_HPP | |||
| namespace ZamCompX2Artwork | |||
| { | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 7056; | |||
| const unsigned int knobWidth = 42; | |||
| const unsigned int knobHeight = 42; | |||
| extern const char* ledredData; | |||
| const unsigned int ledredDataSize = 484; | |||
| const unsigned int ledredWidth = 11; | |||
| const unsigned int ledredHeight = 11; | |||
| extern const char* ledyellowData; | |||
| const unsigned int ledyellowDataSize = 484; | |||
| const unsigned int ledyellowWidth = 11; | |||
| const unsigned int ledyellowHeight = 11; | |||
| extern const char* toggleoffData; | |||
| const unsigned int toggleoffDataSize = 1056; | |||
| const unsigned int toggleoffWidth = 12; | |||
| const unsigned int toggleoffHeight = 22; | |||
| extern const char* toggleoffhorizData; | |||
| const unsigned int toggleoffhorizDataSize = 1056; | |||
| const unsigned int toggleoffhorizWidth = 22; | |||
| const unsigned int toggleoffhorizHeight = 12; | |||
| extern const char* toggleonData; | |||
| const unsigned int toggleonDataSize = 1056; | |||
| const unsigned int toggleonWidth = 12; | |||
| const unsigned int toggleonHeight = 22; | |||
| extern const char* toggleonhorizData; | |||
| const unsigned int toggleonhorizDataSize = 1056; | |||
| const unsigned int toggleonhorizWidth = 22; | |||
| const unsigned int toggleonhorizHeight = 12; | |||
| extern const char* togglesliderData; | |||
| const unsigned int togglesliderDataSize = 676; | |||
| const unsigned int togglesliderWidth = 13; | |||
| const unsigned int togglesliderHeight = 13; | |||
| extern const char* zamcompx2Data; | |||
| const unsigned int zamcompx2DataSize = 256800; | |||
| const unsigned int zamcompx2Width = 800; | |||
| const unsigned int zamcompx2Height = 107; | |||
| } | |||
| #endif // BINARY_ZAMCOMPX2ARTWORK_HPP | |||
| @@ -0,0 +1,345 @@ | |||
| /* | |||
| * ZamCompX2 Stereo compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamCompX2Plugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamCompX2Plugin::ZamCompX2Plugin() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| d_setProgram(0); | |||
| // reset | |||
| d_deactivate(); | |||
| } | |||
| ZamCompX2Plugin::~ZamCompX2Plugin() | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramAttack: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Attack"; | |||
| parameter.symbol = "att"; | |||
| parameter.unit = "ms"; | |||
| parameter.ranges.def = 10.0f; | |||
| parameter.ranges.min = 0.1f; | |||
| parameter.ranges.max = 100.0f; | |||
| break; | |||
| case paramRelease: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Release"; | |||
| parameter.symbol = "rel"; | |||
| parameter.unit = "ms"; | |||
| parameter.ranges.def = 80.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 500.0f; | |||
| break; | |||
| case paramKnee: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Knee"; | |||
| parameter.symbol = "kn"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 9.0f; | |||
| break; | |||
| case paramRatio: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Ratio"; | |||
| parameter.symbol = "rat"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 4.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramThresh: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Threshold"; | |||
| parameter.symbol = "thr"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -80.0f; | |||
| parameter.ranges.max = 0.0f; | |||
| break; | |||
| case paramMakeup: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Makeup"; | |||
| parameter.symbol = "mak"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 30.0f; | |||
| break; | |||
| case paramGainRed: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "Gain Reduction"; | |||
| parameter.symbol = "gr"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramStereo: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; | |||
| parameter.name = "Stereolink"; | |||
| parameter.symbol = "stereo"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 1.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 2.0f; | |||
| break; | |||
| case paramOutputLevel: | |||
| parameter.hints = PARAMETER_IS_OUTPUT; | |||
| parameter.name = "Output Level"; | |||
| parameter.symbol = "outlevel"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = -45.0f; | |||
| parameter.ranges.min = -45.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| } | |||
| } | |||
| void ZamCompX2Plugin::d_initProgramName(uint32_t index, d_string& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float ZamCompX2Plugin::d_getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramAttack: | |||
| return attack; | |||
| break; | |||
| case paramRelease: | |||
| return release; | |||
| break; | |||
| case paramKnee: | |||
| return knee; | |||
| break; | |||
| case paramRatio: | |||
| return ratio; | |||
| break; | |||
| case paramThresh: | |||
| return thresdb; | |||
| break; | |||
| case paramMakeup: | |||
| return makeup; | |||
| break; | |||
| case paramGainRed: | |||
| return gainred; | |||
| break; | |||
| case paramStereo: | |||
| return stereolink; | |||
| break; | |||
| case paramOutputLevel: | |||
| return outlevel; | |||
| break; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void ZamCompX2Plugin::d_setParameterValue(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramAttack: | |||
| attack = value; | |||
| break; | |||
| case paramRelease: | |||
| release = value; | |||
| break; | |||
| case paramKnee: | |||
| knee = value; | |||
| break; | |||
| case paramRatio: | |||
| ratio = value; | |||
| break; | |||
| case paramThresh: | |||
| thresdb = value; | |||
| break; | |||
| case paramMakeup: | |||
| makeup = value; | |||
| break; | |||
| case paramGainRed: | |||
| gainred = value; | |||
| break; | |||
| case paramStereo: | |||
| stereolink = value; | |||
| break; | |||
| case paramOutputLevel: | |||
| outlevel = value; | |||
| break; | |||
| } | |||
| } | |||
| void ZamCompX2Plugin::d_setProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default parameter values */ | |||
| attack = 10.0f; | |||
| release = 80.0f; | |||
| knee = 0.0f; | |||
| ratio = 4.0f; | |||
| thresdb = 0.0f; | |||
| makeup = 0.0f; | |||
| gainred = 0.0f; | |||
| stereolink = 1.0f; | |||
| outlevel = -45.0f; | |||
| /* Default variable values */ | |||
| /* reset filter values */ | |||
| d_activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void ZamCompX2Plugin::d_activate() | |||
| { | |||
| oldL_yl = oldL_y1 = oldR_yl = oldR_y1 = 0.f; | |||
| } | |||
| void ZamCompX2Plugin::d_deactivate() | |||
| { | |||
| // all values to zero | |||
| } | |||
| void ZamCompX2Plugin::d_run(float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| float srate = d_getSampleRate(); | |||
| float width=(knee-0.99f)*6.f; | |||
| float cdb=0.f; | |||
| float attack_coeff = exp(-1000.f/(attack * srate)); | |||
| float release_coeff = exp(-1000.f/(release * srate)); | |||
| int stereo = (stereolink > 1.f) ? STEREOLINK_MAX : (stereolink > 0.f) ? STEREOLINK_AVERAGE : STEREOLINK_UNCOUPLED; | |||
| float max = 0.f; | |||
| float Lgain = 1.f; | |||
| float Rgain = 1.f; | |||
| float Lxg, Lxl, Lyg, Lyl, Ly1; | |||
| float Rxg, Rxl, Ryg, Ryl, Ry1; | |||
| uint32_t i; | |||
| for (i = 0; i < frames; i++) { | |||
| Lyg = Ryg = 0.f; | |||
| Lxg = (inputs[0][i]==0.f) ? -160.f : to_dB(fabs(inputs[0][i])); | |||
| Rxg = (inputs[1][i]==0.f) ? -160.f : to_dB(fabs(inputs[1][i])); | |||
| Lxg = sanitize_denormal(Lxg); | |||
| Rxg = sanitize_denormal(Rxg); | |||
| if (2.f*(Lxg-thresdb)<-width) { | |||
| Lyg = Lxg; | |||
| } else if (2.f*fabs(Lxg-thresdb)<=width) { | |||
| Lyg = Lxg + (1.f/ratio-1.f)*(Lxg-thresdb+width/2.f)*(Lxg-thresdb+width/2.f)/(2.f*width); | |||
| } else if (2.f*(Lxg-thresdb)>width) { | |||
| Lyg = thresdb + (Lxg-thresdb)/ratio; | |||
| } | |||
| Lyg = sanitize_denormal(Lyg); | |||
| if (2.f*(Rxg-thresdb)<-width) { | |||
| Ryg = Rxg; | |||
| } else if (2.f*fabs(Rxg-thresdb)<=width) { | |||
| Ryg = Rxg + (1.f/ratio-1.f)*(Rxg-thresdb+width/2.f)*(Rxg-thresdb+width/2.f)/(2.f*width); | |||
| } else if (2.f*(Rxg-thresdb)>width) { | |||
| Ryg = thresdb + (Rxg-thresdb)/ratio; | |||
| } | |||
| Ryg = sanitize_denormal(Ryg); | |||
| if (stereo == STEREOLINK_UNCOUPLED) { | |||
| Lxl = Lxg - Lyg; | |||
| Rxl = Rxg - Ryg; | |||
| } else if (stereo == STEREOLINK_MAX) { | |||
| Lxl = Rxl = fmaxf(Lxg - Lyg, Rxg - Ryg); | |||
| } else { | |||
| Lxl = Rxl = (Lxg - Lyg + Rxg - Ryg) / 2.f; | |||
| } | |||
| oldL_y1 = sanitize_denormal(oldL_y1); | |||
| oldR_y1 = sanitize_denormal(oldR_y1); | |||
| oldL_yl = sanitize_denormal(oldL_yl); | |||
| oldR_yl = sanitize_denormal(oldR_yl); | |||
| Ly1 = fmaxf(Lxl, release_coeff * oldL_y1+(1.f-release_coeff)*Lxl); | |||
| Lyl = attack_coeff * oldL_yl+(1.f-attack_coeff)*Ly1; | |||
| Ly1 = sanitize_denormal(Ly1); | |||
| Lyl = sanitize_denormal(Lyl); | |||
| cdb = -Lyl; | |||
| Lgain = from_dB(cdb); | |||
| gainred = Lyl; | |||
| Ry1 = fmaxf(Rxl, release_coeff * oldR_y1+(1.f-release_coeff)*Rxl); | |||
| Ryl = attack_coeff * oldR_yl+(1.f-attack_coeff)*Ry1; | |||
| Ry1 = sanitize_denormal(Ry1); | |||
| Ryl = sanitize_denormal(Ryl); | |||
| cdb = -Ryl; | |||
| Rgain = from_dB(cdb); | |||
| outputs[0][i] = inputs[0][i]; | |||
| outputs[0][i] *= Lgain * from_dB(makeup); | |||
| outputs[1][i] = inputs[1][i]; | |||
| outputs[1][i] *= Rgain * from_dB(makeup); | |||
| max = (fabsf(outputs[0][i]) > max) ? fabsf(outputs[0][i]) : sanitize_denormal(max); | |||
| max = (fabsf(outputs[1][i]) > max) ? fabsf(outputs[1][i]) : sanitize_denormal(max); | |||
| oldL_yl = Lyl; | |||
| oldR_yl = Ryl; | |||
| oldL_y1 = Ly1; | |||
| oldR_y1 = Ry1; | |||
| } | |||
| outlevel = (max == 0.f) ? -45.f : to_dB(max); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new ZamCompX2Plugin(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,128 @@ | |||
| /* | |||
| * ZamCompX2 stereo compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMCOMPX2PLUGIN_HPP_INCLUDED | |||
| #define ZAMCOMPX2PLUGIN_HPP_INCLUDED | |||
| #define STEREOLINK_UNCOUPLED 0 | |||
| #define STEREOLINK_AVERAGE 1 | |||
| #define STEREOLINK_MAX 2 | |||
| #include "DistrhoPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamCompX2Plugin : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramAttack = 0, | |||
| paramRelease, | |||
| paramKnee, | |||
| paramRatio, | |||
| paramThresh, | |||
| paramMakeup, | |||
| paramGainRed, | |||
| paramStereo, | |||
| paramOutputLevel, | |||
| paramCount | |||
| }; | |||
| ZamCompX2Plugin(); | |||
| ~ZamCompX2Plugin() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* d_getLabel() const noexcept override | |||
| { | |||
| return "ZamCompX2"; | |||
| } | |||
| const char* d_getMaker() const noexcept override | |||
| { | |||
| return "Damien Zammit"; | |||
| } | |||
| const char* d_getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t d_getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| long d_getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('Z', 'C', 'P', '2'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void d_initParameter(uint32_t index, Parameter& parameter) ; | |||
| void d_initProgramName(uint32_t index, d_string& programName) ; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float d_getParameterValue(uint32_t index) const override; | |||
| void d_setParameterValue(uint32_t index, float value) override; | |||
| void d_setProgram(uint32_t index) ; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| static inline float | |||
| sanitize_denormal(float v) { | |||
| if(!std::isnormal(v)) | |||
| return 0.f; | |||
| return v; | |||
| } | |||
| static inline float | |||
| from_dB(float gdb) { | |||
| return (exp(gdb/20.f*log(10.f))); | |||
| } | |||
| static inline float | |||
| to_dB(float g) { | |||
| return (20.f*log10(g)); | |||
| } | |||
| void d_activate() override; | |||
| void d_deactivate() override; | |||
| void d_run(float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float attack,release,knee,ratio,thresdb,makeup,gainred,stereolink,outlevel; //parameters | |||
| float oldL_yl, oldL_y1, oldR_yl, oldR_y1; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMCOMPX2_HPP_INCLUDED | |||
| @@ -0,0 +1,339 @@ | |||
| /* | |||
| * ZamCompX2 Stereo compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamCompX2UI.hpp" | |||
| using DGL::Point; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamCompX2UI::ZamCompX2UI() | |||
| : UI() | |||
| { | |||
| // background | |||
| fImgBackground = Image(ZamCompX2Artwork::zamcompx2Data, ZamCompX2Artwork::zamcompx2Width, ZamCompX2Artwork::zamcompx2Height, GL_BGR); | |||
| // led images | |||
| fLedRedImg = Image(ZamCompX2Artwork::ledredData, ZamCompX2Artwork::ledredWidth, ZamCompX2Artwork::ledredHeight); | |||
| fLedYellowImg = Image(ZamCompX2Artwork::ledyellowData, ZamCompX2Artwork::ledyellowWidth, ZamCompX2Artwork::ledyellowHeight); | |||
| // led values | |||
| fLedRedValue = 0.0f; | |||
| fLedYellowValue = 0.0f; | |||
| // knob | |||
| Image knobImage(ZamCompX2Artwork::knobData, ZamCompX2Artwork::knobWidth, ZamCompX2Artwork::knobHeight); | |||
| // knob | |||
| fKnobAttack = new ImageKnob(this, knobImage); | |||
| fKnobAttack->setPos(24, 45); | |||
| fKnobAttack->setRange(0.1f, 200.0f); | |||
| fKnobAttack->setStep(0.1f); | |||
| //fKnobAttack->setLogScale(true); | |||
| //fKnobAttack->setDefault(10.0f); | |||
| fKnobAttack->setRotationAngle(240); | |||
| fKnobAttack->setCallback(this); | |||
| fKnobRelease = new ImageKnob(this, knobImage); | |||
| fKnobRelease->setPos(108, 45); | |||
| fKnobRelease->setRange(50.0f, 500.0f); | |||
| fKnobRelease->setStep(1.0f); | |||
| //fKnobRelease->setDefault(80.0f); | |||
| fKnobRelease->setRotationAngle(240); | |||
| fKnobRelease->setCallback(this); | |||
| fKnobThresh = new ImageKnob(this, knobImage); | |||
| fKnobThresh->setPos(191.5, 45); | |||
| fKnobThresh->setRange(-60.0f, 0.0f); | |||
| fKnobThresh->setStep(1.0f); | |||
| //fKnobThresh->setDefault(0.0f); | |||
| fKnobThresh->setRotationAngle(240); | |||
| fKnobThresh->setCallback(this); | |||
| fKnobRatio = new ImageKnob(this, knobImage); | |||
| fKnobRatio->setPos(270, 45); | |||
| fKnobRatio->setRange(1.0f, 20.0f); | |||
| fKnobRatio->setStep(0.1f); | |||
| //fKnobRatio->setDefault(4.0f); | |||
| fKnobRatio->setRotationAngle(240); | |||
| fKnobRatio->setCallback(this); | |||
| fKnobKnee = new ImageKnob(this, knobImage); | |||
| fKnobKnee->setPos(348.5, 45); | |||
| fKnobKnee->setRange(0.0f, 8.0f); | |||
| fKnobKnee->setStep(0.1f); | |||
| //fKnobKnee->setDefault(0.0f); | |||
| fKnobKnee->setRotationAngle(240); | |||
| fKnobKnee->setCallback(this); | |||
| fKnobMakeup = new ImageKnob(this, knobImage); | |||
| fKnobMakeup->setPos(427.3, 45); | |||
| fKnobMakeup->setRange(-30.0f, 30.0f); | |||
| fKnobMakeup->setStep(1.0f); | |||
| //fKnobMakeup->setDefault(0.0f); | |||
| fKnobMakeup->setRotationAngle(240); | |||
| fKnobMakeup->setCallback(this); | |||
| Image toggleonImage(ZamCompX2Artwork::toggleonData, ZamCompX2Artwork::toggleonWidth, ZamCompX2Artwork::toggleonHeight); | |||
| Image toggleoffImage(ZamCompX2Artwork::toggleoffData, ZamCompX2Artwork::toggleoffWidth, ZamCompX2Artwork::toggleoffHeight); | |||
| Point<int> togglePosStart(652,72); | |||
| fToggleStereo = new ImageToggle(this, toggleoffImage, toggleoffImage, toggleonImage); | |||
| fToggleStereo->setPos(togglePosStart); | |||
| fToggleStereo->setCallback(this); | |||
| } | |||
| ZamCompX2UI::~ZamCompX2UI() | |||
| { | |||
| delete fKnobAttack; | |||
| delete fKnobRelease; | |||
| delete fKnobThresh; | |||
| delete fKnobRatio; | |||
| delete fKnobKnee; | |||
| delete fKnobMakeup; | |||
| delete fToggleStereo; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void ZamCompX2UI::d_parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case ZamCompX2Plugin::paramAttack: | |||
| fKnobAttack->setValue(value); | |||
| break; | |||
| case ZamCompX2Plugin::paramRelease: | |||
| fKnobRelease->setValue(value); | |||
| break; | |||
| case ZamCompX2Plugin::paramThresh: | |||
| fKnobThresh->setValue(value); | |||
| break; | |||
| case ZamCompX2Plugin::paramRatio: | |||
| fKnobRatio->setValue(value); | |||
| break; | |||
| case ZamCompX2Plugin::paramKnee: | |||
| fKnobKnee->setValue(value); | |||
| break; | |||
| case ZamCompX2Plugin::paramMakeup: | |||
| fKnobMakeup->setValue(value); | |||
| break; | |||
| case ZamCompX2Plugin::paramGainRed: | |||
| if (fLedRedValue != value) | |||
| { | |||
| fLedRedValue = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case ZamCompX2Plugin::paramOutputLevel: | |||
| if (fLedYellowValue != value) | |||
| { | |||
| fLedYellowValue = value; | |||
| repaint(); | |||
| } | |||
| break; | |||
| case ZamCompX2Plugin::paramStereo: | |||
| //fToggleStereo->setValue((int)value); | |||
| break; | |||
| } | |||
| } | |||
| void ZamCompX2UI::d_programChanged(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| /* | |||
| fKnobAttack->setValue(10.0f); | |||
| fKnobRelease->setValue(80.0f); | |||
| fKnobThresh->setValue(0.0f); | |||
| fKnobRatio->setValue(4.0f); | |||
| fKnobKnee->setValue(0.0f); | |||
| fKnobMakeup->setValue(0.0f); | |||
| */ | |||
| //fToggleStereo->setValue(1.f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void ZamCompX2UI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobAttack) | |||
| d_editParameter(ZamCompX2Plugin::paramAttack, true); | |||
| else if (knob == fKnobRelease) | |||
| d_editParameter(ZamCompX2Plugin::paramRelease, true); | |||
| else if (knob == fKnobThresh) | |||
| d_editParameter(ZamCompX2Plugin::paramThresh, true); | |||
| else if (knob == fKnobRatio) | |||
| d_editParameter(ZamCompX2Plugin::paramRatio, true); | |||
| else if (knob == fKnobKnee) | |||
| d_editParameter(ZamCompX2Plugin::paramKnee, true); | |||
| else if (knob == fKnobMakeup) | |||
| d_editParameter(ZamCompX2Plugin::paramMakeup, true); | |||
| } | |||
| void ZamCompX2UI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobAttack) | |||
| d_editParameter(ZamCompX2Plugin::paramAttack, false); | |||
| else if (knob == fKnobRelease) | |||
| d_editParameter(ZamCompX2Plugin::paramRelease, false); | |||
| else if (knob == fKnobThresh) | |||
| d_editParameter(ZamCompX2Plugin::paramThresh, false); | |||
| else if (knob == fKnobRatio) | |||
| d_editParameter(ZamCompX2Plugin::paramRatio, false); | |||
| else if (knob == fKnobKnee) | |||
| d_editParameter(ZamCompX2Plugin::paramKnee, false); | |||
| else if (knob == fKnobMakeup) | |||
| d_editParameter(ZamCompX2Plugin::paramMakeup, false); | |||
| } | |||
| void ZamCompX2UI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| if (knob == fKnobAttack) | |||
| d_setParameterValue(ZamCompX2Plugin::paramAttack, value); | |||
| else if (knob == fKnobRelease) | |||
| d_setParameterValue(ZamCompX2Plugin::paramRelease, value); | |||
| else if (knob == fKnobThresh) | |||
| d_setParameterValue(ZamCompX2Plugin::paramThresh, value); | |||
| else if (knob == fKnobRatio) | |||
| d_setParameterValue(ZamCompX2Plugin::paramRatio, value); | |||
| else if (knob == fKnobKnee) | |||
| d_setParameterValue(ZamCompX2Plugin::paramKnee, value); | |||
| else if (knob == fKnobMakeup) | |||
| d_setParameterValue(ZamCompX2Plugin::paramMakeup, value); | |||
| } | |||
| void ZamCompX2UI::imageToggleClicked(ImageToggle *toggle, int) | |||
| { | |||
| int flip = !toggle->getValue(); | |||
| if (toggle == fToggleStereo) { | |||
| d_setParameterValue(ZamCompX2Plugin::paramStereo, flip); | |||
| } | |||
| } | |||
| void ZamCompX2UI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| // draw leds | |||
| static const float sLedSpacing = 15.5f; | |||
| static const int sLedInitialX = 498; | |||
| static const int sYellowLedStaticY = 16; | |||
| static const int sRedLedStaticY = 45; | |||
| int numRedLeds; | |||
| int numYellowLeds; | |||
| if (fLedRedValue >= 40.f) | |||
| numRedLeds = 12; | |||
| else if (fLedRedValue >= 30.f) | |||
| numRedLeds = 11; | |||
| else if (fLedRedValue >= 20.f) | |||
| numRedLeds = 10; | |||
| else if (fLedRedValue >= 15.f) | |||
| numRedLeds = 9; | |||
| else if (fLedRedValue >= 10.f) | |||
| numRedLeds = 8; | |||
| else if (fLedRedValue >= 8.f) | |||
| numRedLeds = 7; | |||
| else if (fLedRedValue >= 6.f) | |||
| numRedLeds = 6; | |||
| else if (fLedRedValue >= 5.f) | |||
| numRedLeds = 5; | |||
| else if (fLedRedValue >= 4.f) | |||
| numRedLeds = 4; | |||
| else if (fLedRedValue >= 3.f) | |||
| numRedLeds = 3; | |||
| else if (fLedRedValue >= 2.f) | |||
| numRedLeds = 2; | |||
| else if (fLedRedValue >= 1.f) | |||
| numRedLeds = 1; | |||
| else numRedLeds = 0; | |||
| for (int i=numRedLeds; i>0; --i) | |||
| fLedRedImg.draw(sLedInitialX + (12 - i)*sLedSpacing, sRedLedStaticY); | |||
| if (fLedYellowValue >= 20.f) | |||
| numYellowLeds = 19; | |||
| else if (fLedYellowValue >= 10.f) | |||
| numYellowLeds = 18; | |||
| else if (fLedYellowValue >= 8.f) | |||
| numYellowLeds = 17; | |||
| else if (fLedYellowValue >= 4.f) | |||
| numYellowLeds = 16; | |||
| else if (fLedYellowValue >= 2.f) | |||
| numYellowLeds = 15; | |||
| else if (fLedYellowValue >= 1.f) | |||
| numYellowLeds = 14; | |||
| else if (fLedYellowValue >= 0.f) | |||
| numYellowLeds = 13; | |||
| else if (fLedYellowValue >= -1.f) | |||
| numYellowLeds = 12; | |||
| else if (fLedYellowValue >= -2.f) | |||
| numYellowLeds = 11; | |||
| else if (fLedYellowValue >= -3.f) | |||
| numYellowLeds = 10; | |||
| else if (fLedYellowValue >= -4.f) | |||
| numYellowLeds = 9; | |||
| else if (fLedYellowValue >= -5.f) | |||
| numYellowLeds = 8; | |||
| else if (fLedYellowValue >= -6.f) | |||
| numYellowLeds = 7; | |||
| else if (fLedYellowValue >= -8.f) | |||
| numYellowLeds = 6; | |||
| else if (fLedYellowValue >= -10.f) | |||
| numYellowLeds = 5; | |||
| else if (fLedYellowValue >= -15.f) | |||
| numYellowLeds = 4; | |||
| else if (fLedYellowValue >= -20.f) | |||
| numYellowLeds = 3; | |||
| else if (fLedYellowValue >= -30.f) | |||
| numYellowLeds = 2; | |||
| else if (fLedYellowValue >= -40.f) | |||
| numYellowLeds = 1; | |||
| else numYellowLeds = 0; | |||
| if (numYellowLeds > 12) { | |||
| for (int i=12; i<numYellowLeds; ++i) | |||
| fLedRedImg.draw(sLedInitialX + i*sLedSpacing, sYellowLedStaticY); | |||
| for (int i=0; i<12; ++i) | |||
| fLedYellowImg.draw(sLedInitialX + i*sLedSpacing, sYellowLedStaticY); | |||
| } else { | |||
| for (int i=0; i<numYellowLeds; ++i) | |||
| fLedYellowImg.draw(sLedInitialX + i*sLedSpacing, sYellowLedStaticY); | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new ZamCompX2UI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,97 @@ | |||
| /* | |||
| * ZamCompX2 stereo compressor | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMCOMPX2UI_HPP_INCLUDED | |||
| #define ZAMCOMPX2UI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageKnob.hpp" | |||
| #include "ImageToggle.hpp" | |||
| #include "ZamCompX2Artwork.hpp" | |||
| #include "ZamCompX2Plugin.hpp" | |||
| using DGL::Image; | |||
| using DGL::ImageKnob; | |||
| using DGL::ImageToggle; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamCompX2UI : public UI, | |||
| public ImageKnob::Callback, | |||
| public ImageToggle::Callback | |||
| { | |||
| public: | |||
| ZamCompX2UI(); | |||
| ~ZamCompX2UI() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| unsigned int d_getWidth() const noexcept override | |||
| { | |||
| return ZamCompX2Artwork::zamcompx2Width; | |||
| } | |||
| unsigned int d_getHeight() const noexcept override | |||
| { | |||
| return ZamCompX2Artwork::zamcompx2Height; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void d_parameterChanged(uint32_t index, float value) override; | |||
| void d_programChanged(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void imageToggleClicked(ImageToggle *toggle, int button) override; | |||
| void onDisplay() override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageKnob* fKnobAttack; | |||
| ImageKnob* fKnobRelease; | |||
| ImageKnob* fKnobThresh; | |||
| ImageKnob* fKnobRatio; | |||
| ImageKnob* fKnobKnee; | |||
| ImageKnob* fKnobMakeup; | |||
| Image fImgToggleSlider; | |||
| ImageToggle* fToggleStereo; | |||
| Image fLedRedImg; | |||
| float fLedRedValue; | |||
| Image fLedYellowImg; | |||
| float fLedYellowValue; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMCOMPX2UI_HPP_INCLUDED | |||
| @@ -0,0 +1,36 @@ | |||
| /* | |||
| * ZamEQ2 | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_NAME "ZamEQ2" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 1 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "urn:zamaudio:ZamEQ2" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -0,0 +1,45 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_ZAMEQ2ARTWORK_HPP | |||
| #define BINARY_ZAMEQ2ARTWORK_HPP | |||
| namespace ZamEQ2Artwork | |||
| { | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 7056; | |||
| const unsigned int knobWidth = 42; | |||
| const unsigned int knobHeight = 42; | |||
| extern const char* ledredData; | |||
| const unsigned int ledredDataSize = 484; | |||
| const unsigned int ledredWidth = 11; | |||
| const unsigned int ledredHeight = 11; | |||
| extern const char* ledyellowData; | |||
| const unsigned int ledyellowDataSize = 484; | |||
| const unsigned int ledyellowWidth = 11; | |||
| const unsigned int ledyellowHeight = 11; | |||
| extern const char* toggleoffData; | |||
| const unsigned int toggleoffDataSize = 90048; | |||
| const unsigned int toggleoffWidth = 112; | |||
| const unsigned int toggleoffHeight = 201; | |||
| extern const char* toggleonData; | |||
| const unsigned int toggleonDataSize = 88440; | |||
| const unsigned int toggleonWidth = 110; | |||
| const unsigned int toggleonHeight = 201; | |||
| extern const char* togglesliderData; | |||
| const unsigned int togglesliderDataSize = 676; | |||
| const unsigned int togglesliderWidth = 13; | |||
| const unsigned int togglesliderHeight = 13; | |||
| extern const char* zameq2Data; | |||
| const unsigned int zameq2DataSize = 426600; | |||
| const unsigned int zameq2Width = 632; | |||
| const unsigned int zameq2Height = 225; | |||
| } | |||
| #endif // BINARY_ZAMEQ2ARTWORK_HPP | |||
| @@ -0,0 +1,437 @@ | |||
| /* | |||
| * ZamEQ2 2 band parametric equaliser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamEQ2Plugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamEQ2Plugin::ZamEQ2Plugin() | |||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | |||
| { | |||
| // set default values | |||
| d_setProgram(0); | |||
| // reset | |||
| d_deactivate(); | |||
| } | |||
| ZamEQ2Plugin::~ZamEQ2Plugin() | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramGain1: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Boost/Cut 1"; | |||
| parameter.symbol = "boost1"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -50.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramQ1: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; | |||
| parameter.name = "Bandwidth 1"; | |||
| parameter.symbol = "bw1"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 2.0f; | |||
| parameter.ranges.min = 0.1f; | |||
| parameter.ranges.max = 6.0f; | |||
| break; | |||
| case paramFreq1: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; | |||
| parameter.name = "Frequency 1"; | |||
| parameter.symbol = "f1"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 500.0f; | |||
| parameter.ranges.min = 20.0f; | |||
| parameter.ranges.max = 14000.0f; | |||
| break; | |||
| case paramGain2: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Boost/Cut 2"; | |||
| parameter.symbol = "boost2"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -50.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramQ2: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; | |||
| parameter.name = "Bandwidth 2"; | |||
| parameter.symbol = "bw2"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 2.0f; | |||
| parameter.ranges.min = 0.1f; | |||
| parameter.ranges.max = 6.0f; | |||
| break; | |||
| case paramFreq2: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; | |||
| parameter.name = "Frequency 2"; | |||
| parameter.symbol = "f2"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 3000.0f; | |||
| parameter.ranges.min = 20.0f; | |||
| parameter.ranges.max = 14000.0f; | |||
| break; | |||
| case paramGainL: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Boost/Cut L"; | |||
| parameter.symbol = "boostl"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -50.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramFreqL: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; | |||
| parameter.name = "Frequency L"; | |||
| parameter.symbol = "fl"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 250.0f; | |||
| parameter.ranges.min = 20.0f; | |||
| parameter.ranges.max = 14000.0f; | |||
| break; | |||
| case paramGainH: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Boost/Cut H"; | |||
| parameter.symbol = "boosth"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -50.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramFreqH: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; | |||
| parameter.name = "Frequency H"; | |||
| parameter.symbol = "fh"; | |||
| parameter.unit = "Hz"; | |||
| parameter.ranges.def = 8000.0f; | |||
| parameter.ranges.min = 20.0f; | |||
| parameter.ranges.max = 14000.0f; | |||
| break; | |||
| case paramMaster: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Master Gain"; | |||
| parameter.symbol = "master"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -12.0f; | |||
| parameter.ranges.max = 12.0f; | |||
| break; | |||
| case paramTogglePeaks: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; | |||
| parameter.name = "Peaks ON"; | |||
| parameter.symbol = "peaks"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| } | |||
| } | |||
| void ZamEQ2Plugin::d_initProgramName(uint32_t index, d_string& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float ZamEQ2Plugin::d_getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramGain1: | |||
| return gain1; | |||
| break; | |||
| case paramQ1: | |||
| return q1; | |||
| break; | |||
| case paramFreq1: | |||
| return freq1; | |||
| break; | |||
| case paramGain2: | |||
| return gain2; | |||
| break; | |||
| case paramQ2: | |||
| return q2; | |||
| break; | |||
| case paramFreq2: | |||
| return freq2; | |||
| break; | |||
| case paramGainL: | |||
| return gainl; | |||
| break; | |||
| case paramFreqL: | |||
| return freql; | |||
| break; | |||
| case paramGainH: | |||
| return gainh; | |||
| break; | |||
| case paramFreqH: | |||
| return freqh; | |||
| break; | |||
| case paramMaster: | |||
| return master; | |||
| break; | |||
| case paramTogglePeaks: | |||
| return togglepeaks; | |||
| break; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void ZamEQ2Plugin::d_setParameterValue(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramGain1: | |||
| gain1 = value; | |||
| break; | |||
| case paramQ1: | |||
| q1 = value; | |||
| break; | |||
| case paramFreq1: | |||
| freq1 = value; | |||
| break; | |||
| case paramGain2: | |||
| gain2 = value; | |||
| break; | |||
| case paramQ2: | |||
| q2 = value; | |||
| break; | |||
| case paramFreq2: | |||
| freq2 = value; | |||
| break; | |||
| case paramGainL: | |||
| gainl = value; | |||
| break; | |||
| case paramFreqL: | |||
| freql = value; | |||
| break; | |||
| case paramGainH: | |||
| gainh = value; | |||
| break; | |||
| case paramFreqH: | |||
| freqh = value; | |||
| break; | |||
| case paramMaster: | |||
| master = value; | |||
| break; | |||
| case paramTogglePeaks: | |||
| togglepeaks = value; | |||
| break; | |||
| } | |||
| } | |||
| void ZamEQ2Plugin::d_setProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default parameter values */ | |||
| gain1 = 0.0f; | |||
| q1 = 1.0f; | |||
| freq1 = 500.0f; | |||
| gain2 = 0.0f; | |||
| q2 = 1.0f; | |||
| freq2 = 3000.0f; | |||
| gainl = 0.0f; | |||
| freql = 250.0f; | |||
| gainh = 0.0f; | |||
| freqh = 8000.0f; | |||
| master = 0.f; | |||
| togglepeaks = 0.f; | |||
| /* Default variable values */ | |||
| /* reset filter values */ | |||
| d_activate(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void ZamEQ2Plugin::d_activate() | |||
| { | |||
| int i; | |||
| for (i = 0; i < MAX_FILT; ++i) { | |||
| x1[0][i] = x2[0][i] = 0.f; | |||
| y1[0][i] = y2[0][i] = 0.f; | |||
| b0[0][i] = b1[0][i] = b2[0][i] = 0.f; | |||
| a1[0][i] = a2[0][i] = 0.f; | |||
| } | |||
| } | |||
| void ZamEQ2Plugin::d_deactivate() | |||
| { | |||
| // all values to zero | |||
| } | |||
| void ZamEQ2Plugin::lowshelf(int i, int ch, float srate, float fc, float g) | |||
| { | |||
| float k, v0; | |||
| k = tanf(M_PI * fc / srate); | |||
| v0 = powf(10., g / 20.); | |||
| if (g < 0.f) { | |||
| // LF cut | |||
| float denom = v0 + sqrt(2. * v0)*k + k*k; | |||
| b0[ch][i] = v0 * (1. + sqrt(2.)*k + k*k) / denom; | |||
| b1[ch][i] = 2. * v0*(k*k - 1.) / denom; | |||
| b2[ch][i] = v0 * (1. - sqrt(2.)*k + k*k) / denom; | |||
| a1[ch][i] = 2. * (k*k - v0) / denom; | |||
| a2[ch][i] = (v0 - sqrt(2. * v0)*k + k*k) / denom; | |||
| } else { | |||
| // LF boost | |||
| float denom = 1. + sqrt(2.)*k + k*k; | |||
| b0[ch][i] = (1. + sqrt(2. * v0)*k + v0*k*k) / denom; | |||
| b1[ch][i] = 2. * (v0*k*k - 1.) / denom; | |||
| b2[ch][i] = (1. - sqrt(2. * v0)*k + v0*k*k) / denom; | |||
| a1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| a2[ch][i] = (1. - sqrt(2.)*k + k*k) / denom; | |||
| } | |||
| } | |||
| void ZamEQ2Plugin::highshelf(int i, int ch, float srate, float fc, float g) | |||
| { | |||
| float k, v0; | |||
| k = tanf(M_PI * fc / srate); | |||
| v0 = powf(10., g / 20.); | |||
| if (g < 0.f) { | |||
| // HF cut | |||
| float denom = 1. + sqrt(2. * v0)*k + v0*k*k; | |||
| b0[ch][i] = v0*(1. + sqrt(2.)*k + k*k) / denom; | |||
| b1[ch][i] = 2. * v0*(k*k - 1.) / denom; | |||
| b2[ch][i] = v0*(1. - sqrt(2.)*k + k*k) / denom; | |||
| a1[ch][i] = 2. * (v0*k*k - 1.) / denom; | |||
| a2[ch][i] = (1. - sqrt(2. * v0)*k + v0*k*k) / denom; | |||
| } else { | |||
| // HF boost | |||
| float denom = 1. + sqrt(2.)*k + k*k; | |||
| b0[ch][i] = (v0 + sqrt(2. * v0)*k + k*k) / denom; | |||
| b1[ch][i] = 2. * (k*k - v0) / denom; | |||
| b2[ch][i] = (v0 - sqrt(2. * v0)*k + k*k) / denom; | |||
| a1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| a2[ch][i] = (1. - sqrt(2.)*k + k*k) / denom; | |||
| } | |||
| } | |||
| void ZamEQ2Plugin::peq(int i, int ch, float srate, float fc, float g, float bw) | |||
| { | |||
| float k, v0, q; | |||
| k = tanf(M_PI * fc / srate); | |||
| v0 = powf(10., g / 20.); | |||
| q = powf(2., 1./bw)/(powf(2., bw) - 1.); //q from octave bw | |||
| if (g < 0.f) { | |||
| // cut | |||
| float denom = 1. + k/(v0*q) + k*k; | |||
| b0[ch][i] = (1. + k/q + k*k) / denom; | |||
| b1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| b2[ch][i] = (1. - k/q + k*k) / denom; | |||
| a1[ch][i] = b1[ch][i]; | |||
| a2[ch][i] = (1. - k/(v0*q) + k*k) / denom; | |||
| } else { | |||
| // boost | |||
| float denom = 1. + k/q + k*k; | |||
| b0[ch][i] = (1. + k*v0/q + k*k) / denom; | |||
| b1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| b2[ch][i] = (1. - k*v0/q + k*k) / denom; | |||
| a1[ch][i] = b1[ch][i]; | |||
| a2[ch][i] = (1. - k/q + k*k) / denom; | |||
| } | |||
| } | |||
| float ZamEQ2Plugin::run_filter(int i, int ch, double in) | |||
| { | |||
| double out; | |||
| in = sanitize_denormal(in); | |||
| out = in * b0[ch][i] + x1[ch][i] * b1[ch][i] | |||
| + x2[ch][i] * b2[ch][i] | |||
| - y1[ch][i] * a1[ch][i] | |||
| - y2[ch][i] * a2[ch][i] + 1e-20f; | |||
| out = sanitize_denormal(out); | |||
| x2[ch][i] = sanitize_denormal(x1[ch][i]); | |||
| y2[ch][i] = sanitize_denormal(y1[ch][i]); | |||
| x1[ch][i] = in; | |||
| y1[ch][i] = out; | |||
| return (float) out; | |||
| } | |||
| void ZamEQ2Plugin::d_run(float** inputs, float** outputs, uint32_t frames) | |||
| { | |||
| float srate = d_getSampleRate(); | |||
| lowshelf(0, 0, srate, freql, gainl); | |||
| peq(1, 0, srate, freq1, gain1, q1); | |||
| peq(2, 0, srate, freq2, gain2, q2); | |||
| highshelf(3, 0, srate, freqh, gainh); | |||
| for (uint32_t i = 0; i < frames; i++) { | |||
| double tmp,tmpl, tmph; | |||
| double in = inputs[0][i]; | |||
| in = sanitize_denormal(in); | |||
| //lowshelf | |||
| tmpl = (gainl == 0.f) ? in : run_filter(0, 0, in); | |||
| //highshelf | |||
| tmph = (gainh == 0.f) ? tmpl : run_filter(3, 0, tmpl); | |||
| //parametric1 | |||
| tmp = (gain1 == 0.f) ? tmph : run_filter(1, 0, tmph); | |||
| //parametric2 | |||
| tmpl = (gain2 == 0.f) ? tmp : run_filter(2, 0, tmp); | |||
| outputs[0][i] = inputs[0][i]; | |||
| outputs[0][i] = (float) tmpl; | |||
| outputs[0][i] *= from_dB(master); | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new ZamEQ2Plugin(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,140 @@ | |||
| /* | |||
| * ZamEQ2 2 band parametric equaliser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMCOMPPLUGIN_HPP_INCLUDED | |||
| #define ZAMCOMPPLUGIN_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| #define MAX_FILT 4 | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamEQ2Plugin : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramGain1 = 0, | |||
| paramQ1, | |||
| paramFreq1, | |||
| paramGain2, | |||
| paramQ2, | |||
| paramFreq2, | |||
| paramGainL, | |||
| paramFreqL, | |||
| paramGainH, | |||
| paramFreqH, | |||
| paramMaster, | |||
| paramTogglePeaks, | |||
| paramCount | |||
| }; | |||
| ZamEQ2Plugin(); | |||
| ~ZamEQ2Plugin() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* d_getLabel() const noexcept override | |||
| { | |||
| return "ZamEQ2"; | |||
| } | |||
| const char* d_getMaker() const noexcept override | |||
| { | |||
| return "Damien Zammit"; | |||
| } | |||
| const char* d_getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t d_getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| long d_getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('Z', 'E', 'Q', '2'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void d_initParameter(uint32_t index, Parameter& parameter) ; | |||
| void d_initProgramName(uint32_t index, d_string& programName) ; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float d_getParameterValue(uint32_t index) const override; | |||
| void d_setParameterValue(uint32_t index, float value) override; | |||
| void d_setProgram(uint32_t index) ; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| static inline double | |||
| sanitize_denormal(double v) { | |||
| if(!std::isnormal(v)) | |||
| return 0.f; | |||
| return v; | |||
| } | |||
| static inline double | |||
| from_dB(double gdb) { | |||
| return (exp(gdb/20.f*log(10.f))); | |||
| } | |||
| static inline double | |||
| to_dB(double g) { | |||
| return (20.f*log10(g)); | |||
| } | |||
| static inline int | |||
| sign(double x) { | |||
| return (x >= 0.f ? 1 : -1); | |||
| } | |||
| void d_activate() override; | |||
| void d_deactivate() override; | |||
| void d_run(float** inputs, float** outputs, uint32_t frames) override; | |||
| void peq(int i, int ch, float srate, float fc, float g, float bw); | |||
| void lowshelf(int i, int ch, float srate, float fc, float g); | |||
| void highshelf(int i, int ch, float srate, float fc, float g); | |||
| float run_filter(int i, int ch, double in); | |||
| double x1[1][MAX_FILT], x2[1][MAX_FILT], y1[1][MAX_FILT], y2[1][MAX_FILT]; | |||
| double b0[1][MAX_FILT], b1[1][MAX_FILT], b2[1][MAX_FILT]; | |||
| double a1[1][MAX_FILT], a2[1][MAX_FILT]; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float gain1,q1,freq1,gain2,q2,freq2,gainl,freql,gainh,freqh,master,togglepeaks; //parameters | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMCOMP_HPP_INCLUDED | |||
| @@ -0,0 +1,468 @@ | |||
| /* | |||
| * ZamEQ2 2 band parametric equaliser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamEQ2UI.hpp" | |||
| using DGL::Point; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamEQ2UI::ZamEQ2UI() | |||
| : UI() | |||
| { | |||
| // background | |||
| fImgBackground = Image(ZamEQ2Artwork::zameq2Data, ZamEQ2Artwork::zameq2Width, ZamEQ2Artwork::zameq2Height, GL_BGR); | |||
| // toggle image | |||
| Image sliderImage(ZamEQ2Artwork::togglesliderData, ZamEQ2Artwork::togglesliderWidth, ZamEQ2Artwork::togglesliderHeight); | |||
| // knob | |||
| Image knobImage(ZamEQ2Artwork::knobData, ZamEQ2Artwork::knobWidth, ZamEQ2Artwork::knobHeight); | |||
| // knob | |||
| fKnobGain1 = new ImageKnob(this, knobImage); | |||
| fKnobGain1->setPos(91, 172); | |||
| fKnobGain1->setRange(-50.f, 20.0f); | |||
| fKnobGain1->setRotationAngle(240); | |||
| //fKnobGain1->setDefault(0.0f); | |||
| fKnobGain1->setCallback(this); | |||
| fKnobQ1 = new ImageKnob(this, knobImage); | |||
| fKnobQ1->setPos(91, 122); | |||
| fKnobQ1->setRange(0.1f, 6.0f); | |||
| //fKnobQ1->setLogScale(true); | |||
| fKnobQ1->setRotationAngle(240); | |||
| //fKnobQ1->setDefault(1.0f); | |||
| fKnobQ1->setCallback(this); | |||
| fKnobFreq1 = new ImageKnob(this, knobImage); | |||
| fKnobFreq1->setPos(23, 144); | |||
| fKnobFreq1->setRange(20.f, 14000.0f); | |||
| //fKnobFreq1->setLogScale(true); | |||
| fKnobFreq1->setRotationAngle(240); | |||
| //fKnobFreq1->setDefault(500.0f); | |||
| fKnobFreq1->setCallback(this); | |||
| fKnobGain2 = new ImageKnob(this, knobImage); | |||
| fKnobGain2->setPos(567, 172); | |||
| fKnobGain2->setRange(-50.f, 20.0f); | |||
| fKnobGain2->setRotationAngle(240); | |||
| //fKnobGain2->setDefault(0.0f); | |||
| fKnobGain2->setCallback(this); | |||
| fKnobQ2 = new ImageKnob(this, knobImage); | |||
| fKnobQ2->setPos(567, 122); | |||
| fKnobQ2->setRange(0.1f, 6.0f); | |||
| //fKnobQ2->setLogScale(true); | |||
| fKnobQ2->setRotationAngle(240); | |||
| //fKnobQ2->setDefault(1.0f); | |||
| fKnobQ2->setCallback(this); | |||
| fKnobFreq2 = new ImageKnob(this, knobImage); | |||
| fKnobFreq2->setPos(499, 144); | |||
| fKnobFreq2->setRange(20.f, 14000.0f); | |||
| //fKnobFreq2->setLogScale(true); | |||
| fKnobFreq2->setRotationAngle(240); | |||
| //fKnobFreq2->setDefault(3000.0f); | |||
| fKnobFreq2->setCallback(this); | |||
| fKnobGainL = new ImageKnob(this, knobImage); | |||
| fKnobGainL->setPos(91, 52); | |||
| fKnobGainL->setRange(-50.f, 20.0f); | |||
| fKnobGainL->setRotationAngle(240); | |||
| //fKnobGainL->setDefault(0.0f); | |||
| fKnobGainL->setCallback(this); | |||
| fKnobFreqL = new ImageKnob(this, knobImage); | |||
| fKnobFreqL->setPos(23, 23); | |||
| fKnobFreqL->setRange(20.f, 14000.0f); | |||
| //fKnobFreqL->setLogScale(true); | |||
| fKnobFreqL->setRotationAngle(240); | |||
| //fKnobFreqL->setDefault(250.0f); | |||
| fKnobFreqL->setCallback(this); | |||
| fKnobGainH = new ImageKnob(this, knobImage); | |||
| fKnobGainH->setPos(567, 53); | |||
| fKnobGainH->setRange(-50.f, 20.0f); | |||
| fKnobGainH->setRotationAngle(240); | |||
| //fKnobGainH->setDefault(0.0f); | |||
| fKnobGainH->setCallback(this); | |||
| fKnobFreqH = new ImageKnob(this, knobImage); | |||
| fKnobFreqH->setPos(499, 24); | |||
| fKnobFreqH->setRange(20.f, 14000.0f); | |||
| //fKnobFreqH->setLogScale(true); | |||
| fKnobFreqH->setRotationAngle(240); | |||
| //fKnobFreqH->setDefault(8000.0f); | |||
| fKnobFreqH->setCallback(this); | |||
| Point<int> masterPosStart(211,204); | |||
| Point<int> masterPosEnd(288,204); | |||
| fSliderMaster = new ImageSlider(this, sliderImage); | |||
| fSliderMaster->setStartPos(masterPosStart); | |||
| fSliderMaster->setEndPos(masterPosEnd); | |||
| fSliderMaster->setRange(-12.f,12.f); | |||
| fSliderMaster->setValue(0.f); | |||
| fSliderMaster->setStep(6.f); | |||
| fSliderMaster->setCallback(this); | |||
| fCanvasArea.setPos(165,10); | |||
| fCanvasArea.setSize(305,180); | |||
| } | |||
| ZamEQ2UI::~ZamEQ2UI() | |||
| { | |||
| delete fKnobGain1; | |||
| delete fKnobQ1; | |||
| delete fKnobFreq1; | |||
| delete fKnobGain2; | |||
| delete fKnobQ2; | |||
| delete fKnobFreq2; | |||
| delete fKnobGainL; | |||
| delete fKnobFreqL; | |||
| delete fKnobGainH; | |||
| delete fKnobFreqH; | |||
| delete fSliderMaster; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void ZamEQ2UI::d_parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case ZamEQ2Plugin::paramGain1: | |||
| fKnobGain1->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramQ1: | |||
| fKnobQ1->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramFreq1: | |||
| fKnobFreq1->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramGain2: | |||
| fKnobGain2->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramQ2: | |||
| fKnobQ2->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramFreq2: | |||
| fKnobFreq2->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramGainL: | |||
| fKnobGainL->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramFreqL: | |||
| fKnobFreqL->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramGainH: | |||
| fKnobGainH->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramFreqH: | |||
| fKnobFreqH->setValue(value); | |||
| break; | |||
| case ZamEQ2Plugin::paramMaster: | |||
| fSliderMaster->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| void ZamEQ2UI::d_programChanged(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| /* | |||
| fKnobGain1->resetDefault(); | |||
| fKnobQ1->resetDefault(); | |||
| fKnobFreq1->resetDefault(); | |||
| fKnobGain2->resetDefault(); | |||
| fKnobQ2->resetDefault(); | |||
| fKnobFreq2->resetDefault(); | |||
| fKnobGainL->resetDefault(); | |||
| fKnobFreqL->resetDefault(); | |||
| fKnobGainH->resetDefault(); | |||
| fKnobFreqH->resetDefault(); | |||
| */ | |||
| fSliderMaster->setValue(0.f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void ZamEQ2UI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobGain1) | |||
| d_editParameter(ZamEQ2Plugin::paramGain1, true); | |||
| else if (knob == fKnobQ1) | |||
| d_editParameter(ZamEQ2Plugin::paramQ1, true); | |||
| else if (knob == fKnobFreq1) | |||
| d_editParameter(ZamEQ2Plugin::paramFreq1, true); | |||
| else if (knob == fKnobGain2) | |||
| d_editParameter(ZamEQ2Plugin::paramGain2, true); | |||
| else if (knob == fKnobQ2) | |||
| d_editParameter(ZamEQ2Plugin::paramQ2, true); | |||
| else if (knob == fKnobFreq2) | |||
| d_editParameter(ZamEQ2Plugin::paramFreq2, true); | |||
| else if (knob == fKnobGainL) | |||
| d_editParameter(ZamEQ2Plugin::paramGainL, true); | |||
| else if (knob == fKnobFreqL) | |||
| d_editParameter(ZamEQ2Plugin::paramFreqL, true); | |||
| else if (knob == fKnobGainH) | |||
| d_editParameter(ZamEQ2Plugin::paramGainH, true); | |||
| else if (knob == fKnobFreqH) | |||
| d_editParameter(ZamEQ2Plugin::paramFreqH, true); | |||
| } | |||
| void ZamEQ2UI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobGain1) | |||
| d_editParameter(ZamEQ2Plugin::paramGain1, false); | |||
| else if (knob == fKnobQ1) | |||
| d_editParameter(ZamEQ2Plugin::paramQ1, false); | |||
| else if (knob == fKnobFreq1) | |||
| d_editParameter(ZamEQ2Plugin::paramFreq1, false); | |||
| else if (knob == fKnobGain2) | |||
| d_editParameter(ZamEQ2Plugin::paramGain2, false); | |||
| else if (knob == fKnobQ2) | |||
| d_editParameter(ZamEQ2Plugin::paramQ2, false); | |||
| else if (knob == fKnobFreq2) | |||
| d_editParameter(ZamEQ2Plugin::paramFreq2, false); | |||
| else if (knob == fKnobGainL) | |||
| d_editParameter(ZamEQ2Plugin::paramGainL, false); | |||
| else if (knob == fKnobFreqL) | |||
| d_editParameter(ZamEQ2Plugin::paramFreqL, false); | |||
| else if (knob == fKnobGainH) | |||
| d_editParameter(ZamEQ2Plugin::paramGainH, false); | |||
| else if (knob == fKnobFreqH) | |||
| d_editParameter(ZamEQ2Plugin::paramFreqH, false); | |||
| } | |||
| void ZamEQ2UI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| if (knob == fKnobGain1) | |||
| d_setParameterValue(ZamEQ2Plugin::paramGain1, value); | |||
| else if (knob == fKnobQ1) | |||
| d_setParameterValue(ZamEQ2Plugin::paramQ1, value); | |||
| else if (knob == fKnobFreq1) | |||
| d_setParameterValue(ZamEQ2Plugin::paramFreq1, value); | |||
| else if (knob == fKnobGain2) | |||
| d_setParameterValue(ZamEQ2Plugin::paramGain2, value); | |||
| else if (knob == fKnobQ2) | |||
| d_setParameterValue(ZamEQ2Plugin::paramQ2, value); | |||
| else if (knob == fKnobFreq2) | |||
| d_setParameterValue(ZamEQ2Plugin::paramFreq2, value); | |||
| else if (knob == fKnobGainL) | |||
| d_setParameterValue(ZamEQ2Plugin::paramGainL, value); | |||
| else if (knob == fKnobFreqL) | |||
| d_setParameterValue(ZamEQ2Plugin::paramFreqL, value); | |||
| else if (knob == fKnobGainH) | |||
| d_setParameterValue(ZamEQ2Plugin::paramGainH, value); | |||
| else if (knob == fKnobFreqH) | |||
| d_setParameterValue(ZamEQ2Plugin::paramFreqH, value); | |||
| } | |||
| void ZamEQ2UI::imageSliderDragStarted(ImageSlider* slider) | |||
| { | |||
| if (slider == fSliderMaster) | |||
| d_editParameter(ZamEQ2Plugin::paramMaster, true); | |||
| } | |||
| void ZamEQ2UI::imageSliderDragFinished(ImageSlider* slider) | |||
| { | |||
| if (slider == fSliderMaster) | |||
| d_editParameter(ZamEQ2Plugin::paramMaster, false); | |||
| } | |||
| void ZamEQ2UI::imageSliderValueChanged(ImageSlider* slider, float value) | |||
| { | |||
| if (slider == fSliderMaster) | |||
| d_setParameterValue(ZamEQ2Plugin::paramMaster, value); | |||
| } | |||
| void ZamEQ2UI::lowshelf(int i, int ch, float srate, float fc, float g) | |||
| { | |||
| float k, v0; | |||
| k = tanf(M_PI * fc / srate); | |||
| v0 = powf(10., g / 20.); | |||
| if (g < 0.f) { | |||
| // LF cut | |||
| float denom = v0 + sqrt(2. * v0)*k + k*k; | |||
| b0[ch][i] = v0 * (1. + sqrt(2.)*k + k*k) / denom; | |||
| b1[ch][i] = 2. * v0*(k*k - 1.) / denom; | |||
| b2[ch][i] = v0 * (1. - sqrt(2.)*k + k*k) / denom; | |||
| a1[ch][i] = 2. * (k*k - v0) / denom; | |||
| a2[ch][i] = (v0 - sqrt(2. * v0)*k + k*k) / denom; | |||
| } else { | |||
| // LF boost | |||
| float denom = 1. + sqrt(2.)*k + k*k; | |||
| b0[ch][i] = (1. + sqrt(2. * v0)*k + v0*k*k) / denom; | |||
| b1[ch][i] = 2. * (v0*k*k - 1.) / denom; | |||
| b2[ch][i] = (1. - sqrt(2. * v0)*k + v0*k*k) / denom; | |||
| a1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| a2[ch][i] = (1. - sqrt(2.)*k + k*k) / denom; | |||
| } | |||
| } | |||
| void ZamEQ2UI::highshelf(int i, int ch, float srate, float fc, float g) | |||
| { | |||
| float k, v0; | |||
| k = tanf(M_PI * fc / srate); | |||
| v0 = powf(10., g / 20.); | |||
| if (g < 0.f) { | |||
| // HF cut | |||
| float denom = 1. + sqrt(2. * v0)*k + v0*k*k; | |||
| b0[ch][i] = v0*(1. + sqrt(2.)*k + k*k) / denom; | |||
| b1[ch][i] = 2. * v0*(k*k - 1.) / denom; | |||
| b2[ch][i] = v0*(1. - sqrt(2.)*k + k*k) / denom; | |||
| a1[ch][i] = 2. * (v0*k*k - 1.) / denom; | |||
| a2[ch][i] = (1. - sqrt(2. * v0)*k + v0*k*k) / denom; | |||
| } else { | |||
| // HF boost | |||
| float denom = 1. + sqrt(2.)*k + k*k; | |||
| b0[ch][i] = (v0 + sqrt(2. * v0)*k + k*k) / denom; | |||
| b1[ch][i] = 2. * (k*k - v0) / denom; | |||
| b2[ch][i] = (v0 - sqrt(2. * v0)*k + k*k) / denom; | |||
| a1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| a2[ch][i] = (1. - sqrt(2.)*k + k*k) / denom; | |||
| } | |||
| } | |||
| void ZamEQ2UI::peq(int i, int ch, float srate, float fc, float g, float bw) | |||
| { | |||
| float k, v0, q; | |||
| k = tanf(M_PI * fc / srate); | |||
| v0 = powf(10., g / 20.); | |||
| q = powf(2., 1./bw)/(powf(2., bw) - 1.); //q from octave bw | |||
| if (g < 0.f) { | |||
| // cut | |||
| float denom = 1. + k/(v0*q) + k*k; | |||
| b0[ch][i] = (1. + k/q + k*k) / denom; | |||
| b1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| b2[ch][i] = (1. - k/q + k*k) / denom; | |||
| a1[ch][i] = b1[ch][i]; | |||
| a2[ch][i] = (1. - k/(v0*q) + k*k) / denom; | |||
| } else { | |||
| // boost | |||
| float denom = 1. + k/q + k*k; | |||
| b0[ch][i] = (1. + k*v0/q + k*k) / denom; | |||
| b1[ch][i] = 2. * (k*k - 1.) / denom; | |||
| b2[ch][i] = (1. - k*v0/q + k*k) / denom; | |||
| a1[ch][i] = b1[ch][i]; | |||
| a2[ch][i] = (1. - k/q + k*k) / denom; | |||
| } | |||
| } | |||
| void ZamEQ2UI::calceqcurve(float x[], float y[]) | |||
| { | |||
| float SR = d_getSampleRate(); | |||
| float p1 = 10000.; | |||
| float p2 = 5000.; | |||
| float c2 = log10(1.+SR); | |||
| float c1 = (1.+p1/SR)/(EQPOINTS*(p2/SR)*(p2/SR)); | |||
| double bw1 = fKnobQ1->getValue(); | |||
| double boost1 = fKnobGain1->getValue(); | |||
| double freq1 = fKnobFreq1->getValue(); | |||
| double bw2 = fKnobQ2->getValue(); | |||
| double boost2 = fKnobGain2->getValue(); | |||
| double freq2 = fKnobFreq2->getValue(); | |||
| double boostl = fKnobGainL->getValue(); | |||
| double freql = fKnobFreqL->getValue(); | |||
| double boosth = fKnobGainH->getValue(); | |||
| double freqh = fKnobFreqH->getValue(); | |||
| for (uint32_t i = 0; i < EQPOINTS; ++i) { | |||
| x[i] = 1.5*log10(1.+i+c1)/c2; | |||
| std::complex<double> H; | |||
| double theta = -(i+0.005)*M_PI/EQPOINTS*20./(SR/1000.); | |||
| std::complex<double> expiw = std::polar(1.0, theta); | |||
| std::complex<double> exp2iw = std::polar(1.0, 2.0*theta); | |||
| double freqH; //phaseH; | |||
| lowshelf(0, 0, SR, freql, boostl); | |||
| peq(1, 0, SR, freq1, boost1, bw1); | |||
| peq(2, 0, SR, freq2, boost2, bw2); | |||
| highshelf(3, 0, SR, freqh, boosth); | |||
| H = (1. + a1[0][0]*expiw + a2[0][0]*exp2iw)/(b0[0][0] + b1[0][0]*expiw + b2[0][0]*exp2iw); | |||
| H += (1. + a1[0][1]*expiw + a2[0][1]*exp2iw)/(b0[0][1] + b1[0][1]*expiw + b2[0][1]*exp2iw); | |||
| H += (1. + a1[0][2]*expiw + a2[0][2]*exp2iw)/(b0[0][2] + b1[0][2]*expiw + b2[0][2]*exp2iw); | |||
| H += (1. + a1[0][3]*expiw + a2[0][3]*exp2iw)/(b0[0][3] + b1[0][3]*expiw + b2[0][3]*exp2iw); | |||
| freqH = std::abs(H); | |||
| y[i] = (to_dB(freqH/4.)/5.)-(fSliderMaster->getValue())/24.f+0.5; | |||
| x[i] = fCanvasArea.getX() + x[i]*fCanvasArea.getWidth(); | |||
| y[i] = fCanvasArea.getY() + y[i]*fCanvasArea.getHeight(); | |||
| } | |||
| } | |||
| void ZamEQ2UI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| calceqcurve(eqx, eqy); | |||
| glEnable(GL_BLEND); | |||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
| glEnable(GL_LINE_SMOOTH); | |||
| glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); | |||
| glLineWidth(2); | |||
| int i; | |||
| glColor4f(1.f, 1.f, 0.235f, 1.0f); | |||
| for (i = 1; i < EQPOINTS; ++i) { | |||
| glBegin(GL_LINES); | |||
| if (eqy[i-1] < fCanvasArea.getY() + fCanvasArea.getHeight() | |||
| && eqy[i] < fCanvasArea.getY() + fCanvasArea.getHeight() | |||
| && eqy[i-1] > fCanvasArea.getY() | |||
| && eqy[i] > fCanvasArea.getY()) { | |||
| glVertex2i(eqx[i-1], eqy[i-1]); | |||
| glVertex2i(eqx[i], eqy[i]); | |||
| } | |||
| glEnd(); | |||
| } | |||
| // reset color | |||
| glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new ZamEQ2UI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,150 @@ | |||
| /* | |||
| * ZamEQ2 2 band parametric equaliser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMEQ2UI_HPP_INCLUDED | |||
| #define ZAMEQ2UI_HPP_INCLUDED | |||
| #define EQPOINTS 1000 | |||
| #include <complex> | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageKnob.hpp" | |||
| #include "ImageSlider.hpp" | |||
| #include "ZamEQ2Artwork.hpp" | |||
| #include "ZamEQ2Plugin.hpp" | |||
| using DGL::Image; | |||
| using DGL::ImageKnob; | |||
| using DGL::ImageSlider; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamEQ2UI : public UI, | |||
| public ImageKnob::Callback, | |||
| public ImageSlider::Callback | |||
| { | |||
| public: | |||
| ZamEQ2UI(); | |||
| ~ZamEQ2UI() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| unsigned int d_getWidth() const noexcept override | |||
| { | |||
| return ZamEQ2Artwork::zameq2Width; | |||
| } | |||
| unsigned int d_getHeight() const noexcept override | |||
| { | |||
| return ZamEQ2Artwork::zameq2Height; | |||
| } | |||
| inline double | |||
| to_dB(double g) { | |||
| return (20.*log10(g)); | |||
| } | |||
| inline double | |||
| from_dB(double gdb) { | |||
| return (exp(gdb/20.*log(10.))); | |||
| } | |||
| inline double | |||
| sanitize_denormal(double value) { | |||
| if (!std::isnormal(value)) { | |||
| return (0.); | |||
| } | |||
| return value; | |||
| } | |||
| float toIEC(float db) { | |||
| float def = 0.0f; /* Meter deflection %age */ | |||
| if (db < -70.0f) { | |||
| def = 0.0f; | |||
| } else if (db < -60.0f) { | |||
| def = (db + 70.0f) * 0.25f; | |||
| } else if (db < -50.0f) { | |||
| def = (db + 60.0f) * 0.5f + 5.0f; | |||
| } else if (db < -40.0f) { | |||
| def = (db + 50.0f) * 0.75f + 7.5; | |||
| } else if (db < -30.0f) { | |||
| def = (db + 40.0f) * 1.5f + 15.0f; | |||
| } else if (db < -20.0f) { | |||
| def = (db + 30.0f) * 2.0f + 30.0f; | |||
| } else if (db < 0.0f) { | |||
| def = (db + 20.0f) * 2.5f + 50.0f; | |||
| } else { | |||
| def = 100.0f; | |||
| } | |||
| return (def * 2.0f); | |||
| } | |||
| void calceqcurve(float x[], float y[]); | |||
| void peq(int i, int ch, float srate, float fc, float g, float bw); | |||
| void lowshelf(int i, int ch, float srate, float fc, float g); | |||
| void highshelf(int i, int ch, float srate, float fc, float g); | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void d_parameterChanged(uint32_t index, float value) override; | |||
| void d_programChanged(uint32_t index) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| 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; | |||
| ImageKnob* fKnobGain1; | |||
| ImageKnob* fKnobQ1; | |||
| ImageKnob* fKnobFreq1; | |||
| ImageKnob* fKnobGain2; | |||
| ImageKnob* fKnobQ2; | |||
| ImageKnob* fKnobFreq2; | |||
| ImageKnob* fKnobGainL; | |||
| ImageKnob* fKnobFreqL; | |||
| ImageKnob* fKnobGainH; | |||
| ImageKnob* fKnobFreqH; | |||
| ImageSlider* fSliderMaster; | |||
| float eqx[EQPOINTS]; | |||
| float eqy[EQPOINTS]; | |||
| DGL::Rectangle<int> fCanvasArea; | |||
| double a1[1][MAX_FILT], a2[1][MAX_FILT], b0[1][MAX_FILT], b1[1][MAX_FILT], b2[1][MAX_FILT]; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMEQ2UI_HPP_INCLUDED | |||
| @@ -0,0 +1,36 @@ | |||
| /* | |||
| * ZamSynth | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_NAME "ZamSynth" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 1 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 0 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 1 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "urn:zamaudio:ZamSynth" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -0,0 +1,67 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 DGL_IMAGE_TOGGLE_HPP_INCLUDED | |||
| #define DGL_IMAGE_TOGGLE_HPP_INCLUDED | |||
| #include "Image.hpp" | |||
| #include "Widget.hpp" | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| class ImageToggle : public Widget | |||
| { | |||
| public: | |||
| class Callback | |||
| { | |||
| public: | |||
| virtual ~Callback() {} | |||
| virtual void imageToggleClicked(ImageToggle* imageToggle, int button) = 0; | |||
| }; | |||
| ImageToggle(Window& parent, const Image& image); | |||
| ImageToggle(Widget* widget, const Image& image); | |||
| ImageToggle(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown); | |||
| ImageToggle(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown); | |||
| ImageToggle(const ImageToggle& imageToggle); | |||
| void setCallback(Callback* callback); | |||
| float getValue() override; | |||
| void setValue(float value) override; | |||
| protected: | |||
| void onDisplay() override; | |||
| bool onMouse(int button, bool press, int x, int y) override; | |||
| bool onMotion(int x, int y) override; | |||
| private: | |||
| Image fImageNormal; | |||
| Image fImageHover; | |||
| Image fImageDown; | |||
| Image* fCurImage; | |||
| int fCurButton; | |||
| Callback* fCallback; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| #endif // DGL_IMAGE_TOGGLE_HPP_INCLUDED | |||
| @@ -0,0 +1,40 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_ZAMSYNTHARTWORK_HPP | |||
| #define BINARY_ZAMSYNTHARTWORK_HPP | |||
| namespace ZamSynthArtwork | |||
| { | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 7056; | |||
| const unsigned int knobWidth = 42; | |||
| const unsigned int knobHeight = 42; | |||
| extern const char* smoothrData; | |||
| const unsigned int smoothrDataSize = 6864; | |||
| const unsigned int smoothrWidth = 78; | |||
| const unsigned int smoothrHeight = 22; | |||
| extern const char* smoothyData; | |||
| const unsigned int smoothyDataSize = 6864; | |||
| const unsigned int smoothyWidth = 78; | |||
| const unsigned int smoothyHeight = 22; | |||
| extern const char* toggleoffData; | |||
| const unsigned int toggleoffDataSize = 1056; | |||
| const unsigned int toggleoffWidth = 12; | |||
| const unsigned int toggleoffHeight = 22; | |||
| extern const char* toggleonData; | |||
| const unsigned int toggleonDataSize = 1056; | |||
| const unsigned int toggleonWidth = 12; | |||
| const unsigned int toggleonHeight = 22; | |||
| extern const char* zamsynthData; | |||
| const unsigned int zamsynthDataSize = 315000; | |||
| const unsigned int zamsynthWidth = 350; | |||
| const unsigned int zamsynthHeight = 300; | |||
| } | |||
| #endif // BINARY_ZAMSYNTHARTWORK_HPP | |||
| @@ -0,0 +1,343 @@ | |||
| /* | |||
| * ZamSynth polyphonic synthesiser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamSynthPlugin.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamSynthPlugin::ZamSynthPlugin() | |||
| : Plugin(paramCount, 1, 1) // 1 program, 1 state | |||
| { | |||
| // set default values | |||
| d_setProgram(0); | |||
| // reset | |||
| d_deactivate(); | |||
| } | |||
| ZamSynthPlugin::~ZamSynthPlugin() | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Init | |||
| void ZamSynthPlugin::d_initParameter(uint32_t index, Parameter& parameter) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramGain: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | |||
| parameter.name = "Gain"; | |||
| parameter.symbol = "gain"; | |||
| parameter.unit = "dB"; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -30.0f; | |||
| parameter.ranges.max = 30.0f; | |||
| break; | |||
| case paramSpeed: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; | |||
| parameter.name = "Speed"; | |||
| parameter.symbol = "speed"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 10.0f; | |||
| parameter.ranges.min = 1.0f; | |||
| parameter.ranges.max = 20.0f; | |||
| break; | |||
| case paramGraph: | |||
| parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; | |||
| parameter.name = "Graph toggle"; | |||
| parameter.symbol = "graph"; | |||
| parameter.unit = " "; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.max = 1.0f; | |||
| break; | |||
| } | |||
| } | |||
| void ZamSynthPlugin::d_initProgramName(uint32_t index, d_string& programName) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| programName = "Default"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Internal data | |||
| float ZamSynthPlugin::d_getParameterValue(uint32_t index) const | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramGain: | |||
| return gain; | |||
| break; | |||
| case paramSpeed: | |||
| return speed; | |||
| break; | |||
| case paramGraph: | |||
| return graph; | |||
| break; | |||
| default: | |||
| return 0.0f; | |||
| } | |||
| } | |||
| void ZamSynthPlugin::d_setParameterValue(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case paramGain: | |||
| gain = value; | |||
| break; | |||
| case paramSpeed: | |||
| speed = value; | |||
| break; | |||
| case paramGraph: | |||
| graph = value; | |||
| break; | |||
| } | |||
| } | |||
| void ZamSynthPlugin::d_setProgram(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| /* Default parameter values */ | |||
| gain = 0.0f; | |||
| graph = 0.0f; | |||
| speed = 10.0f; | |||
| /* Default variable values */ | |||
| for (int i = 0; i < MAX_VOICES; i++) { | |||
| voice[i].playing = false; | |||
| voice[i].notenum = -1; | |||
| voice[i].envpos = 0; | |||
| voice[i].slowcount = 0; | |||
| voice[i].curamp = 0.f; | |||
| voice[i].vi = 0.f; | |||
| voice[i].rampstate = 0.f; | |||
| } | |||
| curvoice = voice; //ptr to first voice | |||
| for (int i = 0; i < AREAHEIGHT; i++) { | |||
| wave_y[i] = sin(i*2.*M_PI/d_getSampleRate());//*1000 | |||
| } | |||
| for (int i = 0; i < MAX_ENV; i++) { | |||
| env_y[i] = (sin(i*2.*M_PI/d_getSampleRate()*1000./2.)) > 0.f ? sin(i*2.*M_PI/d_getSampleRate()*1000./2.) : 0.f; | |||
| } | |||
| /* reset filter values */ | |||
| d_activate(); | |||
| } | |||
| void ZamSynthPlugin::d_setState(const char* key, const char* value) | |||
| { | |||
| if (strcmp(key, "waveform") == 0) { | |||
| char* tmp; | |||
| int i = 0; | |||
| char tmpbuf[4*AREAHEIGHT+1] = {0}; | |||
| snprintf(tmpbuf, 4*AREAHEIGHT, "%s", value); | |||
| tmp = strtok(tmpbuf, " "); | |||
| while ((tmp != NULL) && (i < AREAHEIGHT)) { | |||
| wave_y[i] = ((float) atoi(tmp))/AREAHEIGHT - 0.5; | |||
| i++; | |||
| //printf("dsp wave_y[%d]=%.2f ", i, wave_y[i]); | |||
| tmp = strtok(NULL, " "); | |||
| } | |||
| } else if (strcmp(key, "envelope") == 0) { | |||
| char* tmp; | |||
| int i = 0; | |||
| char tmpbuf[4*MAX_ENV+1] = {0}; | |||
| snprintf(tmpbuf, 4*MAX_ENV, "%s", value); | |||
| tmp = strtok(tmpbuf, " "); | |||
| while ((tmp != NULL) && (i < MAX_ENV)) { | |||
| env_y[i] = ((float) atoi(tmp))/MAX_ENV - 0.5; | |||
| i++; | |||
| //printf("dsp env_y[%d]=%.2f ", i, env_y[i]); | |||
| tmp = strtok(NULL, " "); | |||
| } | |||
| } | |||
| } | |||
| void ZamSynthPlugin::d_initStateKey(unsigned int index, d_string& key) | |||
| { | |||
| if (index == 0) key = "waveform"; | |||
| if (index == 1) key = "envelope"; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Process | |||
| void ZamSynthPlugin::d_activate() | |||
| { | |||
| } | |||
| void ZamSynthPlugin::d_deactivate() | |||
| { | |||
| // all values to zero | |||
| } | |||
| float ZamSynthPlugin::wavetable(float in) | |||
| { | |||
| int index = (int) ((in / (2.0 * M_PI)) * (AREAHEIGHT-1.0)); | |||
| return (wave_y[index]); | |||
| //return (sin(in)); | |||
| } | |||
| void ZamSynthPlugin::d_run(float**, float** outputs, uint32_t frames, | |||
| const MidiEvent* midievent, uint32_t midicount) | |||
| { | |||
| float srate = d_getSampleRate(); | |||
| int slowfactor = (int) srate / (speed * 2400); // 1-20 ~ 20-1 | |||
| uint32_t i; | |||
| float RD_0; | |||
| for (i = 0; i < midicount; i++) { | |||
| int type = midievent[i].buf[0] & 0xF0; | |||
| int chan = midievent[i].buf[0] & 0x0F; | |||
| int num = midievent[i].buf[1]; | |||
| int vel = midievent[i].buf[2]; | |||
| if (type == 0x90 && chan == 0x0) { | |||
| // NOTE ON | |||
| nvoices = 0; | |||
| //printf("ON: Note\n"); | |||
| //printf("ON: begin attack\n"); | |||
| for (int k = 0; k < 128; k++) | |||
| if (voice[k].playing) | |||
| nvoices++; | |||
| curvoice = &voice[nvoices]; | |||
| curvoice->envpos = 1; // begin attack | |||
| curvoice->playing = true; | |||
| curvoice->notenum = num; | |||
| curvoice->vi = vel / 127.f; | |||
| curvoice->curamp = curvoice->vi; | |||
| curvoice->rampstate = 0; | |||
| } | |||
| else if (type == 0x80 && chan == 0x0) { | |||
| // NOTE OFF | |||
| //printf("OFF: Note\n"); | |||
| //find voice with current notenum | |||
| nvoices = 0; | |||
| for (int k = 0; k < 128; k++) { | |||
| if (voice[k].playing && voice[k].notenum == num) { | |||
| voice[k].envpos = MAX_ENV / 2 + 1; // begin release; | |||
| } | |||
| if (!voice[k].playing && voice[k].notenum == num) { | |||
| voice[k].notenum = -1; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| float power; | |||
| bool signal; | |||
| float wave; | |||
| float outl; | |||
| float outr; | |||
| for (i = 0; i < frames; i++) { | |||
| signal = false; | |||
| outl = outr = 0.f; | |||
| power = 0.f; | |||
| int k; | |||
| Voice* j; | |||
| // process envelope positions per sample | |||
| for (k = 0; k < 128; k++) { | |||
| j = &voice[k]; | |||
| if (j->playing) { | |||
| if (j->envpos <= 0) { | |||
| //silence | |||
| j->curamp = 0.f; | |||
| j->playing = false; | |||
| j->slowcount = 0; | |||
| j->envpos = 0; | |||
| } else if (j->envpos > 0 && (int) j->envpos < MAX_ENV / 2) { | |||
| //attack | |||
| j->curamp = j->vi * env_y[j->envpos]; | |||
| //printf("att: %d %d curamp=%.2f\n",k,j->envpos, j->curamp); | |||
| j->slowcount++; | |||
| j->envpos += ((j->slowcount % slowfactor) == 0) ? 1 : 0; | |||
| } else if (j->envpos > MAX_ENV / 2) { | |||
| //release | |||
| j->curamp = j->vi * env_y[j->envpos]; | |||
| //printf("rel: %d %d curamp=%.2f\n",k,j->envpos, j->curamp); | |||
| j->slowcount++; | |||
| j->envpos += ((j->slowcount % slowfactor) == 0) ? 1 : 0; | |||
| if (j->envpos == MAX_ENV) { | |||
| //end of release | |||
| j->envpos = 0; | |||
| j->slowcount = 0; | |||
| j->curamp = 0.f; | |||
| j->vi = 0.f; | |||
| j->playing = false; | |||
| //printf("killed, n=%d\n",k); | |||
| } | |||
| } else { | |||
| //sustain | |||
| j->curamp = j->vi * env_y[MAX_ENV/2]; | |||
| //printf("sustain...\n"); | |||
| } | |||
| } | |||
| } | |||
| for (k = 0; k < 128; k++) { | |||
| float rampfreq; | |||
| if (voice[k].curamp < 0.f && voice[k].playing) printf("WTF NEG\n"); | |||
| if (!voice[k].playing) continue; | |||
| signal = true; | |||
| rampfreq = 440.0*powf(2.0, (voice[k].notenum-48.0-36)/12.); | |||
| // ramp sawtooth | |||
| RD_0 = 1.4247585730565955E-4*srate/44100.*rampfreq + voice[k].rampstate; | |||
| if (RD_0>6.283185307179586) {RD_0 -= 6.283185307179586;} | |||
| if (RD_0<-6.283185307179586) {RD_0 += 6.283185307179586;} | |||
| voice[k].rampstate = RD_0; | |||
| // wavetable | |||
| wave = wavetable(voice[k].rampstate); | |||
| power += sqrt(voice[k].curamp); | |||
| outl += wave*voice[k].curamp/5.; | |||
| outr += wave*voice[k].curamp/5.; | |||
| } | |||
| if (signal) { | |||
| //outl; | |||
| //outr; | |||
| outputs[0][i] = outl*from_dB(gain); | |||
| outputs[1][i] = outr*from_dB(gain); | |||
| } else { | |||
| outputs[0][i] = 0.f; | |||
| outputs[1][i] = 0.f; | |||
| } | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Plugin* createPlugin() | |||
| { | |||
| return new ZamSynthPlugin(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,138 @@ | |||
| /* | |||
| * ZamSynth polyphonic synthesiser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMSYNTHPLUGIN_HPP_INCLUDED | |||
| #define ZAMSYNTHPLUGIN_HPP_INCLUDED | |||
| #include <string.h> | |||
| #include "DistrhoPlugin.hpp" | |||
| #define MAX_VOICES 128 | |||
| #define AREAHEIGHT 250 | |||
| #define MAX_ENV AREAHEIGHT | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamSynthPlugin : public Plugin | |||
| { | |||
| public: | |||
| enum Parameters | |||
| { | |||
| paramGain, | |||
| paramSpeed, | |||
| paramGraph, | |||
| paramCount | |||
| }; | |||
| ZamSynthPlugin(); | |||
| ~ZamSynthPlugin() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* d_getLabel() const noexcept override | |||
| { | |||
| return "ZamSynth"; | |||
| } | |||
| const char* d_getMaker() const noexcept override | |||
| { | |||
| return "Damien Zammit"; | |||
| } | |||
| const char* d_getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t d_getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| long d_getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('Z', 'S', 'T', 'H'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void d_initParameter(uint32_t index, Parameter& parameter) ; | |||
| void d_initProgramName(uint32_t index, d_string& programName) ; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float d_getParameterValue(uint32_t index) const override; | |||
| void d_setParameterValue(uint32_t index, float value) override; | |||
| void d_setProgram(uint32_t index) ; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| static inline float | |||
| sanitize_denormal(float v) { | |||
| if(!std::isnormal(v)) | |||
| return 0.f; | |||
| return v; | |||
| } | |||
| static inline float | |||
| from_dB(float gdb) { | |||
| return (exp(gdb/20.f*log(10.f))); | |||
| } | |||
| static inline float | |||
| to_dB(float g) { | |||
| return (20.f*log10(g)); | |||
| } | |||
| float wavetable(float in); | |||
| void d_activate() override; | |||
| void d_deactivate() override; | |||
| void d_run(float** inputs, float** outputs, uint32_t frames, | |||
| const MidiEvent* midievent, uint32_t midicount) override; | |||
| void d_setState(const char* key, const char* value) override; | |||
| void d_initStateKey(unsigned int key, d_string& val) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float gain, graph, speed; | |||
| int nvoices; | |||
| float wave_y[AREAHEIGHT]; | |||
| float env_y[MAX_ENV]; | |||
| typedef struct v { | |||
| bool playing; | |||
| int notenum; | |||
| int envpos; | |||
| int slowcount; | |||
| float curamp; | |||
| float vi; | |||
| float rampstate; | |||
| } Voice; | |||
| Voice voice[128]; | |||
| Voice* curvoice; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMSYNTH_HPP_INCLUDED | |||
| @@ -0,0 +1,331 @@ | |||
| /* | |||
| * ZamSynth polyphonic synthesiser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamSynthUI.hpp" | |||
| using DGL::Point; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamSynthUI::ZamSynthUI() | |||
| : UI() | |||
| { | |||
| // background | |||
| fImgBackground = Image(ZamSynthArtwork::zamsynthData, ZamSynthArtwork::zamsynthWidth, ZamSynthArtwork::zamsynthHeight, GL_BGR); | |||
| // knob | |||
| Image knobImage(ZamSynthArtwork::knobData, ZamSynthArtwork::knobWidth, ZamSynthArtwork::knobHeight); | |||
| // button | |||
| Image smoothrImage(ZamSynthArtwork::smoothrData, ZamSynthArtwork::smoothrWidth, ZamSynthArtwork::smoothrHeight); | |||
| Image smoothyImage(ZamSynthArtwork::smoothyData, ZamSynthArtwork::smoothyWidth, ZamSynthArtwork::smoothyHeight); | |||
| // toggle | |||
| Image toggleonImage(ZamSynthArtwork::toggleonData, ZamSynthArtwork::toggleonWidth, ZamSynthArtwork::toggleonHeight); | |||
| Image toggleoffImage(ZamSynthArtwork::toggleoffData, ZamSynthArtwork::toggleoffWidth, ZamSynthArtwork::toggleoffHeight); | |||
| // knob | |||
| fKnobGain = new ImageKnob(this, knobImage); | |||
| fKnobGain->setPos(284.75, 240); | |||
| fKnobGain->setRange(-30.f, 30.0f); | |||
| //fKnobGain->setDefault(0.0f); | |||
| fKnobGain->setRotationAngle(240); | |||
| fKnobGain->setCallback(this); | |||
| fKnobSpeed = new ImageKnob(this, knobImage); | |||
| fKnobSpeed->setPos(284.75, 92.5); | |||
| fKnobSpeed->setRange(1.f, 20.0f); | |||
| //fKnobSpeed->setDefault(10.0f); | |||
| fKnobSpeed->setStep(1.0f); | |||
| fKnobSpeed->setRotationAngle(240); | |||
| fKnobSpeed->setCallback(this); | |||
| // button | |||
| fButtonSmooth = new ImageButton(this, smoothrImage, smoothrImage, smoothyImage); | |||
| fButtonSmooth->setPos(265, 165); | |||
| fButtonSmooth->setCallback(this); | |||
| // drawing area | |||
| fCanvasArea.setPos(10,10); | |||
| fCanvasArea.setSize(AREAHEIGHT,AREAHEIGHT); | |||
| for (int i = 0; i < AREAHEIGHT; i++) { | |||
| wave_y[i] = -(AREAHEIGHT*(sin(2.*i*M_PI/AREAHEIGHT)-1.0))/2.; | |||
| env_y[i] = -(2*AREAHEIGHT*(sin(2.*i*M_PI/AREAHEIGHT/2.)-1.0))/2. < AREAHEIGHT / 2. ? -(2*AREAHEIGHT*(sin(2.*i*M_PI/AREAHEIGHT/2.)-1.0))/2. : AREAHEIGHT / 2.; | |||
| } | |||
| // toggle | |||
| fToggleGraph = new ImageToggle(this, toggleonImage, toggleoffImage, toggleoffImage); | |||
| fToggleGraph->setPos(300, 33); | |||
| fToggleGraph->setCallback(this); | |||
| fToggleGraph->setValue(0.f); | |||
| } | |||
| ZamSynthUI::~ZamSynthUI() | |||
| { | |||
| delete fKnobGain; | |||
| delete fKnobSpeed; | |||
| delete fButtonSmooth; | |||
| delete fToggleGraph; | |||
| } | |||
| void ZamSynthUI::d_stateChanged(const char* key, const char* value) | |||
| { | |||
| if (strcmp(key, "waveform") == 0) { | |||
| char* tmp; | |||
| int i = 0; | |||
| char tmpbuf[4*AREAHEIGHT+1] = {0}; | |||
| snprintf(tmpbuf, 4*AREAHEIGHT, "%s", value); | |||
| tmp = strtok(tmpbuf, " "); | |||
| while ((tmp != NULL) && (i < AREAHEIGHT)) { | |||
| wave_y[i] = AREAHEIGHT-((float)atoi(tmp)); | |||
| i++; | |||
| //printf("reload dsp wave_y[%d]=%.2f ", i, wave_y[i]); | |||
| tmp = strtok(NULL, " "); | |||
| } | |||
| } else if (strcmp(key, "envelope") == 0) { | |||
| char* tmp; | |||
| int i = 0; | |||
| char tmpbuf[4*AREAHEIGHT+1] = {0}; | |||
| snprintf(tmpbuf, 4*AREAHEIGHT, "%s", value); | |||
| tmp = strtok(tmpbuf, " "); | |||
| while ((tmp != NULL) && (i < AREAHEIGHT)) { | |||
| env_y[i] = AREAHEIGHT-((float)atoi(tmp)); | |||
| i++; | |||
| //printf("reload dsp env_y[%d]=%.2f ", i, env_y[i]); | |||
| tmp = strtok(NULL, " "); | |||
| } | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void ZamSynthUI::d_parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case ZamSynthPlugin::paramGain: | |||
| fKnobGain->setValue(value); | |||
| break; | |||
| case ZamSynthPlugin::paramSpeed: | |||
| fKnobSpeed->setValue(value); | |||
| break; | |||
| case ZamSynthPlugin::paramGraph: | |||
| fToggleGraph->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| void ZamSynthUI::d_programChanged(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| fKnobGain->setValue(0.0f); | |||
| fKnobSpeed->setValue(10.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void ZamSynthUI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobGain) | |||
| d_editParameter(ZamSynthPlugin::paramGain, true); | |||
| else if (knob == fKnobSpeed) | |||
| d_editParameter(ZamSynthPlugin::paramSpeed, true); | |||
| } | |||
| void ZamSynthUI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobGain) | |||
| d_editParameter(ZamSynthPlugin::paramGain, false); | |||
| else if (knob == fKnobSpeed) | |||
| d_editParameter(ZamSynthPlugin::paramSpeed, false); | |||
| } | |||
| void ZamSynthUI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| if (knob == fKnobGain) | |||
| d_setParameterValue(ZamSynthPlugin::paramGain, value); | |||
| else if (knob == fKnobSpeed) | |||
| d_setParameterValue(ZamSynthPlugin::paramSpeed, value); | |||
| } | |||
| void ZamSynthUI::imageButtonClicked(ImageButton*, int) | |||
| { | |||
| float wavesmooth[AREAHEIGHT]; | |||
| float xs[AREAHEIGHT]; | |||
| int i; | |||
| for (i = 0; i < AREAHEIGHT; i++) { | |||
| xs[i] = i; | |||
| } | |||
| float *gr; | |||
| gr = (fToggleGraph->getValue() == 1.f) ? env_y : wave_y; | |||
| gaussiansmooth(wavesmooth, xs, gr, AREAHEIGHT, 4); | |||
| memcpy(gr, wavesmooth, AREAHEIGHT*sizeof(float)); | |||
| char tmp[4*AREAHEIGHT+1] = {0}; | |||
| for(i = 0; i < AREAHEIGHT; i++) { | |||
| char wavestr[5] = {0}; | |||
| snprintf(wavestr, sizeof(wavestr), "%03d ", (int) (fCanvasArea.getHeight()-gr[i])); | |||
| strcat(tmp, wavestr); | |||
| } | |||
| if (fToggleGraph->getValue() == 1.f) | |||
| d_setState("envelope", tmp); | |||
| else | |||
| d_setState("waveform", tmp); | |||
| } | |||
| void ZamSynthUI::imageToggleClicked(ImageToggle*, int) | |||
| { | |||
| float toggle = fToggleGraph->getValue(); | |||
| fToggleGraph->setValue(toggle); | |||
| d_setParameterValue(ZamSynthPlugin::paramGraph, toggle); | |||
| } | |||
| void ZamSynthUI::gaussiansmooth(float* smoothed, float* xs, float* ys, int n, int radius) | |||
| { | |||
| int i,j; | |||
| float numer; | |||
| float denom; | |||
| float kernel; | |||
| for (i = 0; i < n; i++) { | |||
| numer = 0.f; | |||
| denom = 0.f; | |||
| for (j = 0; j < n; j++) { | |||
| kernel = expf(-(i - xs[j])*(i - xs[j]) / (2. * radius)); | |||
| numer += kernel * ys[j]; | |||
| denom += kernel; | |||
| } | |||
| smoothed[i] = numer / denom; | |||
| } | |||
| } | |||
| bool ZamSynthUI::onMouse(int button, bool press, int x, int y) | |||
| { | |||
| if (button != 1) | |||
| return false; | |||
| if (press) | |||
| { | |||
| if (! fCanvasArea.contains(x, y)) { | |||
| //fDragValid = false; | |||
| return false; | |||
| } | |||
| fDragging = true; | |||
| fDragValid = true; | |||
| return true; | |||
| } | |||
| else if (fDragging) | |||
| { | |||
| fDragging = false; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| bool ZamSynthUI::onMotion(int x, int y) | |||
| { | |||
| if (! fDragging) | |||
| return false; | |||
| if (! fDragValid) | |||
| { | |||
| fDragValid = true; | |||
| } | |||
| if (x > fCanvasArea.getWidth()+10) | |||
| x = fCanvasArea.getWidth()+10; | |||
| if (x < 10) x = 10; | |||
| if (y < 10) y = 10; | |||
| float *gr; | |||
| if (fToggleGraph->getValue() == 0.f) { | |||
| gr = wave_y; | |||
| if (y > fCanvasArea.getHeight()+10) | |||
| y = fCanvasArea.getHeight()+10; | |||
| } else { | |||
| gr = env_y; | |||
| if (y > fCanvasArea.getHeight() / 2. + 10) | |||
| y = fCanvasArea.getHeight() / 2. + 10; | |||
| } | |||
| if (gr[x-10] != (y-10)) { | |||
| char tmp[4*AREAHEIGHT+1] = {0}; | |||
| int i; | |||
| for(i = 0; i < AREAHEIGHT; i++) { | |||
| char wavestr[5] = {0}; | |||
| snprintf(wavestr, sizeof(wavestr), "%03d ", (int) (fCanvasArea.getHeight()-gr[i])); | |||
| strcat(tmp, wavestr); | |||
| } | |||
| gr[x-10] = y-10; | |||
| if (gr == env_y) | |||
| d_setState("envelope",tmp); | |||
| else | |||
| d_setState("waveform",tmp); | |||
| repaint(); | |||
| } | |||
| return true; | |||
| } | |||
| void ZamSynthUI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| glEnable(GL_BLEND); | |||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
| glEnable(GL_LINE_SMOOTH); | |||
| glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); | |||
| glLineWidth(2); | |||
| float *gr; | |||
| gr = (fToggleGraph->getValue() == 1.f) ? env_y : wave_y; | |||
| int i; | |||
| glColor4f(0.235f, 1.f, 0.235f, 1.0f); | |||
| for (i = 2; i < AREAHEIGHT; ++i) { | |||
| glBegin(GL_LINES); | |||
| glVertex2i(i-1+fCanvasArea.getX(), gr[i-1]+fCanvasArea.getY()); | |||
| glVertex2i(i+fCanvasArea.getX(), gr[i]+fCanvasArea.getY()); | |||
| glEnd(); | |||
| } | |||
| // reset color | |||
| glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new ZamSynthUI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,107 @@ | |||
| /* | |||
| * ZamSynth polyphonic synthesiser | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMSYNTHUI_HPP_INCLUDED | |||
| #define ZAMSYNTHUI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "Geometry.hpp" | |||
| #include "ImageKnob.hpp" | |||
| #include "ImageButton.hpp" | |||
| #include "ImageToggle.hpp" | |||
| #include "ZamSynthArtwork.hpp" | |||
| #include "ZamSynthPlugin.hpp" | |||
| using DGL::Image; | |||
| using DGL::ImageKnob; | |||
| using DGL::ImageButton; | |||
| using DGL::ImageToggle; | |||
| #define AREAHEIGHT 250 | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamSynthUI : public UI, | |||
| public ImageKnob::Callback, | |||
| public ImageButton::Callback, | |||
| public ImageToggle::Callback | |||
| { | |||
| public: | |||
| ZamSynthUI(); | |||
| ~ZamSynthUI() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| unsigned int d_getWidth() const noexcept override | |||
| { | |||
| return ZamSynthArtwork::zamsynthWidth; | |||
| } | |||
| unsigned int d_getHeight() const noexcept override | |||
| { | |||
| return ZamSynthArtwork::zamsynthHeight; | |||
| } | |||
| void gaussiansmooth(float* smoothed, float* xs, float* ys, int n, int radius); | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void d_parameterChanged(uint32_t index, float value) override; | |||
| void d_programChanged(uint32_t index) override; | |||
| void d_stateChanged(const char*, const char*) override; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void imageKnobDragStarted(ImageKnob* knob) override; | |||
| void imageKnobDragFinished(ImageKnob* knob) override; | |||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | |||
| void imageButtonClicked(ImageButton* button, int) override; | |||
| void imageToggleClicked(ImageToggle* toggle, int) override; | |||
| void onDisplay() override; | |||
| bool onMouse(int, bool, int, int) override; | |||
| bool onMotion(int, int) override; | |||
| private: | |||
| Image fImgBackground; | |||
| ImageKnob* fKnobGain; | |||
| ImageKnob* fKnobSpeed; | |||
| ImageButton* fButtonSmooth; | |||
| ImageToggle* fToggleGraph; | |||
| float wave_y[AREAHEIGHT]; | |||
| float env_y[AREAHEIGHT]; | |||
| bool fGraph; | |||
| bool fDragging; | |||
| bool fDragValid; | |||
| DGL::Rectangle<int> fCanvasArea; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMSYNTHUI_HPP_INCLUDED | |||
| @@ -0,0 +1,36 @@ | |||
| /* | |||
| * ZamTube | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| #define DISTRHO_PLUGIN_NAME "ZamTube" | |||
| #define DISTRHO_PLUGIN_HAS_UI 1 | |||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | |||
| #define DISTRHO_PLUGIN_NUM_INPUTS 1 | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | |||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||
| #define DISTRHO_PLUGIN_URI "urn:zamaudio:ZamTube" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -0,0 +1,25 @@ | |||
| /* (Auto-generated binary data file). */ | |||
| #ifndef BINARY_ZAMTUBEARTWORK_HPP | |||
| #define BINARY_ZAMTUBEARTWORK_HPP | |||
| namespace ZamTubeArtwork | |||
| { | |||
| extern const char* knobData; | |||
| const unsigned int knobDataSize = 7056; | |||
| const unsigned int knobWidth = 42; | |||
| const unsigned int knobHeight = 42; | |||
| extern const char* notchData; | |||
| const unsigned int notchDataSize = 2016; | |||
| const unsigned int notchWidth = 21; | |||
| const unsigned int notchHeight = 24; | |||
| extern const char* zamtubeData; | |||
| const unsigned int zamtubeDataSize = 423360; | |||
| const unsigned int zamtubeWidth = 448; | |||
| const unsigned int zamtubeHeight = 315; | |||
| } | |||
| #endif // BINARY_ZAMTUBEARTWORK_HPP | |||
| @@ -0,0 +1,200 @@ | |||
| /* | |||
| * ZamTube triode WDF distortion model | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMTUBEPLUGIN_HPP_INCLUDED | |||
| #define ZAMTUBEPLUGIN_HPP_INCLUDED | |||
| #include "DistrhoPlugin.hpp" | |||
| #include "wdf.h" | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| #include <stdint.h> | |||
| #include <math.h> | |||
| template <int N> inline float faustpower(float x) { return powf(x,N); } | |||
| template <int N> inline double faustpower(double x) { return pow(x,N); } | |||
| template <int N> inline int faustpower(int x) { return faustpower<N/2>(x) * faustpower<N-N/2>(x); } | |||
| template <> inline int faustpower<0>(int) { return 1; } | |||
| template <> inline int faustpower<1>(int x) { return x; } | |||
| #define FAUSTFLOAT float | |||
| typedef long double quad; | |||
| #define TOLERANCE 1e-6 | |||
| #define DANGER 1000.f | |||
| class ZamTubePlugin : public Plugin | |||
| { | |||
| public: | |||
| Triode v; | |||
| V Vi; | |||
| C Ci; | |||
| C Ck; | |||
| C Co; | |||
| R Ro; | |||
| R Rg; | |||
| R Ri; | |||
| R Rk; | |||
| V E; | |||
| T e; | |||
| //Official | |||
| //->Gate | |||
| ser S0; | |||
| inv I0; | |||
| par P0; | |||
| ser S1; | |||
| inv I1; | |||
| //->Cathode | |||
| par I3; | |||
| //->Plate | |||
| ser S2; | |||
| inv I4; | |||
| par P2; | |||
| float fConst0; | |||
| float fConst1; | |||
| float fConst2; | |||
| float fConst3; | |||
| float fRec0[4]; | |||
| float fRec1[4]; | |||
| float fRec2[4]; | |||
| float fRec3[4]; | |||
| float fRec4[4]; | |||
| float fRec5[4]; | |||
| float fRec6[4]; | |||
| float fRec7[4]; | |||
| float fRec8[4]; | |||
| float fRec9[4]; | |||
| float fRec10[4]; | |||
| float fRec11[4]; | |||
| float fRec12[4]; | |||
| float fRec13[4]; | |||
| float fConst4; | |||
| float fConst5; | |||
| float fRec14[4]; | |||
| float fConst6; | |||
| float fRec15[4]; | |||
| float fRec16[4]; | |||
| float fRec17[4]; | |||
| float fRec18[4]; | |||
| float fRec19[4]; | |||
| float fRec20[4]; | |||
| float fRec21[4]; | |||
| float fRec22[4]; | |||
| float fRec23[4]; | |||
| float fRec24[4]; | |||
| float fSamplingFreq; | |||
| enum Parameters | |||
| { | |||
| paramTubedrive = 0, | |||
| paramBass, | |||
| paramMiddle, | |||
| paramTreble, | |||
| paramToneStack, | |||
| paramGain, | |||
| paramCount | |||
| }; | |||
| ZamTubePlugin(); | |||
| ~ZamTubePlugin() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| const char* d_getLabel() const noexcept override | |||
| { | |||
| return "ZamTube"; | |||
| } | |||
| const char* d_getMaker() const noexcept override | |||
| { | |||
| return "Damien Zammit"; | |||
| } | |||
| const char* d_getLicense() const noexcept override | |||
| { | |||
| return "GPL v2+"; | |||
| } | |||
| uint32_t d_getVersion() const noexcept override | |||
| { | |||
| return 0x1000; | |||
| } | |||
| long d_getUniqueId() const noexcept override | |||
| { | |||
| return d_cconst('Z', 'T', 'U', 'B'); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Init | |||
| void d_initParameter(uint32_t index, Parameter& parameter) ; | |||
| void d_initProgramName(uint32_t index, d_string& programName) ; | |||
| // ------------------------------------------------------------------- | |||
| // Internal data | |||
| float d_getParameterValue(uint32_t index) const override; | |||
| void d_setParameterValue(uint32_t index, float value) override; | |||
| void d_setProgram(uint32_t index) ; | |||
| // ------------------------------------------------------------------- | |||
| // Process | |||
| static inline float | |||
| sanitize_denormal(float v) { | |||
| if(!std::isnormal(v) || !std::isfinite(v)) | |||
| return 0.f; | |||
| return v; | |||
| } | |||
| static inline float | |||
| from_dB(float gdb) { | |||
| return (exp(gdb/20.f*log(10.f))); | |||
| } | |||
| static inline float | |||
| to_dB(float g) { | |||
| return (20.f*log10(g)); | |||
| } | |||
| void d_activate() override; | |||
| void d_deactivate() override; | |||
| void d_run(float** inputs, float** outputs, uint32_t frames) override; | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| float tubedrive,bass,middle,treble,tonestack,mastergain; //parameters | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMTUBE_HPP_INCLUDED | |||
| @@ -0,0 +1,214 @@ | |||
| /* | |||
| * ZamTube triode WDF distortion model | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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 "ZamTubeUI.hpp" | |||
| using DGL::Point; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| ZamTubeUI::ZamTubeUI() | |||
| : UI() | |||
| { | |||
| // background | |||
| fImgBackground = Image(ZamTubeArtwork::zamtubeData, ZamTubeArtwork::zamtubeWidth, ZamTubeArtwork::zamtubeHeight, GL_BGR); | |||
| // knob | |||
| Image knobImage(ZamTubeArtwork::knobData, ZamTubeArtwork::knobWidth, ZamTubeArtwork::knobHeight); | |||
| // notch slider | |||
| Image notchImage(ZamTubeArtwork::notchData, ZamTubeArtwork::notchWidth, ZamTubeArtwork::notchHeight); | |||
| // knobs | |||
| fKnobTube = new ImageKnob(this, knobImage); | |||
| fKnobTube->setPos(177, 76); | |||
| fKnobTube->setRange(0.f, 30.0f); | |||
| fKnobTube->setStep(0.1f); | |||
| //fKnobTube->setDefault(0.0f); | |||
| fKnobTube->setRotationAngle(240); | |||
| fKnobTube->setCallback(this); | |||
| fKnobBass = new ImageKnob(this, knobImage); | |||
| fKnobBass->setPos(63, 140.5); | |||
| fKnobBass->setRange(0.f, 1.0f); | |||
| fKnobBass->setStep(0.01f); | |||
| //fKnobBass->setDefault(0.5f); | |||
| fKnobBass->setRotationAngle(240); | |||
| fKnobBass->setCallback(this); | |||
| fKnobMids = new ImageKnob(this, knobImage); | |||
| fKnobMids->setPos(63, 87); | |||
| fKnobMids->setRange(0.f, 1.0f); | |||
| fKnobMids->setStep(0.01f); | |||
| //fKnobMids->setDefault(0.5f); | |||
| fKnobMids->setRotationAngle(240); | |||
| fKnobMids->setCallback(this); | |||
| fKnobTreb = new ImageKnob(this, knobImage); | |||
| fKnobTreb->setPos(63, 33); | |||
| fKnobTreb->setRange(0.f, 1.0f); | |||
| fKnobTreb->setStep(0.01f); | |||
| //fKnobTreb->setDefault(0.0f); | |||
| fKnobTreb->setRotationAngle(240); | |||
| fKnobTreb->setCallback(this); | |||
| fKnobGain = new ImageKnob(this, knobImage); | |||
| fKnobGain->setPos(63, 231); | |||
| fKnobGain->setRange(-30.f, 30.0f); | |||
| fKnobGain->setStep(1.f); | |||
| //fKnobGain->setDefault(0.0f); | |||
| fKnobGain->setRotationAngle(240); | |||
| fKnobGain->setCallback(this); | |||
| Point<int> notchPosStart(289,5); | |||
| Point<int> notchPosEnd(289,5+280); | |||
| fSliderNotch = new ImageSlider(this, notchImage); | |||
| fSliderNotch->setStartPos(notchPosStart); | |||
| fSliderNotch->setEndPos(notchPosEnd); | |||
| fSliderNotch->setRange(0.f, 24.f); | |||
| fSliderNotch->setStep(1.f); | |||
| fSliderNotch->setValue(0.f); | |||
| fSliderNotch->setCallback(this); | |||
| } | |||
| ZamTubeUI::~ZamTubeUI() | |||
| { | |||
| delete fKnobTube; | |||
| delete fKnobBass; | |||
| delete fKnobMids; | |||
| delete fKnobTreb; | |||
| delete fKnobGain; | |||
| delete fSliderNotch; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void ZamTubeUI::d_parameterChanged(uint32_t index, float value) | |||
| { | |||
| switch (index) | |||
| { | |||
| case ZamTubePlugin::paramTubedrive: | |||
| fKnobTube->setValue(value); | |||
| break; | |||
| case ZamTubePlugin::paramBass: | |||
| fKnobBass->setValue(value); | |||
| break; | |||
| case ZamTubePlugin::paramMiddle: | |||
| fKnobMids->setValue(value); | |||
| break; | |||
| case ZamTubePlugin::paramTreble: | |||
| fKnobTreb->setValue(value); | |||
| break; | |||
| case ZamTubePlugin::paramGain: | |||
| fKnobGain->setValue(value); | |||
| break; | |||
| } | |||
| } | |||
| void ZamTubeUI::d_programChanged(uint32_t index) | |||
| { | |||
| if (index != 0) | |||
| return; | |||
| // Default values | |||
| fKnobTube->setValue(0.0f); | |||
| fKnobBass->setValue(0.5f); | |||
| fKnobMids->setValue(0.5f); | |||
| fKnobTreb->setValue(0.0f); | |||
| fKnobGain->setValue(0.0f); | |||
| fSliderNotch->setValue(0.0f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| void ZamTubeUI::imageKnobDragStarted(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobTube) | |||
| d_editParameter(ZamTubePlugin::paramTubedrive, true); | |||
| else if (knob == fKnobBass) | |||
| d_editParameter(ZamTubePlugin::paramBass, true); | |||
| else if (knob == fKnobMids) | |||
| d_editParameter(ZamTubePlugin::paramMiddle, true); | |||
| else if (knob == fKnobTreb) | |||
| d_editParameter(ZamTubePlugin::paramTreble, true); | |||
| else if (knob == fKnobGain) | |||
| d_editParameter(ZamTubePlugin::paramGain, true); | |||
| } | |||
| void ZamTubeUI::imageKnobDragFinished(ImageKnob* knob) | |||
| { | |||
| if (knob == fKnobTube) | |||
| d_editParameter(ZamTubePlugin::paramTubedrive, false); | |||
| else if (knob == fKnobBass) | |||
| d_editParameter(ZamTubePlugin::paramBass, false); | |||
| else if (knob == fKnobMids) | |||
| d_editParameter(ZamTubePlugin::paramMiddle, false); | |||
| else if (knob == fKnobTreb) | |||
| d_editParameter(ZamTubePlugin::paramTreble, false); | |||
| else if (knob == fKnobGain) | |||
| d_editParameter(ZamTubePlugin::paramGain, false); | |||
| } | |||
| void ZamTubeUI::imageKnobValueChanged(ImageKnob* knob, float value) | |||
| { | |||
| if (knob == fKnobTube) | |||
| d_setParameterValue(ZamTubePlugin::paramTubedrive, value); | |||
| else if (knob == fKnobBass) | |||
| d_setParameterValue(ZamTubePlugin::paramBass, value); | |||
| else if (knob == fKnobMids) | |||
| d_setParameterValue(ZamTubePlugin::paramMiddle, value); | |||
| else if (knob == fKnobTreb) | |||
| d_setParameterValue(ZamTubePlugin::paramTreble, value); | |||
| else if (knob == fKnobGain) | |||
| d_setParameterValue(ZamTubePlugin::paramGain, value); | |||
| } | |||
| void ZamTubeUI::imageSliderDragStarted(ImageSlider*) | |||
| { | |||
| d_editParameter(ZamTubePlugin::paramToneStack, true); | |||
| } | |||
| void ZamTubeUI::imageSliderDragFinished(ImageSlider*) | |||
| { | |||
| d_editParameter(ZamTubePlugin::paramToneStack, false); | |||
| } | |||
| void ZamTubeUI::imageSliderValueChanged(ImageSlider*, float value) | |||
| { | |||
| d_setParameterValue(ZamTubePlugin::paramToneStack, value); | |||
| } | |||
| void ZamTubeUI::onDisplay() | |||
| { | |||
| fImgBackground.draw(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| { | |||
| return new ZamTubeUI(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -0,0 +1,92 @@ | |||
| /* | |||
| * ZamTube triode WDF distortion model | |||
| * Copyright (C) 2014 Damien Zammit <damien@zamaudio.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. | |||
| */ | |||
| #ifndef ZAMTUBEUI_HPP_INCLUDED | |||
| #define ZAMTUBEUI_HPP_INCLUDED | |||
| #include "DistrhoUI.hpp" | |||
| #include "ImageKnob.hpp" | |||
| #include "ImageSlider.hpp" | |||
| #include "ZamTubeArtwork.hpp" | |||
| #include "ZamTubePlugin.hpp" | |||
| using DGL::Image; | |||
| using DGL::ImageKnob; | |||
| using DGL::ImageSlider; | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| class ZamTubeUI : public UI, | |||
| public ImageKnob::Callback, | |||
| public ImageSlider::Callback | |||
| { | |||
| public: | |||
| ZamTubeUI(); | |||
| ~ZamTubeUI() override; | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Information | |||
| unsigned int d_getWidth() const noexcept override | |||
| { | |||
| return ZamTubeArtwork::zamtubeWidth; | |||
| } | |||
| unsigned int d_getHeight() const noexcept override | |||
| { | |||
| return ZamTubeArtwork::zamtubeHeight; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| void d_parameterChanged(uint32_t index, float value) ; | |||
| void d_programChanged(uint32_t index) ; | |||
| // ------------------------------------------------------------------- | |||
| // Widget Callbacks | |||
| 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; | |||
| ImageKnob* fKnobTube; | |||
| ImageKnob* fKnobBass; | |||
| ImageKnob* fKnobMids; | |||
| ImageKnob* fKnobTreb; | |||
| ImageKnob* fKnobGain; | |||
| ImageSlider* fSliderNotch; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // ZAMTUBEUI_HPP_INCLUDED | |||
| @@ -0,0 +1,21 @@ | |||
| //inv.h | |||
| #ifndef __INV_H__ | |||
| #define __INV_H__ | |||
| class ser; | |||
| class par; | |||
| #include "wdf.h" | |||
| #include "ser.h" | |||
| #include "par.h" | |||
| class inv : public Adaptor { | |||
| public: | |||
| template <class Port>inv(Port *left); | |||
| inv(ser *l); | |||
| T waveUp(); | |||
| void setWD(T waveparent); | |||
| }; | |||
| #else | |||
| #endif | |||
| @@ -0,0 +1,23 @@ | |||
| //par.h | |||
| #ifndef __PAR_H__ | |||
| #define __PAR_H__ | |||
| class inv; | |||
| class ser; | |||
| #include "wdf.h" | |||
| #include "inv.h" | |||
| #include "ser.h" | |||
| class par : public Adaptor { | |||
| public: | |||
| template <class Port1, class Port2>par(Port1 *left, Port2 *right); | |||
| par(inv *l, R* r); | |||
| par(inv *l, V* r); | |||
| par(C *l, R* r); | |||
| T waveUp(); | |||
| void setWD(T waveparent); | |||
| }; | |||
| #else | |||
| #endif | |||
| @@ -0,0 +1,22 @@ | |||
| //ser.h | |||
| #ifndef __SER_H__ | |||
| #define __SER_H__ | |||
| class inv; | |||
| class par; | |||
| #include "inv.h" | |||
| #include "par.h" | |||
| class ser : public Adaptor { | |||
| public: | |||
| template <class Port1, class Port2>ser(Port1 *left, Port2 *right); | |||
| ser(R* l, par* r); | |||
| ser(C* l, R* r); | |||
| ser(C* l, V* r); | |||
| T waveUp(); | |||
| void setWD(T waveparent); | |||
| }; | |||
| #else | |||
| #endif | |||