diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..360ea12 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vs diff --git a/AZR3.sln b/AZR3.sln new file mode 100644 index 0000000..5a23631 --- /dev/null +++ b/AZR3.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29306.81 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AZR3_vst2.4", "AZR3_vst2.4\AZR3.vcxproj", "{99B8CCFB-1485-43A8-9D2B-DB120773FA15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Debug|x64.ActiveCfg = Debug|x64 + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Debug|x64.Build.0 = Debug|x64 + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Debug|x86.ActiveCfg = Debug|Win32 + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Debug|x86.Build.0 = Debug|Win32 + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Release|x64.ActiveCfg = Release|x64 + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Release|x64.Build.0 = Release|x64 + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Release|x86.ActiveCfg = Release|Win32 + {99B8CCFB-1485-43A8-9D2B-DB120773FA15}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BB3785B3-895D-458E-BD4E-2159182A336B} + EndGlobalSection +EndGlobal diff --git a/AZR3_vst2.4/.gitignore b/AZR3_vst2.4/.gitignore new file mode 100644 index 0000000..5efe345 --- /dev/null +++ b/AZR3_vst2.4/.gitignore @@ -0,0 +1,4 @@ +/Release +/build +/Debug +/dist diff --git a/AZR3_vst2.4/AZR3.def b/AZR3_vst2.4/AZR3.def new file mode 100644 index 0000000..72ade77 --- /dev/null +++ b/AZR3_vst2.4/AZR3.def @@ -0,0 +1,2 @@ +EXPORTS VSTPluginMain + main=VSTPluginMain diff --git a/AZR3_vst2.4/AZR3.vcxproj b/AZR3_vst2.4/AZR3.vcxproj new file mode 100644 index 0000000..2225c15 --- /dev/null +++ b/AZR3_vst2.4/AZR3.vcxproj @@ -0,0 +1,557 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {99B8CCFB-1485-43A8-9D2B-DB120773FA15} + azr3 + AZR3_vst2.4 + 10.0 + + + + DynamicLibrary + v142 + Static + false + + + NotSet + + + DynamicLibrary + v142 + Static + false + x64 + NotSet + + + Static + + + true + NotSet + DynamicLibrary + v142 + + + v142 + Static + x64 + true + DynamicLibrary + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>16.0.29124.152 + + + false + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + AZR3 + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\ + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + true + false + false + true + + + false + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + AZR3 + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\ + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + true + false + false + true + + + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\ + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + false + false + AZR3 + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + true + false + false + true + + + false + false + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\ + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + AZR3 + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + true + false + false + true + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/azr3.tlb + + + + MaxSpeed + Default + WIN32;_DEBUG;NDEBUG;_WINDOWS;WINDOWS=1;DEVELOP;%(PreprocessorDefinitions) + true + MultiThreaded + true + false + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\azr3.pch + NoListing + true + Level1 + true + Default + true + Default + Cdecl + true + Precise + Speed + false + stdcpp17 + true + NotSet + false + false + ..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + false + false + false + false + NotUsing + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + shell32.lib;msvcrtd.lib;ole32.lib;gdi32.lib;User32.lib;advapi32.lib;%(AdditionalDependencies) + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\$(TargetFileName) + true + libcmt.lib;libcmtd.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) + .\$(AssemblyName).def + true + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(AssemblyName).pdb + false + + + + + MachineX86 + true + true + false + + + + + false + false + false + false + NoErrorReport + + + move $(ProjectDir)$(Configuration)\$(PlatformTarget)\$(TargetFileName) $(ProjectDir)dist\$(TargetName)_$(PlatformTarget)_$(Configuration)$(TargetExt) + + + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(TargetName).bsc + + + false + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Debug/azr3.tlb + + + + + MaxSpeed + Default + WIN32;_DEBUG;NDEBUG;_WINDOWS;WINDOWS=1;DEVELOP;%(PreprocessorDefinitions) + true + MultiThreaded + true + false + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\azr3.pch + NoListing + true + Level1 + true + Default + Default + stdcpp17 + true + true + Speed + false + NotSet + false + false + false + ..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + false + false + false + false + NotUsing + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + shell32.lib;msvcrtd.lib;ole32.lib;gdi32.lib;User32.lib;advapi32.lib;%(AdditionalDependencies) + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\$(TargetFileName) + true + libcmt.lib;libcmtd.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) + .\$(AssemblyName).def + true + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(AssemblyName).pdb + false + + + + + + + true + + + false + false + false + true + false + false + NoErrorReport + + + move $(ProjectDir)$(Configuration)\$(PlatformTarget)\$(TargetFileName) $(ProjectDir)dist\$(TargetName)_$(PlatformTarget)_$(Configuration)$(TargetExt) + + + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(TargetName).bsc + + + false + + + + + NDEBUG;%(PreprocessorDefinitions) + true + Win32 + .\Release/azr3.tlb + + + + MaxSpeed + Default + true + Speed + false + false + WIN32;_WINDOWS;WINDOWS=1;%(PreprocessorDefinitions) + true + false + MultiThreaded + true + NotSet + Precise + false + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\azr3.pch + true + true + Default + stdcpp17 + Level1 + true + false + ..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + false + false + false + false + false + NotUsing + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + libcmt.lib;uuid.lib;shell32.lib;ole32.lib;gdi32.lib;User32.lib;advapi32.lib;%(AdditionalDependencies) + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\$(TargetFileName) + true + .\$(AssemblyName).def + Windows + + + false + + + MachineX86 + + + false + false + false + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(AssemblyName).pdb + true + false + true + false + NoErrorReport + msvcrt.lib;libc.lib;msvcrtd.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) + + + move $(ProjectDir)$(Configuration)\$(PlatformTarget)\$(TargetFileName) $(ProjectDir)dist\$(TargetName)_$(PlatformTarget)$(TargetExt) + + + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(TargetName).bsc + + + false + + + + + NDEBUG;%(PreprocessorDefinitions) + true + .\Release/azr3.tlb + + + + + MaxSpeed + Default + true + Speed + false + false + WIN32;_WINDOWS;WINDOWS=1;%(PreprocessorDefinitions) + true + false + MultiThreaded + true + NotSet + Precise + false + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\azr3.pch + true + true + Default + stdcpp17 + true + false + false + ..\..\vstsdk;..\..\vstsdk\public.sdk\source\vst2.x;..\..\vstsdk\vstgui.sf\vstgui + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + false + false + false + false + false + NotUsing + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\ + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + libcmt.lib;uuid.lib;shell32.lib;ole32.lib;gdi32.lib;User32.lib;advapi32.lib;%(AdditionalDependencies) + $(ProjectDir)\$(Configuration)\$(PlatformTarget)\$(TargetFileName) + true + .\$(AssemblyName).def + Windows + + + false + + + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(AssemblyName).pdb + true + false + false + false + true + false + false + NoErrorReport + msvcrt.lib;libc.lib;msvcrtd.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) + + + move $(ProjectDir)$(Configuration)\$(PlatformTarget)\$(TargetFileName) $(ProjectDir)dist\$(TargetName)_$(PlatformTarget)$(TargetExt) + + + $(ProjectDir)build\$(Configuration)\$(PlatformTarget)\$(TargetName).bsc + + + false + + + + + + + + + + + + + + + + + + MaxSpeed + MaxSpeed + WIN32;NDEBUG;_WINDOWS;WINDOWS=1;DEVELOP + WIN32;NDEBUG;_WINDOWS;WINDOWS=1;DEVELOP + true + true + MaxSpeed + MaxSpeed + WIN32;NDEBUG;_WINDOWS;WINDOWS=1 + WIN32;NDEBUG;_WINDOWS;WINDOWS=1 + true + true + ..\vstsdk + ..\vstsdk + ..\vstsdk + + + + + + + + + ..\vstsdk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AZR3_vst2.4/AZR3.vcxproj.filters b/AZR3_vst2.4/AZR3.vcxproj.filters new file mode 100644 index 0000000..91d78f1 --- /dev/null +++ b/AZR3_vst2.4/AZR3.vcxproj.filters @@ -0,0 +1,242 @@ + + + + + {a9b0475a-28a3-49f1-838d-0dcdd4dde78f} + + + {e669ad06-5348-4c82-9365-a2b7d736a015} + h;hpp;hxx;hm;inl + + + {41bba98c-16db-452d-8316-7f44f5a38a27} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {df2ff566-c0b1-450b-9b9e-1302c4893ade} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {74b8f7b9-d927-4b3f-947f-44540f4d3504} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {732f0fd6-ae2e-47cf-920a-d837b37a4a0e} + h;hpp;hxx;hm;inl + + + {992c9ec6-3b8c-426d-8d58-2752b33de639} + + + {1607e6d0-3c81-4a74-ae61-4673a0221bd1} + + + {cdde329c-e126-4ab8-a12b-356c27586879} + + + {f9e8b030-905a-4dbe-89fd-77079692b5eb} + + + {619e6c63-21f7-4e93-af68-aaab95b86616} + + + + + Plugin\Source + + + Plugin\Source\Controls + + + Plugin\Source\Controls + + + Plugin\Source\Controls + + + VST\VSTSDK + + + VST\VSTSDK + + + VST\VSTGUI + + + VST\VSTGUI + + + VST\VSTGUI + + + VST\VSTGUI + + + Plugin\Source + + + Plugin\Source + + + Plugin\Source + + + Plugin\Source + + + Plugin\Source + + + Plugin\Source + + + Plugin\Source\Controls + + + Plugin\Source + + + Plugin\Source + + + Plugin\Source\Controls + + + Plugin\Source\Controls + + + Plugin\Source + + + Plugin\Source + + + Plugin\Source\FX + + + Plugin\Source\FX + + + Plugin\Source\FX + + + Plugin\Source\FX + + + Plugin\Source\FX + + + + + Plugin\Header + + + Plugin\Header + + + Plugin\Header\Controls + + + Plugin\Header\Controls + + + Plugin\Header\Controls + + + Plugin\Header + + + Plugin\Header + + + Plugin\Header + + + Plugin\Header\Controls + + + Plugin\Header + + + Plugin\Header\Controls + + + Plugin\Header\Controls + + + Plugin\Header + + + Plugin\Header + + + Plugin\Header\FX + + + Plugin\Header\FX + + + Plugin\Header\FX + + + Plugin\Header\FX + + + Plugin\Header\FX + + + Plugin\Header\FX + + + + + Plugin\Source + + + + + Plugin\Source + + + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + Plugin\Ressources + + + \ No newline at end of file diff --git a/AZR3_vst2.4/AZR3.vcxproj.user b/AZR3_vst2.4/AZR3.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/AZR3_vst2.4/AZR3.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/AZR3_vst2.4/Controls.cpp b/AZR3_vst2.4/Controls.cpp new file mode 100644 index 0000000..1d6bdd6 --- /dev/null +++ b/AZR3_vst2.4/Controls.cpp @@ -0,0 +1,25 @@ +/* + This is my "standard" controls library. + + CDeviceDisplay + The program display (program number and name, boot message) + + CDrawbar + Drawbars + + CCircDisplay + The knobs with integrated number display + + CTabButton + Tabs to click on... +*/ + +#include "Controls.h" +#include "resource.h" + +#include +#include +#include +#include +#include + diff --git a/AZR3_vst2.4/Controls.h b/AZR3_vst2.4/Controls.h new file mode 100644 index 0000000..e69de29 diff --git a/AZR3_vst2.4/Controls.sbr b/AZR3_vst2.4/Controls.sbr new file mode 100644 index 0000000..8bd7e4d Binary files /dev/null and b/AZR3_vst2.4/Controls.sbr differ diff --git a/AZR3_vst2.4/Controls/CAbstractVertical.cpp b/AZR3_vst2.4/Controls/CAbstractVertical.cpp new file mode 100644 index 0000000..4c479de --- /dev/null +++ b/AZR3_vst2.4/Controls/CAbstractVertical.cpp @@ -0,0 +1,129 @@ +#include "CAbstractVertical.h" +#include "../Globals.h" + +#include +#include +#include +#include +#include + +CAbstractVertical::CAbstractVertical(const CRect& size, CControlListener* listener, long tag, CBitmap* bitmap, CBitmap* background) + : CControl(size, listener, tag, background), + bitmapControl(bitmap), + firstRun(true), + offscreenContext(NULL), + lastValue(-1), + directionUp(true) +{ + controlSize(size.left, size.top, size.right, size.bottom); + width = bitmap->getWidth(); + height = bitmap->getHeight(); + + controlDimensions = { width, height }; +} + +void CAbstractVertical::draw(CDrawContext* pContext) +{ + if (firstRun) + { + offscreenContext = new COffscreenContext(this->getFrame(), controlDimensions.width, controlDimensions.height, kBlackCColor); + firstRun = false; + } + + drawControl(pContext); + + lastValue = value; +} + +void CAbstractVertical::mouse(CDrawContext* pContext, CPoint& where, long button) +{ + int x, x_start; + float range1 = .01f; + float range2 = .001f; + float range; + static bool pressed = false; + + if (!bMouseEnabled) + return; + + if (button == -1) button = pContext->getMouseButtons(); + + if (listener && button & (kAlt | kShift | kControl | kApple)) + { + if (listener->controlModifierClicked(pContext, this, button) != 0) + return; + } + + if (!(button & kLButton)) + return; + + x_start = x = where.v; + beginEdit(); + do + { + button = pContext->getMouseButtons(); + if ((button & kLButton) && !pressed) + { + pressed = true; + ((AEffGUIEditor*)this->getEditor())->setParameter(n_mousedown, (float)tag); + } + else if (!(button & kLButton) && pressed) + { + pressed = false; + ((AEffGUIEditor*)this->getEditor())->setParameter(n_mousedown, -1); + } + + if (button & kShift) + range = range2; + else + range = range1; + + getMouseLocation(pContext, where); + if (where.v != x) + { + x = x_start - where.v; + + if(directionUp) + value += range * (float)x; + else + value -= range * (float)x; + + if (value < 0.01f) + value = 0; + else if (value > 1) + value = 1; + x = x_start = where.v; + //l_value = value; + } + + bounceValue(); + + if (isDirty()) + listener->valueChanged(pContext, this); + + doIdleStuff(); + } while (button & kLButton); + endEdit(); +} + +void CAbstractVertical::drawControl(CDrawContext* pContext) +{ +} + +void CAbstractVertical::setControlDimensions(int width, int height) +{ + controlDimensions = { width, height }; +} + +void CAbstractVertical::setReverseMouseDirection() +{ + directionUp = false; +} + +CAbstractVertical::~CAbstractVertical() +{ + if (offscreenContext != NULL) + { + delete offscreenContext; + } +} diff --git a/AZR3_vst2.4/Controls/CAbstractVertical.h b/AZR3_vst2.4/Controls/CAbstractVertical.h new file mode 100644 index 0000000..e5a68af --- /dev/null +++ b/AZR3_vst2.4/Controls/CAbstractVertical.h @@ -0,0 +1,29 @@ +#pragma once +#include "../Globals.h" +#include + +class CAbstractVertical : public CControl +{ +public: + CAbstractVertical(const CRect& size, CControlListener* listener, long tag, CBitmap* bitmap, CBitmap* background); + ~CAbstractVertical(); + void draw(CDrawContext* pContext); + void mouse(CDrawContext* pContext, CPoint& where, long button); + + virtual void drawControl(CDrawContext* pContext); +protected: + float lastValue; + bool firstRun, directionUp; + int width, height; + CRect controlSize; + COffscreenContext* offscreenContext; + CBitmap* bitmapControl; + struct whTuple + { + int width; + int height; + } controlDimensions; + + void setControlDimensions(int width, int height); + void setReverseMouseDirection(); +}; diff --git a/AZR3_vst2.4/Controls/CCircDisplay.cpp b/AZR3_vst2.4/Controls/CCircDisplay.cpp new file mode 100644 index 0000000..92a6d23 --- /dev/null +++ b/AZR3_vst2.4/Controls/CCircDisplay.cpp @@ -0,0 +1,55 @@ +#include "CCircDisplay.h" +#include + +CCircDisplay::CCircDisplay(const CRect& size, CControlListener* listener, int tag, CBitmap* bitmap, CBitmap* digits, CBitmap* background) + : CAbstractVertical(size, listener, tag, bitmap, background), + digitBitmap(digits) +{ + numOfSpritePhases = int(height / width); + digitWidth = digits->getWidth(); + digitHeight = digits->getHeight() / 12; +} + +void CCircDisplay::drawControl(CDrawContext* pContext) +{ + unsigned int index; + int y = 0, z; + + if (stringConvert) + stringConvert(value, caption); + else + sprintf(caption, "%3d%", int(100 * value + .001f)); + + CRect rect(0, 0, width, width); + pBackground->draw(offscreenContext, rect, CPoint(controlSize.left, controlSize.top)); + bitmapControl->drawTransparent(offscreenContext, rect, CPoint(0, int(value * (numOfSpritePhases - 1)) * width)); + + for (index = 0; index < strlen(caption); index++) + { + if (caption[index] == '.') + { + int offsetX = 0; + if (y >= digitWidth) + offsetX = y - digitWidth; + rect(12 + offsetX, 19, 12 + offsetX + digitWidth, 19 + digitHeight); + digitBitmap->drawTransparent(offscreenContext, rect, CPoint(0, 10 * digitHeight)); + continue; + } + else if (caption[index] == ' ') + { + y += digitWidth; + continue; + } + else if (caption[index] == '%') + z = 11 * digitHeight; + else if (!isdigit(caption[index])) + continue; + else + z = digitHeight * (caption[index] - '0'); + + rect(12 + y, 18, 12 + y + digitWidth, 18 + digitHeight); + digitBitmap->drawTransparent(offscreenContext, rect, CPoint(0, z)); + y += digitWidth; + } + offscreenContext->copyFrom(pContext, CRect(controlSize.left, controlSize.top, controlSize.left + width, controlSize.top + width), CPoint(0, 0)); +} diff --git a/AZR3_vst2.4/Controls/CCircDisplay.h b/AZR3_vst2.4/Controls/CCircDisplay.h new file mode 100644 index 0000000..25887ba --- /dev/null +++ b/AZR3_vst2.4/Controls/CCircDisplay.h @@ -0,0 +1,18 @@ +#pragma once +#include "customControl.h" +#include "CAbstractVertical.h" + +class CCircDisplay : + public customControl, + public CAbstractVertical +{ +public: + CCircDisplay(const CRect& size, CControlListener* listener, int tag, CBitmap* bitmap, CBitmap* digits, CBitmap* background); + //void setStringConvert(void (*convert) (float value, char* string)); + void drawControl(CDrawContext* pContext); +protected: + //void (*stringConvert)(float value, char* string); + //void (*parameterConversions::*stringConvert) (float value, char* string); + int numOfSpritePhases, digitWidth, digitHeight; + CBitmap* digitBitmap; +}; diff --git a/AZR3_vst2.4/Controls/CDeviceDisplay.cpp b/AZR3_vst2.4/Controls/CDeviceDisplay.cpp new file mode 100644 index 0000000..3ecf205 --- /dev/null +++ b/AZR3_vst2.4/Controls/CDeviceDisplay.cpp @@ -0,0 +1,115 @@ +#include "CDeviceDisplay.h" + +CDeviceDisplay::CDeviceDisplay(const CRect& size, CControlListener* listener, long tag, CBitmap* background) : CControl(size, listener, tag, background) +{ + my_tag = tag; + top = size.top; + bottom = size.bottom; + left = size.left; + right = size.right; + first = 1; + line1[0] = 0; + line2[0] = 0; + line3[0] = 0; + line4[0] = 0; + last_value = -2; + linevalue = -1; + my_drawcontext = NULL; + oc = NULL; +} + +void CDeviceDisplay::draw(CDrawContext* pContext) +{ + last_value = value; + my_drawcontext = pContext; + if (first == 1) + { + oc = new COffscreenContext(this->getFrame(), right - left, bottom - top, kBlackCColor); + first = 0; + } + CRect rect(0, 0, right - left, bottom - top); + pBackground->draw(oc, rect, CPoint(left, top)); + oc->setFont(kNormalFontVerySmall); + { + CColor mc = { 255,236,200,0 }; + oc->setFontColor(mc); + oc->setLineWidth(1); + oc->setFrameColor(mc); + mc.red = 126; + mc.green = 210; + mc.blue = 204; + oc->setFillColor(mc); + } + oc->drawString(line1, CRect(2, 0, right - left, 10), false, kLeftText); + oc->drawString(line2, CRect(2, 10, right - left, 10 + 10), false, kLeftText); + oc->drawString(line3, CRect(2, 20, right - left, 20 + 10), false, kLeftText); + oc->drawString(line4, CRect(2, 30, right - left, 30 + 10), false, kLeftText); + if (linevalue >= 0) + { + oc->drawRect(CRect(2, 42, right - left - 2, 48)); + oc->fillRect(CRect(3, 43, 4 + (int)((right - left - 7) * linevalue), 47)); + } + oc->copyFrom(pContext, CRect(left, top, right, bottom), CPoint(0, 0)); +} + +void CDeviceDisplay::setline(float value) +{ + linevalue = value; + this->setDirty(); +} + +void CDeviceDisplay::setstring(int line, char* string) +{ + if (line == 1) + strncpy(line1, string, sizeof(line1)); + else if (line == 2) + strncpy(line2, string, sizeof(line2)); + else if (line == 3) + strncpy(line3, string, sizeof(line3)); + else if (line == 4) + strncpy(line4, string, sizeof(line4)); + this->setDirty(); +} + +void CDeviceDisplay::mouse(CDrawContext* pContext, CPoint& where, long button) +{ + int x; + x = where.v; + + beginEdit(); + do + { + button = pContext->getMouseButtons(); + getMouseLocation(pContext, where); + + if (abs(where.v - x) > 10) + { + if (where.v < x) + { + if (value > 0) + { + setDirty(true); + value--; + } + } + else + { + setDirty(true); + value++; + } + x = where.v; + } + + if (isDirty()) + listener->valueChanged(pContext, this); + + doIdleStuff(); + } while (button & kLButton); + endEdit(); +} + +CDeviceDisplay::~CDeviceDisplay() +{ + if (oc != NULL) + delete oc; +} diff --git a/AZR3_vst2.4/Controls/CDeviceDisplay.h b/AZR3_vst2.4/Controls/CDeviceDisplay.h new file mode 100644 index 0000000..8d58eb9 --- /dev/null +++ b/AZR3_vst2.4/Controls/CDeviceDisplay.h @@ -0,0 +1,21 @@ +#pragma once +#include "../Globals.h" +#include + +class CDeviceDisplay : public CControl +{ +public: + CDeviceDisplay(const CRect& size, CControlListener* listener, long tag, CBitmap* background); + ~CDeviceDisplay(); + void draw(CDrawContext* pContext); + void mouse(CDrawContext* pContext, CPoint& where, long button); + void setstring(int line, char* string); + void setline(float value); +protected: + float last_value; + int top, left, bottom, right, first, my_tag; + COffscreenContext* oc; + CDrawContext* my_drawcontext; + char line1[256], line2[256], line3[256], line4[256]; + float linevalue; +}; diff --git a/AZR3_vst2.4/Controls/CDrawbar.cpp b/AZR3_vst2.4/Controls/CDrawbar.cpp new file mode 100644 index 0000000..0166413 --- /dev/null +++ b/AZR3_vst2.4/Controls/CDrawbar.cpp @@ -0,0 +1,22 @@ +#include "CDrawbar.h" + +CDrawbar::CDrawbar(const CRect& size, CControlListener* listener, long tag, CBitmap* bitmap, CBitmap* background, int handleHeight) + : CAbstractVertical(size, listener, tag, bitmap, background), + faderBitmap(bitmap), + handleHeight(handleHeight) +{ + setControlDimensions(controlSize.right - controlSize.left, controlSize.bottom - controlSize.top); + setReverseMouseDirection(); +} + +void CDrawbar::drawControl(CDrawContext* pContext) +{ + int pos = int((1 - value) * (height - handleHeight)); + + CRect rect(0, 0, width, height); + faderBitmap->draw(offscreenContext, rect, CPoint(0, pos)); + rect(0, height - pos, width, height); + pBackground->draw(offscreenContext, rect, CPoint(controlSize.left, controlSize.bottom - pos)); + rect(controlSize.left, controlSize.top, controlSize.right, controlSize.bottom); + offscreenContext->copyFrom(pContext, rect, CPoint(0, 0)); +} diff --git a/AZR3_vst2.4/Controls/CDrawbar.h b/AZR3_vst2.4/Controls/CDrawbar.h new file mode 100644 index 0000000..d9ce95c --- /dev/null +++ b/AZR3_vst2.4/Controls/CDrawbar.h @@ -0,0 +1,12 @@ +#pragma once +#include "CAbstractVertical.h" +class CDrawbar : + public CAbstractVertical +{ +public: + CDrawbar(const CRect& size, CControlListener* listener, long tag, CBitmap* bitmap, CBitmap* background, int handleHeight); + void drawControl(CDrawContext* pContext); +protected: + int handleHeight; + CBitmap* faderBitmap; +}; diff --git a/AZR3_vst2.4/Controls/CTabButton.cpp b/AZR3_vst2.4/Controls/CTabButton.cpp new file mode 100644 index 0000000..d68b779 --- /dev/null +++ b/AZR3_vst2.4/Controls/CTabButton.cpp @@ -0,0 +1,34 @@ +#include "CTabButton.h" + +CTabButton::CTabButton(CRect& size, CControlListener* listener, int tag, CBitmap* bm) : CControl(size, listener, tag, bm) +{ +} + +CTabButton::~CTabButton() +{ +} + +void CTabButton::draw(CDrawContext* pContext) +{ +} + +void CTabButton::mouse(CDrawContext* pContext, CPoint& where, long button) +{ + + if (!bMouseEnabled) + return; + + if (button == -1) button = pContext->getMouseButtons(); + + if (listener && button & (kAlt | kShift | kControl | kApple)) + { + if (listener->controlModifierClicked(pContext, this, button) != 0) + return; + } + + if (!(button & kLButton)) + return; + + if (button) + ((AEffGUIEditor*)this->getEditor())->setParameter(tag, 1); +} diff --git a/AZR3_vst2.4/Controls/CTabButton.h b/AZR3_vst2.4/Controls/CTabButton.h new file mode 100644 index 0000000..40a3222 --- /dev/null +++ b/AZR3_vst2.4/Controls/CTabButton.h @@ -0,0 +1,12 @@ +#pragma once +#include "../Globals.h" +#include + +class CTabButton : public CControl +{ +public: + CTabButton(CRect& size, CControlListener* listener, int tag, CBitmap* bm); + ~CTabButton(); + void draw(CDrawContext* pContext); + void mouse(CDrawContext* pContext, CPoint& where, long button); +}; diff --git a/AZR3_vst2.4/Controls/customControl.cpp b/AZR3_vst2.4/Controls/customControl.cpp new file mode 100644 index 0000000..b101d88 --- /dev/null +++ b/AZR3_vst2.4/Controls/customControl.cpp @@ -0,0 +1,11 @@ +#include "customControl.h" + +customControl::customControl() + : stringConvert(NULL), caption(" ") +{ +} + +void customControl::setStringConvert(void (*convert) (float value, char* string)) +{ + stringConvert = convert; +} diff --git a/AZR3_vst2.4/Controls/customControl.h b/AZR3_vst2.4/Controls/customControl.h new file mode 100644 index 0000000..eb4cd00 --- /dev/null +++ b/AZR3_vst2.4/Controls/customControl.h @@ -0,0 +1,11 @@ +#pragma once +#include "../parameterConversions.h" + +class customControl +{ +public: + customControl(); + virtual void setStringConvert(void (*convert) (float value, char* string)); + void (*stringConvert)(float value, char* string); + char caption[16]; +}; diff --git a/AZR3_vst2.4/Editor.cpp b/AZR3_vst2.4/Editor.cpp new file mode 100644 index 0000000..3c2156d --- /dev/null +++ b/AZR3_vst2.4/Editor.cpp @@ -0,0 +1,1010 @@ +#include +#include +#include +#include + +#include "Editor.h" +#include "noteController.h" + +#if WIN32 +#include "resource.h" +#else +enum +{ + IDB_cknob = 128, + IDB_vonoff, + IDB_dbbrown, + IDB_dbwhite, + IDB_inside, + IDB_miniledred, + IDB_minioffon, + IDB_yellow, + IDB_onoffgreen, + IDB_dbblack, + IDB_panelfx, + IDB_panelvoice, + IDB_vu +}; +#endif + + +Editor::~Editor() +{ +} + + +Editor::Editor(AudioEffect* effect) : AEffGUIEditor(effect) +{ + m1 = 0, m2 = 0, m3 = 0; + ticks = 0; + frame = 0; + frame_ok = false; + rect.left = 0; + rect.top = 0; + rect.right = 709; + rect.bottom = 448; + justloaded = true; + //effect->setEditor (this); +} + +void Editor::idle() +{ + if (ctrl_splash->getValue()) + return; + if (!justloaded && getTicks() - oldTicks < 200) + return; + if (!controls[n_1_midi] || !controls[n_2_midi] || !controls[n_3_midi] + || !ctrl_display) + return; + + if (justloaded && ctrl_display) + { + if (ticks < 100) + { + controls[n_1_midi]->setValue(1); + controls[n_2_midi]->setValue(1); + controls[n_3_midi]->setValue(1); + ctrl_display->setstring(1, "=== Rumpelrausch Täips ==="); + ctrl_display->setstring(2, "Loading Rumpel/OS V3"); + ctrl_display->setstring(3, ""); + } + else if (ticks > 1000) + { + effect->setParameter(n_mute, 0); + ctrl_display->setline(-1); + ctrl_display->setstring(1, "=== PLEASE DONATE ==="); + ctrl_display->setstring(2, ""); + ctrl_display->setstring(3, "have fun"); + ctrl_display->setstring(4, " flp"); + } + else if (ticks <= 1000) + { + ctrl_display->setline((float)ticks / 1000); + } + + if (ticks > 3500) + { + setParameter(n_display, -1); + justloaded = false; + } + ctrl_display->setDirty(true); + } + else + { + long t = getTicks(); + if (m1 < 0) + { + controls[n_1_midi]->setValue(1); + m1 = t; + } + if (m2 < 0) + { + controls[n_2_midi]->setValue(1); + m2 = t; + } + if (m3 < 0) + { + controls[n_3_midi]->setValue(1); + m3 = t; + } + + if (t > m1 + 50) + { + controls[n_1_midi]->setValue(0); + m1 = 0; + } + if (t > m2 + 50) + { + controls[n_2_midi]->setValue(0); + m2 = 0; + } + if (t > m3 + 50) + { + controls[n_3_midi]->setValue(0); + m3 = 0; + } + } + + if (controls[n_vu] != NULL) + controls[n_vu]->setValue(effect->getParameter(n_output)); + + ticks = getTicks() - oldTicks; + AEffGUIEditor::idle(); + if (ctrl_display != NULL) + ctrl_display->setDirty(true); +} + +bool Editor::open(void* ptr) +{ + oldTicks = getTicks(); + panelmode = n_voicemode; + // panelmode = n_fxmode; + ticks = 0; + frame = 0; + AEffGUIEditor::open(ptr); + int version = getVstGuiVersion(); + int verMaj = (version & 0xFF00) >> 16; + int verMin = (version & 0x00FF); + int x, c; + + mousedown = -1; + + // initialize control array + for (x = 0; x < kNumControls; x++) + controls[x] = NULL; + + CPoint point(0, 0); + CRect rct(387, 17, 529, 68); + + bitmaps[b_panelvoice] = new CBitmap(IDB_panelvoice); + int panel_width = bitmaps[b_panelvoice]->getWidth(); + int panel_height = bitmaps[b_panelvoice]->getHeight(); + rct(0, 0, panel_width, panel_height); + frame = new CFrame(rct, ptr, this); + frame->setBackground(bitmaps[b_panelvoice]); + frame->setTransparency(false); + + bitmaps[b_panelfx] = new CBitmap(IDB_panelfx); + bitmaps[b_cknob] = new CBitmap(IDB_cknob); + bitmaps[b_dbblack] = new CBitmap(IDB_dbblack); + bitmaps[b_dbbrown] = new CBitmap(IDB_dbbrown); + bitmaps[b_dbwhite] = new CBitmap(IDB_dbwhite); + bitmaps[b_inside] = new CBitmap(IDB_inside); + bitmaps[b_miniledred] = new CBitmap(IDB_miniledred); + bitmaps[b_minioffon] = new CBitmap(IDB_minioffon); + bitmaps[b_onoffgreen] = new CBitmap(IDB_onoffgreen); + bitmaps[b_vonoff] = new CBitmap(IDB_vonoff); + bitmaps[b_yellow] = new CBitmap(IDB_yellow); + bitmaps[b_vu] = new CBitmap(IDB_vu); + + CCircDisplay* ctrl; + + rct(387, 17, 529, 68); + ctrl_display = new CDeviceDisplay(rct, this, n_display, bitmaps[b_panelvoice]); + frame->addView(ctrl_display); + +#ifdef DELAYED_PARAMS + rct(537, 19, 537 + 11, 19 + 12); + ctrl_compare = new COnOffButton(rct, this, n_compare, bitmaps[b_minioffon]); + frame->addView(ctrl_compare); +#endif + + rct(537, 49, 537 + 11, 49 + 12); + ctrl_split = new COnOffButton(rct, this, n_split, bitmaps[b_minioffon]); + frame->addView(ctrl_split); + +#ifdef DELAYED_PARAMS + rct(537, 34, 537 + 11, 34 + 12); + ctrl_save = new CKickButton(rct, this, n_save, 12, bitmaps[b_minioffon], point); + frame->addView(ctrl_save); +#endif + + //-------- enumerated controls + + c = n_mono; + rct(61, 105, 61 + 11, 105 + 12); + controls[c] = new COnOffButton(rct, this, c, bitmaps[b_minioffon]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_click; + rct(2 * 44, 2 * 44, 2 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_bender; + rct(3 * 44, 2 * 44, 3 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_bendrange); + frame->addView(controls[c]); + { + CCircDisplay* ctrl1 = (CCircDisplay*)controls[c]; + ctrl1->setStringConvert(parameterConversions::convert_bendrange); + } + ctyp[c] = cCCircDisplay; + + c = n_sustain; + rct(4 * 44, 2 * 44, 4 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_shape; + rct(5 * 44, 2 * 44, 5 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_shape); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_perc; + rct(7 * 44, 2 * 44, 7 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_perc); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_percvol; + rct(8 * 44, 2 * 44, 8 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_percfade; + rct(9 * 44, 2 * 44, 9 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_vol1; + rct(11 * 44, 2 * 44, 11 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_vol2; + rct(12 * 44, 2 * 44, 12 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_vol3; + rct(13 * 44, 2 * 44, 13 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_master; + rct(14 * 44, 2 * 44, 14 * 44 + 44, 2 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + + + c = n_1_perc; + rct(16, 173, 16 + 11, 173 + 12); + controls[c] = new COnOffButton(rct, this, c, bitmaps[b_minioffon]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_1_sustain; + rct(16, 213, 16 + 11, 213 + 12); + controls[c] = new COnOffButton(rct, this, c, bitmaps[b_minioffon]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_1_midi; + rct(15, 286, 15 + 14, 286 + 7); + controls[c] = new CMovieBitmap(rct, this, + c, 2, 7, bitmaps[b_miniledred], point); + frame->addView(controls[c]); + ctyp[c] = cCMovieBitmap; + + c = n_1_db1; + rct(42, 159, 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbbrown], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db3; + rct(1 * 24 + 42, 159, 1 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbbrown], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db2; + rct(2 * 24 + 42, 159, 2 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db4; + rct(3 * 24 + 42, 159, 3 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db5; + rct(4 * 24 + 42, 159, 4 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbblack], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db6; + rct(5 * 24 + 42, 159, 5 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db7; + rct(6 * 24 + 42, 159, 6 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbblack], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db8; + rct(7 * 24 + 42, 159, 7 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbblack], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_1_db9; + rct(8 * 24 + 42, 159, 8 * 24 + 42 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + + + c = n_2_perc; + rct(279, 173, 279 + 11, 173 + 12); + controls[c] = new COnOffButton(rct, this, c, bitmaps[b_minioffon]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_2_sustain; + rct(279, 213, 279 + 11, 213 + 12); + controls[c] = new COnOffButton(rct, this, c, bitmaps[b_minioffon]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_2_midi; + rct(278, 286, 278 + 14, 286 + 7); + controls[c] = new CMovieBitmap(rct, this, + c, 2, 7, bitmaps[b_miniledred], point); + frame->addView(controls[c]); + ctyp[c] = cCMovieBitmap; + + c = n_2_db1; + rct(305, 159, 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbbrown], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db3; + rct(1 * 24 + 305, 159, 1 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbbrown], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db2; + rct(2 * 24 + 305, 159, 2 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db4; + rct(3 * 24 + 305, 159, 3 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db5; + rct(4 * 24 + 305, 159, 4 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbblack], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db6; + rct(5 * 24 + 305, 159, 5 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db7; + rct(6 * 24 + 305, 159, 6 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbblack], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db8; + rct(7 * 24 + 305, 159, 7 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbblack], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_2_db9; + rct(8 * 24 + 305, 159, 8 * 24 + 305 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + + + c = n_3_perc; + rct(543, 173, 543 + 11, 173 + 12); + controls[c] = new COnOffButton(rct, this, c, bitmaps[b_minioffon]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_3_sustain; + rct(543, 213, 543 + 11, 213 + 12); + controls[c] = new COnOffButton(rct, this, c, bitmaps[b_minioffon]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_3_midi; + rct(542, 286, 542 + 14, 286 + 7); + controls[c] = new CMovieBitmap(rct, this, + c, 2, 7, bitmaps[b_miniledred], point); + frame->addView(controls[c]); + ctyp[c] = cCMovieBitmap; + + c = n_3_db1; + rct(569, 159, 569 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbbrown], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_3_db3; + rct(1 * 24 + 569, 159, 1 * 24 + 569 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbbrown], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_3_db2; + rct(2 * 24 + 569, 159, 2 * 24 + 569 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_3_db4; + rct(3 * 24 + 569, 159, 3 * 24 + 569 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbwhite], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + c = n_3_db5; + rct(4 * 24 + 569, 159, 4 * 24 + 569 + 22, 159 + 150); + controls[c] = new CDrawbar(rct, this, + c, bitmaps[b_dbblack], bitmaps[b_panelfx], 31); + frame->addView(controls[c]); + ctyp[c] = cCFader; + + + //------ mode switches -------------------------------------- + c = n_voicemode; + rct(15, 322, 28, 362); + controls[c] = new CTabButton(rct, this, + c, bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCTab; + + c = n_fxmode; + rct(15, 368, 28, 410); + controls[c] = new CTabButton(rct, this, + c, bitmaps[b_panelfx]); + frame->addView(controls[c]); + ctyp[c] = cCTab; + + + //------ voiceController params --------------------------------------- + + c = n_1_vibrato; + rct(39, 332, 39 + 25, 332 + 11); + controls[c] = new COnOffButton(rct, this, + c, bitmaps[b_onoffgreen]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_1_vstrength; + rct(2 * 44, 8 * 44, 2 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelvoice]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_1_vmix; + rct(4 * 44, 8 * 44, 4 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelvoice]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + + + c = n_2_vibrato; + rct(302, 332, 302 + 25, 332 + 11); + controls[c] = new COnOffButton(rct, this, + c, bitmaps[b_onoffgreen]); + frame->addView(controls[c]); + ctyp[c] = cCOnOffButton; + + c = n_2_vstrength; + rct(8 * 44, 8 * 44, 8 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelvoice]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + c = n_2_vmix; + rct(10 * 44, 8 * 44, 10 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelvoice]); + frame->addView(controls[c]); + ctyp[c] = cCCircDisplay; + + + //------ FX params --------------------------------------- + + c = n_mrvalve; + rct(39, 332, 39 + 25, 332 + 11); + controls[c] = new COnOffButton(rct, this, + c, bitmaps[b_onoffgreen]); + ctyp[c] = cCOnOffButton; + + c = n_drive; + rct(1 * 44, 8 * 44, 1 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctyp[c] = cCCircDisplay; + + c = n_set; + rct(2 * 44, 8 * 44, 2 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctyp[c] = cCCircDisplay; + + c = n_tone; + rct(3 * 44, 8 * 44, 3 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_tone); + ctyp[c] = cCCircDisplay; + + c = n_mix; + rct(4 * 44, 8 * 44, 4 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctyp[c] = cCCircDisplay; + + + + + c = n_speakers; + rct(302, 332, 302 + 25, 332 + 11); + controls[c] = new COnOffButton(rct, this, + c, bitmaps[b_onoffgreen]); + ctyp[c] = cCOnOffButton; + + c = n_complex; + rct(444, 331, 444 + 11, 331 + 12); + controls[c] = new COnOffButton(rct, this, + c, bitmaps[b_minioffon]); + ctyp[c] = cCOnOffButton; + + c = n_pedalspeed; + rct(512, 331, 512 + 11, 331 + 12); + controls[c] = new COnOffButton(rct, this, + c, bitmaps[b_minioffon]); + ctyp[c] = cCOnOffButton; + + c = n_speed; + rct(322, 356, 322 + 15, 356 + 28); + controls[c] = new COnOffButton(rct, this, + c, bitmaps[b_vonoff]); + ctyp[c] = cCOnOffButton; + + + + c = n_l_slow; + rct(8 * 44, 8 * 44, 8 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_speed); + ctyp[c] = cCCircDisplay; + + c = n_l_fast; + rct(9 * 44, 8 * 44, 9 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_speed); + ctyp[c] = cCCircDisplay; + + c = n_u_slow; + rct(10 * 44, 8 * 44, 10 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_speed); + ctyp[c] = cCCircDisplay; + + c = n_u_fast; + rct(11 * 44, 8 * 44, 11 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctrl = (CCircDisplay*)controls[c]; + ctrl->setStringConvert(parameterConversions::convert_speed); + ctyp[c] = cCCircDisplay; + + c = n_belt; + rct(12 * 44, 8 * 44, 12 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctyp[c] = cCCircDisplay; + + c = n_spread; + rct(13 * 44, 8 * 44, 13 * 44 + 44, 8 * 44 + 44); + controls[c] = new CCircDisplay(rct, this, + c, bitmaps[b_cknob], bitmaps[b_yellow], bitmaps[b_panelfx]); + ctyp[c] = cCCircDisplay; + + //------ splash screen --------------------------------------- + + rct(677, 7, 707, 78); + CRect rcti(0, 0, bitmaps[b_inside]->getWidth(), bitmaps[b_inside]->getHeight()); + ctrl_splash = new CSplashScreen(rct, this, n_splash, bitmaps[b_inside], rcti, point); + frame->addView(ctrl_splash); + + c = n_vu; + rct(470, 428, 470 + 113, 428 + 20); + controls[c] = new CMovieBitmap(rct, this, + c, 5, 20, bitmaps[b_vu], point); + frame->addView(controls[c]); + ctyp[c] = cCMovieBitmap; + + for (x = 0; x < kNumControls; x++) + if (controls[x]) + controls[x]->setTransparency(false); + + ctrl_display->setTransparency(false); +#ifdef DELAYED_PARAMS + ctrl_save->setTransparency(false); + ctrl_compare->setTransparency(false); +#endif + ctrl_splash->setTransparency(false); + + frame->draw(); + + for (x = 0; x < kNumParams; x++) // let's fetch all values since effect does not do it + { + if (controls[x] != NULL) + controls[x]->setValue(effect->getParameter(x)); + } + + setParameter(n_display, 1); + + frame_ok = true; + setParameter(n_fxmode, 1); + frame->setDirty(true); + return true; +} + +void Editor::close() +{ + int x; + // attach the missing controls so they get removed automatically + if (panelmode == n_fxmode) + { + c_visible(n_1_vibrato, true); + c_visible(n_1_vstrength, true); + c_visible(n_1_vmix, true); + c_visible(n_2_vibrato, true); + c_visible(n_2_vstrength, true); + c_visible(n_2_vmix, true); + } + else + { + c_visible(n_mrvalve, true); + c_visible(n_drive, true); + c_visible(n_set, true); + c_visible(n_tone, true); + c_visible(n_mix, true); + c_visible(n_speakers, true); + c_visible(n_speed, true); + c_visible(n_l_slow, true); + c_visible(n_l_fast, true); + c_visible(n_u_slow, true); + c_visible(n_u_fast, true); + c_visible(n_belt, true); + c_visible(n_spread, true); + c_visible(n_complex, true); + c_visible(n_pedalspeed, true); + } + + for (x = 0; x < kNumBitmaps; x++) + if (bitmaps[x] != NULL) + bitmaps[x]->forget(); + + if (frame) + delete frame; + frame = 0; + +} + +void Editor::valueChanged(CDrawContext* context, CControl* control) +{ + if (!control) + return; + long tag = control->getTag(); + float value = control->getValue(); + + effect->setParameter(n_param_is_manual, 1); + +#ifdef DELAYED_PARAMS + if (tag == n_compare) + effect->setParameterAutomated(tag, value); + else +#endif + if (tag == n_display) + { + effect->setParameterAutomated(tag, value); + ctrl_display->redraw(); + setParameter(tag, value); + } +#ifdef DELAYED_PARAMS + else if (tag == n_save) + { + if (control->getValue() == 0) + { + ctrl_display->setstring(3, "program saved"); + ctrl_compare->setValue(0); + ctrl_compare->draw(context); + ctrl_display->draw(context); + effect->setParameterAutomated(tag, 1); + effect->setParameterAutomated(n_compare, 0); + } + control->draw(context); + // control->update(context); + control->setDirty(true); + } +#endif + else if (tag == n_split) + { + if (value > .5f) + { + ctrl_display->setstring(3, "Select Pedal Splitpoint"); + effect->setParameter(n_split, 1); + } + else + { + ctrl_display->setstring(3, "Splitpoint removed"); + effect->setParameter(n_split, 0); + } + } + else if (tag == n_splash) + effect->setParameter(tag, value); + + + if (tag >= 0 && tag < kNumParams) + { +#ifdef DELAYED_PARAMS + if (ctrl_compare->getValue() > 0) + { + control->setValue(effect->getParameter(tag)); + control->redraw(); + control->setDirty(false); + } + else +#endif + { + control->redraw(); + effect->setParameterAutomated(tag, value); + +#ifdef DELAYED_PARAMS + ctrl_display->setstring(3, " * modified *"); +#else + ctrl_display->setstring(3, ""); +#endif + ctrl_display->redraw(); + } + + if (mousedown >= 0) // show actual value in parameter display + { + char t[256], t2[40]; + effect->getParameterDisplay(tag, t2); + effect->getParameterName(tag, t); + sprintf(t, "%s : %s", t, t2); + ctrl_display->setstring(4, t); + ctrl_display->setline(value); + ctrl_display->setDirty(true); + } + } + effect->setParameter(n_param_is_manual, 0); +} + +void Editor::setParameter(VstInt32 index, float value) +{ + CControl* ctrl = NULL; + + if (!frame || !frame_ok) + return; + + if (index == n_mousedown) // mouse button down on control + { + int tag = (int)value; + if (value == -1) + { + ctrl_display->setstring(4, ""); + ctrl_display->setline(-1); + mousedown = -1; + } + else if (tag >= 0 && tag < kNumParams) + { + char t[256], t2[40]; + effect->getParameterDisplay(tag, t2); + effect->getParameterName(tag, t); + sprintf(t, "%s : %s", t, t2); + ctrl_display->setline(effect->getParameter(tag)); + ctrl_display->setstring(4, t); + mousedown = tag; + } + ctrl_display->setDirty(true); + } + else if (index == n_1_midi) + m1 = -1; + else if (index == n_2_midi) + m2 = -1; + else if (index == n_3_midi) + m3 = -1; + else if (index == n_display) + { + char t[256]; + long curProgram = effect->getProgram(); + ctrl_display->setValue((float)curProgram); + effect->getProgramName(t); + ctrl_display->setstring(2, t); + sprintf(t, "Rumpelrausch AZR3 V%s P%02d", VERSION, curProgram); + ctrl_display->setstring(1, t); + ctrl_display->setstring(4, ""); + ctrl_display->setline(-1); +#ifdef DELAYED_PARAMS + if (ctrl_compare->getValue() == 0) + ctrl_display->setstring(3, ""); +#endif + ctrl_display->setDirty(true); + return; + } + else if (index == n_voicemode && index != panelmode) + { + c_visible(n_mrvalve, false); + c_visible(n_drive, false); + c_visible(n_set, false); + c_visible(n_tone, false); + c_visible(n_mix, false); + c_visible(n_speakers, false); + c_visible(n_speed, false); + c_visible(n_l_slow, false); + c_visible(n_l_fast, false); + c_visible(n_u_slow, false); + c_visible(n_u_fast, false); + c_visible(n_belt, false); + c_visible(n_spread, false); + c_visible(n_complex, false); + c_visible(n_pedalspeed, false); + frame->setBackground(bitmaps[b_panelvoice]); + c_visible(n_1_vibrato, true); + c_visible(n_1_vstrength, true); + c_visible(n_1_vmix, true); + c_visible(n_2_vibrato, true); + c_visible(n_2_vstrength, true); + c_visible(n_2_vmix, true); + + frame->setDirty(true); + panelmode = index; + } + else if (index == n_fxmode && index != panelmode) + { + c_visible(n_1_vstrength, false); + c_visible(n_1_vibrato, false); + c_visible(n_1_vmix, false); + c_visible(n_2_vstrength, false); + c_visible(n_2_vibrato, false); + c_visible(n_2_vmix, false); + frame->setBackground(bitmaps[b_panelfx]); + c_visible(n_mrvalve, true); + c_visible(n_drive, true); + c_visible(n_set, true); + c_visible(n_tone, true); + c_visible(n_mix, true); + c_visible(n_speakers, true); + c_visible(n_speed, true); + c_visible(n_l_slow, true); + c_visible(n_l_fast, true); + c_visible(n_u_slow, true); + c_visible(n_u_fast, true); + c_visible(n_belt, true); + c_visible(n_spread, true); + c_visible(n_complex, true); + c_visible(n_pedalspeed, true); + + frame->setDirty(true); + panelmode = index; + } + else if (index == n_split) + { + char txt[64]; + sprintf(txt, "Splitpoint=%s", noteController::note2str(long(value * 128))); + ctrl_display->setstring(3, txt); + ctrl_split->setValue(0); + } + else if ((index >= 0 && index < kNumParams) || index == n_compare) + { + if (value == -1) + value = effect->getParameter(index); + + if (controls[index] != NULL) + ctrl = controls[index]; + + if (ctrl != NULL) + { + if (value == ctrl->getValue()) + return; + ctrl->setValue(value); + ctrl->setDirty(true); + // postUpdate(); + } + } +} + +void Editor::c_visible(long tag, bool show) +{ + CControl* control = controls[tag]; + if (control == NULL) + return; + if (show) + frame->addView(control); + else + frame->removeView(control, false); +} \ No newline at end of file diff --git a/AZR3_vst2.4/Editor.h b/AZR3_vst2.4/Editor.h new file mode 100644 index 0000000..ae31b0b --- /dev/null +++ b/AZR3_vst2.4/Editor.h @@ -0,0 +1,78 @@ +#pragma once +#include "audioeffectx.h" +#include "aeffeditor.h" + +#include "Globals.h" +#include "parameterConversions.h" +#include "Controls.h" +#include "Controls/CCircDisplay.h" +#include "Controls/CDrawbar.h" +#include "Controls/CDeviceDisplay.h" +#include "Controls/CTabButton.h" + +#include "vstgui.h" + +enum +{ + cCOnOffButton=0, + cCParamDisplay, + cCTextEdit, + cCOptionMenu, + cCKnob, + cCAnimKnob, + cCVerticalSwitch, + cCHorizontalSwitch, + cCRockerSwitch, + cCMovieBitmap, + cCMovieButton, + cCAutoAnimation, + cCVerticalSlider, + cCHorizontalSlider, + cCSpecialDigit, + cCKickButton, + cCSplashScreen, + cCVuMeter, + cCFileSelector, + cCDisplay, + cCFader, + cCCircDisplay, + cCTab, + cCTextSplash, + +}; + + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class Editor : public AEffGUIEditor, public CControlListener +{ +public: + Editor (AudioEffect *effect); + virtual ~Editor (); + virtual void idle(); +protected: + virtual bool open (void *ptr); + virtual void close (); + virtual void setParameter (VstInt32 index, float value); + virtual void valueChanged (CDrawContext* context, CControl* control); + void c_visible(long tag,bool show); + +private: + int panelmode; + long m1,m2,m3; + long oldTicks,ticks; + int panel_width,panel_height; + bool justloaded,frame_ok; + int mousedown; + + CBitmap* bitmaps[kNumBitmaps]; + CControl* controls[kNumControls]; + int ctyp[kNumControls]; + CDeviceDisplay* ctrl_display; + COnOffButton* ctrl_compare; + COnOffButton* ctrl_split; + CKickButton* ctrl_save; + CSplashScreen* ctrl_splash; +}; diff --git a/AZR3_vst2.4/Editor.sbr b/AZR3_vst2.4/Editor.sbr new file mode 100644 index 0000000..90c5b3a Binary files /dev/null and b/AZR3_vst2.4/Editor.sbr differ diff --git a/AZR3_vst2.4/FX/fxAllpass.cpp b/AZR3_vst2.4/FX/fxAllpass.cpp new file mode 100644 index 0000000..63d35a6 --- /dev/null +++ b/AZR3_vst2.4/FX/fxAllpass.cpp @@ -0,0 +1,29 @@ +#include "fxAllpass.h" + +fxAllpass::fxAllpass() : a1(0.f), zm1(0.f) +{ + a1 = zm1 = my_delay = y = 0; +} + +void fxAllpass::reset() +{ + a1 = zm1 = y = 0; + set_delay(my_delay); +} + +void fxAllpass::set_delay(float fxDelay) +{ + my_delay = fxDelay; + a1 = (1 - fxDelay) / (1 + fxDelay); + a1 = DENORMALIZE(a1); +} + +float fxAllpass::clock(float input) +{ + if (input<.00000001f && input>-.00000001f) // prevent Pentium FPU Normalizing + return(0); + + y = -a1 * input + zm1; + zm1 = y * a1 + input; + return(y); +} diff --git a/AZR3_vst2.4/FX/fxAllpass.h b/AZR3_vst2.4/FX/fxAllpass.h new file mode 100644 index 0000000..2753585 --- /dev/null +++ b/AZR3_vst2.4/FX/fxAllpass.h @@ -0,0 +1,13 @@ +#pragma once +#include "fxGlobals.h" + +class fxAllpass +{ +public: + fxAllpass(); + void reset(); + void set_delay(float fxDelay); + float clock(float input); +private: + float a1, zm1, my_delay, y; +}; diff --git a/AZR3_vst2.4/FX/fxDelay.cpp b/AZR3_vst2.4/FX/fxDelay.cpp new file mode 100644 index 0000000..c5b35f1 --- /dev/null +++ b/AZR3_vst2.4/FX/fxDelay.cpp @@ -0,0 +1,96 @@ +#include "fxDelay.h" + +fxDelay::fxDelay(int buflen, bool interpolate) + : alpha(0), alpha2(0), alpha3(0), offset(0), outPointer(0), + writep(p_buflen / 2), samplerate(44100), p_buflen(buflen), interp(interpolate), + readp(0) +{ + float x = 0; + int y; + buffer = new float[p_buflen]; + for (y = 0; y < p_buflen; y++) + buffer[y] = 0; +}; + +void fxDelay::set_delay(float dtime) +{ + offset = dtime * samplerate * .001f; + + if (offset < 0.1f) + offset = 0.1f; + else if (offset >= p_buflen) + offset = (float)p_buflen - 1; + + outPointer = writep - offset; + if (outPointer < 0) + outPointer += p_buflen; + + readp = (int)outPointer; + alpha = outPointer - readp; + alpha2 = alpha * alpha; + alpha3 = alpha2 * alpha; +}; + +void fxDelay::set_samplerate(float sr) +{ + set_delay(1000 * offset / samplerate); + samplerate = sr; +} + +void fxDelay::flood(float value) +{ + int x; + for (x = 0; x < p_buflen; x++) + buffer[x] = value; +} + +fxDelay::~fxDelay() +{ + delete[] buffer; +} + +float fxDelay::clock(float input) +{ + float output = 0, y0, y1, y2, ym1; + int ym1p, y1p, y2p; + if (p_buflen > 4410) + { + return(0); + } + + buffer[writep] = input; + + if (interp) + { + ym1p = readp - 1; + if (ym1p < 0) + ym1p += p_buflen; + y1p = readp + 1; + if (y1p >= p_buflen) + y1p -= p_buflen; + y2p = readp + 2; + if (y2p >= p_buflen) + y2p -= p_buflen; + + + ym1 = buffer[ym1p]; + y0 = buffer[readp]; + y1 = buffer[y1p]; + y2 = buffer[y2p]; + + output = (alpha3 * (y0 - y1 + y2 - ym1) + + alpha2 * (-2 * y0 + y1 - y2 + 2 * ym1) + + alpha * (y1 - ym1) + y0); + } + else + output = buffer[readp]; + + writep++; + if (writep >= p_buflen) + writep -= p_buflen; + readp++; + if (readp >= p_buflen) + readp -= p_buflen; + + return(output); +}; diff --git a/AZR3_vst2.4/FX/fxDelay.h b/AZR3_vst2.4/FX/fxDelay.h new file mode 100644 index 0000000..b79f702 --- /dev/null +++ b/AZR3_vst2.4/FX/fxDelay.h @@ -0,0 +1,23 @@ +#pragma once +#include "fxGlobals.h" + +class fxDelay +{ +public: + fxDelay(int buflen, bool interpolate); + ~fxDelay(); + void set_delay(float dtime); + void set_samplerate(float samplerate); + void flood(float value); + float clock(float input); +protected: + float* buffer; + int p_buflen; + bool interp; + float offset; + float samplerate; + int readp, writep; + + float outPointer; + float alpha, alpha2, alpha3; +}; diff --git a/AZR3_vst2.4/FX/fxGenericFilter.cpp b/AZR3_vst2.4/FX/fxGenericFilter.cpp new file mode 100644 index 0000000..4cca442 --- /dev/null +++ b/AZR3_vst2.4/FX/fxGenericFilter.cpp @@ -0,0 +1,48 @@ +#include "fxGenericFilter.h" + +fxGenericFilter::fxGenericFilter() +{ + m_l = m_h = m_b = m_f = q = 0; +} + +void fxGenericFilter::clock(float input) +{ + float in; + in = DENORMALIZE(input); + m_l = DENORMALIZE(m_l); + m_b = DENORMALIZE(m_b); + + m_h = in - m_l - q * m_b; + m_b += m_f * m_h; + m_l += m_f * m_b; +} + +float fxGenericFilter::lp() +{ + return(m_l); +} + +float fxGenericFilter::bp() +{ + return(m_b); +} + +float fxGenericFilter::hp() +{ + return(m_h); +} + +void fxGenericFilter::set_samplerate(float samplerate) +{ + fs = samplerate; + m_l = m_h = m_b = 0; + setparam(fc, q, fs); +} + +void fxGenericFilter::setparam(float cutoff, float mq, float samplerate) +{ + fc = cutoff; + q = mq; + fs = samplerate; + m_f = 2.0f * sinf(PI * fc / fs); +} diff --git a/AZR3_vst2.4/FX/fxGenericFilter.h b/AZR3_vst2.4/FX/fxGenericFilter.h new file mode 100644 index 0000000..205383b --- /dev/null +++ b/AZR3_vst2.4/FX/fxGenericFilter.h @@ -0,0 +1,24 @@ +#pragma once +#include "fxGlobals.h" + +class fxGenericFilter +{ + friend class fxGenericLowpass; +public: + fxGenericFilter(); + ~fxGenericFilter() {}; + float lp(); + float bp(); + float hp(); + void clock(float input); + void setparam(float cutoff, float q, float samplerate); + void set_samplerate(float samplerate); +private: + float fs; // sampling freq + float fc; // cutoff freq + float q; // resonance + float m_f, m_q, m_qnrm; + float m_h; // hp out + float m_b; // bp out + float m_l; // lp out +}; diff --git a/AZR3_vst2.4/FX/fxGenericLowpass.cpp b/AZR3_vst2.4/FX/fxGenericLowpass.cpp new file mode 100644 index 0000000..4b2476c --- /dev/null +++ b/AZR3_vst2.4/FX/fxGenericLowpass.cpp @@ -0,0 +1,19 @@ +#include "fxGenericLowpass.h" + +fxGenericLowpass::fxGenericLowpass() : fxGenericFilter() +{ +} + +float fxGenericLowpass::clock(float input) +{ + float in; + in = DENORMALIZE(input); + m_l = DENORMALIZE(m_l); + m_b = DENORMALIZE(m_b); + + m_h = in - m_l - q * m_b; + m_b += m_f * m_h; + m_l += m_f * m_b; + + return(m_l); +} diff --git a/AZR3_vst2.4/FX/fxGenericLowpass.h b/AZR3_vst2.4/FX/fxGenericLowpass.h new file mode 100644 index 0000000..a7a43dd --- /dev/null +++ b/AZR3_vst2.4/FX/fxGenericLowpass.h @@ -0,0 +1,10 @@ +#pragma once +#include "fxGlobals.h" +#include "fxGenericFilter.h" + +class fxGenericLowpass : public fxGenericFilter +{ +public: + fxGenericLowpass(); + float clock(float input); +}; diff --git a/AZR3_vst2.4/FX/fxGlobals.h b/AZR3_vst2.4/FX/fxGlobals.h new file mode 100644 index 0000000..8d147fe --- /dev/null +++ b/AZR3_vst2.4/FX/fxGlobals.h @@ -0,0 +1,6 @@ +#pragma once + +#define DENORMALIZE(fv) (fv<.00000001f && fv>-.00000001f)?0:(fv) +#define PI 3.14159265358979323846f + +#include diff --git a/AZR3_vst2.4/FX/fxLFO.cpp b/AZR3_vst2.4/FX/fxLFO.cpp new file mode 100644 index 0000000..afebbe3 --- /dev/null +++ b/AZR3_vst2.4/FX/fxLFO.cpp @@ -0,0 +1,73 @@ +#include "fxLFO.h" + +fxLFO::fxLFO() +{ + output = 0; + inc = 0; + dir = 1; + c = 1; + s = 0; +} + +void fxLFO::set_samplerate(float sr) +{ + samplerate = sr; +} + +void fxLFO::set_rate(float srate, int type) +{ + my_srate = srate; + my_type = type; + if (type == 0) + inc = 2.0f * PI * srate / samplerate; + else + inc = 2 * srate / samplerate; + ci = cosf(inc); + si = sinf(inc); +} + +float fxLFO::get_rate() +{ + return(my_srate); +} + +void fxLFO::set_phase(float phase) +{ + if (phase >= 0 && phase <= 1) + { + output = phase; + s = phase; + } +} + +float fxLFO::clock() +{ + if (my_type == 1) // triangle wave + { + if (dir == 1) + output += inc; + else + output -= inc; + + if (output >= 1) + { + dir = -1; + output = 1; + } + else if (output <= 0) + { + dir = 1; + output = 0; + } + } + else if (my_type == 0) // sine wave + { + nc = DENORMALIZE(c * ci - s * si); + ns = DENORMALIZE(c * si + s * ci); + c = nc; + s = ns; + output = DENORMALIZE((s + 1) * .5f); + } + + return(output); +} diff --git a/AZR3_vst2.4/FX/fxLFO.h b/AZR3_vst2.4/FX/fxLFO.h new file mode 100644 index 0000000..cb770e9 --- /dev/null +++ b/AZR3_vst2.4/FX/fxLFO.h @@ -0,0 +1,22 @@ +#pragma once +#include "fxGlobals.h" + +class fxLFO +{ +public: + fxLFO(); + ~fxLFO() {}; + float clock(); + void set_samplerate(float samplerate); + void set_rate(float srate, int type); // Hz; type: 0=sin, 1=tri + void set_phase(float phase); + float get_rate(); +private: + int my_type; + float output; + float samplerate; + float inc; + int dir; + float c, s, ci, si, nc, ns; + float my_srate; +}; diff --git a/AZR3_vst2.4/Globals.h b/AZR3_vst2.4/Globals.h new file mode 100644 index 0000000..dd3f718 --- /dev/null +++ b/AZR3_vst2.4/Globals.h @@ -0,0 +1,233 @@ +#pragma once +#define VERSION "2.0" + +// #define DELAYED_PARAMS 1 + +#define WAVETABLESIZE 256 + +const float Pi = 3.14159265358979323846; + +#define NUMOFVOICES 11 + +#define _fabsf(fv) fabsf(fv) + +/* + ID and Effect name are used by the host application to distinguish + between plugins. You can register a specific ID through a Steinberg + service. +*/ +#define MY_ID 'FLP5' +#define EFFECT_NAME "AZR3" +#define VENDOR_STRING "Rumpelrausch Täips" +#define PRODUCT_STRING "AZR3" + +#define EVTBUFSIZE 1024 // number of events to memorize in buffer + +enum +{ + TONEWHEEL_SHAPE_SINE=0, + TONEWHEEL_SHAPE_SINE1, + TONEWHEEL_SHAPE_SINE2, + TONEWHEEL_SHAPE_SINE3, + TONEWHEEL_SHAPE_TRI, + TONEWHEEL_SHAPE_SAW, + NUM_OF_TONEWHEEL_SHAPES +}; + +enum // bitmap indices +{ + b_panelfx=0, + b_panelvoice, + b_cknob, + b_dbblack, + b_dbwhite, + b_dbbrown, + b_inside, + b_miniledred, + b_minioffon, + b_onoffgreen, + b_vonoff, + b_yellow, + b_vu, + kNumBitmaps, +}; + +enum +{ + kNumPrograms = 32, + kNumOutputs = 2, +// The parameters +// The order shows how the code has grown in time... + n_mono=0, + n_click, + n_bender, + n_shape, + n_perc, + n_percvol, + n_percfade, + n_vol1, + n_vol2, + n_vol3, + n_master, +//11 + n_1_perc, + n_1_db1, + n_1_db2, + n_1_db3, + n_1_db4, + n_1_db5, + n_1_db6, + n_1_db7, + n_1_db8, + n_1_db9, +//21 + n_1_vibrato, + n_1_vstrength, + n_1_vmix, + n_2_perc, + n_2_db1, + n_2_db2, + n_2_db3, + n_2_db4, + n_2_db5, + n_2_db6, +//31 + n_2_db7, + n_2_db8, + n_2_db9, + n_2_vibrato, + n_2_vstrength, + n_2_vmix, + n_3_perc, + n_3_db1, + n_3_db2, + n_3_db3, +//41 + n_3_db4, + n_3_db5, + n_mrvalve, + n_drive, + n_set, + n_tone, + n_mix, + n_speakers, + n_speed, + n_l_slow, +//51 + n_l_fast, + n_u_slow, + n_u_fast, + n_belt, + n_spread, + n_complex, + n_pedalspeed, + n_splitpoint, + n_sustain, + n_1_sustain, +// 61 + n_2_sustain, + n_3_sustain, + + n_spare_1, + n_spare_2, + n_spare_3, + + kNumParams, + + n_1_midi, + n_2_midi, + n_3_midi, + n_vu, + n_compare, + n_save, + n_display, + n_redraw, + n_setprogname, + n_param_is_manual, + n_splash, + n_voicemode, + n_fxmode, + n_split, + n_output, + + kNumControls, + + n_mute, + n_mousedown +}; + +// Let's be friendly and do at least some GUI-less support... +static char labels[kNumParams][32]= +{ + "Mono ", + "Click ", + "Bender ", + "Shape ", + "Percussion register", + "Percussion volume", + "Percussion fadetime", + "Volume 1", + "Volume 2", + "Volume 3", + "Volume Master", + + "1/ Percussion on", + "1/ 16 ", + "1/ 5 1/3", + "1/ 8 ", + "1/ 4 ", + "1/ 2 2/3", + "1/ 2 ", + "1/ 1 3/5", + "1/ 1 1/3", + "1/ 1 ", + + "1/ Vibrato", + "1/ Vibrato Strength", + "1/ Vibrato Mix", + "2/ Percussion on", + "2/ 16 ", + "2/ 5 1/3", + "2/ 8 ", + "2/ 4 ", + "2/ 2 2/3", + "2/ 2 ", + + "2/ 1 3/5", + "2/ 1 1/3", + "2/ 1 ", + "2/ Vibrato", + "2/ Vibrato Strength", + "2/ Vibrato Mix", + "3/ Percussion on", + "3/ 16 ", + "3/ 5 1/3", + "3/ 8 ", + + "3/ 4 ", + "3/ 2 2/3", + "Mr. Valve on", + "Drive ", + "Set ", + "Tone ", + "Mix ", + "Speakers on", + "Speed ", + "Speed lower/slow", + + "Speed lower/fast", + "Speed upper/slow", + "Speed upper/fast", + "Belt friction", + "Microhpone spread", + "Complex on", + "Pedal speed on", + "Splitpoint", + "Sustain time", + "Sustain 1 on", + "Sustain 2 on", + "Sustain 3 on", + "spare 1", + "spare 2", + "spare 3" +}; diff --git a/AZR3_vst2.4/Quelle.cpp b/AZR3_vst2.4/Quelle.cpp new file mode 100644 index 0000000..e69de29 diff --git a/AZR3_vst2.4/Resources/cknob.bmp b/AZR3_vst2.4/Resources/cknob.bmp new file mode 100644 index 0000000..8264ddf Binary files /dev/null and b/AZR3_vst2.4/Resources/cknob.bmp differ diff --git a/AZR3_vst2.4/Resources/dbblack.bmp b/AZR3_vst2.4/Resources/dbblack.bmp new file mode 100644 index 0000000..ca09de6 Binary files /dev/null and b/AZR3_vst2.4/Resources/dbblack.bmp differ diff --git a/AZR3_vst2.4/Resources/dbbrown.bmp b/AZR3_vst2.4/Resources/dbbrown.bmp new file mode 100644 index 0000000..1f4ce16 Binary files /dev/null and b/AZR3_vst2.4/Resources/dbbrown.bmp differ diff --git a/AZR3_vst2.4/Resources/dbwhite.bmp b/AZR3_vst2.4/Resources/dbwhite.bmp new file mode 100644 index 0000000..8e5b0e3 Binary files /dev/null and b/AZR3_vst2.4/Resources/dbwhite.bmp differ diff --git a/AZR3_vst2.4/Resources/inside.bmp b/AZR3_vst2.4/Resources/inside.bmp new file mode 100644 index 0000000..45442a7 Binary files /dev/null and b/AZR3_vst2.4/Resources/inside.bmp differ diff --git a/AZR3_vst2.4/Resources/make a change.bmp b/AZR3_vst2.4/Resources/make a change.bmp new file mode 100644 index 0000000..d8662b5 Binary files /dev/null and b/AZR3_vst2.4/Resources/make a change.bmp differ diff --git a/AZR3_vst2.4/Resources/material-bg-knopf1.bmp b/AZR3_vst2.4/Resources/material-bg-knopf1.bmp new file mode 100644 index 0000000..0dffc89 Binary files /dev/null and b/AZR3_vst2.4/Resources/material-bg-knopf1.bmp differ diff --git a/AZR3_vst2.4/Resources/miniledred.bmp b/AZR3_vst2.4/Resources/miniledred.bmp new file mode 100644 index 0000000..c1acc3d Binary files /dev/null and b/AZR3_vst2.4/Resources/miniledred.bmp differ diff --git a/AZR3_vst2.4/Resources/minioffon.bmp b/AZR3_vst2.4/Resources/minioffon.bmp new file mode 100644 index 0000000..d22608c Binary files /dev/null and b/AZR3_vst2.4/Resources/minioffon.bmp differ diff --git a/AZR3_vst2.4/Resources/num_yellow.bmp b/AZR3_vst2.4/Resources/num_yellow.bmp new file mode 100644 index 0000000..f9d78ca Binary files /dev/null and b/AZR3_vst2.4/Resources/num_yellow.bmp differ diff --git a/AZR3_vst2.4/Resources/onoffgreen.bmp b/AZR3_vst2.4/Resources/onoffgreen.bmp new file mode 100644 index 0000000..bd1f998 Binary files /dev/null and b/AZR3_vst2.4/Resources/onoffgreen.bmp differ diff --git a/AZR3_vst2.4/Resources/panel-both.bmp b/AZR3_vst2.4/Resources/panel-both.bmp new file mode 100644 index 0000000..9d72c75 Binary files /dev/null and b/AZR3_vst2.4/Resources/panel-both.bmp differ diff --git a/AZR3_vst2.4/Resources/panelfx.bmp b/AZR3_vst2.4/Resources/panelfx.bmp new file mode 100644 index 0000000..d73a3fa Binary files /dev/null and b/AZR3_vst2.4/Resources/panelfx.bmp differ diff --git a/AZR3_vst2.4/Resources/panelvoice.bmp b/AZR3_vst2.4/Resources/panelvoice.bmp new file mode 100644 index 0000000..83a2337 Binary files /dev/null and b/AZR3_vst2.4/Resources/panelvoice.bmp differ diff --git a/AZR3_vst2.4/Resources/vonoff.bmp b/AZR3_vst2.4/Resources/vonoff.bmp new file mode 100644 index 0000000..bedc82c Binary files /dev/null and b/AZR3_vst2.4/Resources/vonoff.bmp differ diff --git a/AZR3_vst2.4/effectAudioProcessing.h b/AZR3_vst2.4/effectAudioProcessing.h new file mode 100644 index 0000000..f932cba --- /dev/null +++ b/AZR3_vst2.4/effectAudioProcessing.h @@ -0,0 +1,13 @@ +#ifndef __effectAudioProcessing_h__ +#define __effectAudioProcessing_h__ + +#include "effectMain.h" + +class effectAudioProcessing : + public effectMain +{ + void process(float** inputs, float** outputs, long sampleFrames); + void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames); +}; + +#endif diff --git a/AZR3_vst2.4/effectMain.cpp b/AZR3_vst2.4/effectMain.cpp new file mode 100644 index 0000000..5534494 --- /dev/null +++ b/AZR3_vst2.4/effectMain.cpp @@ -0,0 +1,206 @@ +#include "effectMain.h" +#include "effectAudioProcessing.h" + +// TODO: put into class +//extern void convert_bendrange(float value, char* string); +//extern void convert_tone(float value, char* string); +//extern void convert_speed(float value, char* string); +//extern void convert_perc(float value, char* string); +//extern void convert_shape(float value, char* string); + +AudioEffect* createEffectInstance(audioMasterCallback audioMaster) +{ + return new effectMain(audioMaster); +} + +effectMain::effectMain(audioMasterCallback audioMaster) : AudioEffectX(audioMaster, kNumPrograms, kNumParams) +{ + fullyloaded = false; + mute = true; + + if (audioMaster) + { + setNumInputs(2); + setNumOutputs(kNumOutputs); + canDoubleReplacing(false); + canProcessReplacing(true); + isSynth(true); + this-> + noTail(false); + setUniqueID(MY_ID); + } + + initall(); + + n1 = new noteController(NUMOFVOICES); + vdelay1 = new fxDelay(441, true); + vdelay2 = new fxDelay(441, true); + wand_r = new fxDelay(4410, false); + wand_l = new fxDelay(4410, false); + delay1 = new fxDelay(4410, true); + delay2 = new fxDelay(4410, true); + delay3 = new fxDelay(4410, true); + delay4 = new fxDelay(4410, true); + + my_p = virtual_my_p = programs[0].p; + setProgramDelayCount = 0; + setSampleRate((float)updateSampleRate()); + setFactorySounds(); + actual_curProgram = -1; + setProgram(0, true); + + buildTonewheelSet(TONEWHEEL_SHAPE_SINE); + + editor = NULL; + editor = new Editor(this); + + suspend(); + param_is_manual = true; +} + +effectMain::~effectMain() +{ + if (n1 != NULL) + n1->~noteController(); + n1 = NULL; + if (wand_r != NULL) + wand_r->~fxDelay(); + wand_r = NULL; + if (wand_l != NULL) + wand_l->~fxDelay(); + wand_l = NULL; + if (vdelay1 != NULL) + vdelay1->~fxDelay(); + vdelay1 = NULL; + if (vdelay2 != NULL) + vdelay2->~fxDelay(); + vdelay2 = NULL; + if (delay1 != NULL) + delay1->~fxDelay(); + delay1 = NULL; + if (delay2 != NULL) + delay2->~fxDelay(); + delay2 = NULL; + if (delay3 != NULL) + delay3->~fxDelay(); + delay3 = NULL; + if (delay4 != NULL) + delay4->~fxDelay(); + delay4 = NULL; + if (editor != NULL) + editor->~AEffEditor(); + editor = NULL; +} + +/* +// Don't set variable parameters here: +// The function might get called after program select +// so the program values would get overriden. +*/ +void effectMain::setSampleRate(float sampleRate) +{ + AudioEffectX::setSampleRate(sampleRate); + samplerate = sampleRate; + + warmth.setparam(2700, 1.2f, sampleRate); + + if (n1 != NULL) + n1->set_samplerate(samplerate); + if (vdelay1 != NULL) + vdelay1->set_samplerate(samplerate); + if (vdelay2 != NULL) + vdelay2->set_samplerate(samplerate); + vlfo.set_samplerate(samplerate); + vlfo.set_rate(35, 0); + split.setparam(400, 1.3f, samplerate); + horn_filt.setparam(2500, .5f, samplerate); + //horn_filt.setparam(4500, 0.02f, samplerate); + damp.setparam(200, .9f, samplerate); + //damp.setparam(3500, 1.5f, samplerate); + if (wand_r != NULL) + { + wand_r->set_samplerate(samplerate); + wand_r->set_delay(35); + } + if (wand_r != NULL) + { + wand_l->set_samplerate(samplerate); + wand_l->set_delay(20); + } + if (delay1 != NULL) + delay1->set_samplerate(samplerate); + if (delay2 != NULL) + delay2->set_samplerate(samplerate); + if (delay3 != NULL) + delay3->set_samplerate(samplerate); + if (delay4 != NULL) + delay4->set_samplerate(samplerate); + lfo1.set_samplerate(samplerate); + lfo2.set_samplerate(samplerate); + lfo3.set_samplerate(samplerate); + lfo4.set_samplerate(samplerate); + + body_filt.setparam(190, 1.5f, samplerate); + postbody_filt.setparam(1100, 1.5f, samplerate); +} + +bool effectMain::getOutputProperties(VstInt32 index, VstPinProperties* properties) +{ + if (index < kNumOutputs) + { + /* + We could add "L" and "R" for the channels, but this + is not recognized by all hosts. This is the most compatible + solution. + */ + sprintf(properties->label, "AZR3"); + sprintf(properties->shortLabel, "AZR3"); + properties->flags = kVstPinIsActive; + if (index < 2) + properties->flags |= kVstPinIsStereo; + return true; + } + return false; +} + +//bool effectMain::getInputProperties(VstInt32 index, VstPinProperties* properties) +//{ +// if (index < 2) +// { +// properties->flags = kVstPinIsActive | kVstPinIsStereo; +// sprintf(properties->label, "AZR3 Input"); +// sprintf(properties->shortLabel, "AZR3 IN"); +// } +// return true; +//} + +bool effectMain::getEffectName(char* name) +{ + strcpy(name, EFFECT_NAME); + return true; +} + +bool effectMain::getVendorString(char* text) +{ + strcpy(text, VENDOR_STRING); + return true; +} + +bool effectMain::getProductString(char* text) +{ + strcpy(text, PRODUCT_STRING); + return true; +} + +VstInt32 effectMain::canDo(char* text) +{ + if (!strcmp(text, "receiveVstEvents")) + return 1; + else if (!strcmp(text, "receiveVstMidiEvent")) + return 1; + else if (!strcmp(text, "sendVstMidiEvent")) + return 1; + else + return -1; +} + diff --git a/AZR3_vst2.4/effectMain.h b/AZR3_vst2.4/effectMain.h new file mode 100644 index 0000000..6fe82e7 --- /dev/null +++ b/AZR3_vst2.4/effectMain.h @@ -0,0 +1,222 @@ +#pragma once +#include "audioeffectx.h" + +#include +#include +#include + +#include "noteController.h" +#include "Globals.h" +#include "Editor.h" +#include "FX/fxDelay.h" +#include "FX/fxLFO.h" +#include "FX/fxGenericFilter.h" +#include "FX/fxGenericLowpass.h" +#include "FX/fxAllpass.h" +#include "vstProgram.h" + +enum +{ + evt_none = 0, + evt_noteon, + evt_noteoff, + evt_alloff, + evt_pedal, + evt_progchange, + evt_pitch, + evt_modulation, + evt_volume, + evt_channel_volume, + evt_drawbar, +}; + +class effectMain : public AudioEffectX +{ + friend class MoogProgram; +public: + effectMain(audioMasterCallback audioMaster); + ~effectMain(); + + void process(float** inputs, float** outputs, long sampleframes); + void processReplacing(float** inputs, float** outputs, VstInt32 sampleframes); + VstInt32 processEvents(VstEvents* events); + + void setProgram(VstInt32 program, bool force); + bool copyProgram(VstInt32 destination); + void setInternalParameter(VstInt32 index, float value); + + //---from AudioEffect----------------------- + virtual void setProgram(VstInt32 program); + virtual void setProgramName(char* name); + virtual void getProgramName(char* name); + virtual VstInt32 getProgram(); + virtual void setParameter(VstInt32 index, float value); + virtual float getParameter(VstInt32 index); + virtual void getParameterLabel(VstInt32 index, char* label); + virtual void getParameterDisplay(VstInt32 index, char* text); + virtual void getParameterName(VstInt32 index, char* text); + virtual void setSampleRate(float sampleRate); + virtual void resume(); + virtual void suspend(); + + virtual bool getOutputProperties(VstInt32 index, VstPinProperties* properties); + //virtual bool getInputProperties(VstInt32 index, VstPinProperties* properties); + virtual bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text); + virtual bool getEffectName(char* name); + virtual bool getVendorString(char* text); + virtual bool getProductString(char* text); + virtual VstInt32 getVendorVersion() { return 1; } + virtual VstInt32 canDo(char* text); + virtual VstPlugCategory getPlugCategory() { return kPlugCategSynth; } + + void setFactorySounds(); + bool buildTonewheelSet(int shape); + void rebuildWavetableSet(int number); + void rebuildClickWavetable(); + void initall() + { + int x; + mono_before = 0; + samplecount = 0; + mono = mono1 = mono2 = l_before = r_before = 0; + + viblfo = 0; + vmix1 = vmix2 = 0; + + dist = fuzz = odmix = 0; + spread = spread2 = cross1 = 0; + lslow = lfast = uslow = ufast = ubelt_up = ubelt_down = lbelt_up = lbelt_down = lspeed = uspeed = 0; + er_r = er_l = 0; + lp = right = left = lright = lleft = upper = lower = 0; + llfo_out = llfo_nout = llfo_d_out = llfo_d_nout = 0; + lfo_out = lfo_nout = lfo_d_out = lfo_d_nout = 0; + last_out1 = last_out2 = 0; + + VCA = 1; + compare = false; + waitforsplit = false; + splitpoint = 0; + + gp_value = 0; + last_shape = -1; + + odmix = 0; + vmix1 = 0; + vmix2 = 0; + + for (x = 0; x < WAVETABLESIZE * 12 + 1; x++) + wavetable[x] = 0; + + for (x = 0; x < kNumParams; x++) + last_value[x] = -99; + + for (x = 0; x < EVTBUFSIZE; x++) + { + this->delta[x] = -10; + this->events[x] = evt_none; + } + event_pos = event_read_pos = 0; + has_events = false; + + if (samplerate < 8000) + samplerate = 44100; + +#ifdef DEVELOP + ctrl1 = .5f; + ctrl2 = .51f; + ctrl3 = .44f; + ctrl4 = 0; +#endif + + } + void add_event(unsigned char type, long delta, float value1, float value2, float value3); + float* event_clock(); + +protected: + noteController* n1; + bool mute, fullyloaded; + float click[16]; + float volume[16]; + float mono_before; + float* out1, * out2, * in1, * in2; + bool compare, comparebuffer; + float samplerate; + long samplecount; + bool param_is_manual; + bool waitforsplit; + long splitpoint; + + float p[kNumParams], * my_p, * virtual_my_p, actual_p[kNumParams], i_p[kNumParams]; + float last_value[kNumParams]; + float* p_mono, mono, mono1, mono2, VCA, l_before, r_before; + long setProgramDelayCount, actual_curProgram; + + vstProgram programs[kNumPrograms]; + + float tonewheel[WAVETABLESIZE]; // master waveform + + float sin_16[WAVETABLESIZE]; + float sin_8[WAVETABLESIZE]; + float sin_513[WAVETABLESIZE]; + float sin_4[WAVETABLESIZE]; + float sin_223[WAVETABLESIZE]; + float sin_2[WAVETABLESIZE]; + float sin_135[WAVETABLESIZE]; + float sin_113[WAVETABLESIZE]; + float sin_1[WAVETABLESIZE]; + + // TABLES_PER_CHANNEL tables per channel; 3 channels; 1 spare table +#define TABLES_PER_CHANNEL 8 + float wavetable[WAVETABLESIZE * TABLES_PER_CHANNEL * 3 + 1]; + + fxLFO vlfo; + fxDelay* vdelay1, * vdelay2; + float viblfo; + bool vibchanged1, vibchanged2, lfo_calced; + float vmix1, vmix2; + fxGenericLowpass warmth; + + fxGenericFilter fuzz_filt, body_filt, postbody_filt; + float dist, sin_dist, i_dist, dist4, dist8; + float fuzz; + bool do_dist; + bool odchanged; + float odmix, n_odmix, n2_odmix, n25_odmix, odmix75; + + float spread, spread2; + float cross1; + bool fastmode; + float lslow, lfast, uslow, ufast, lspeed, uspeed; + float ubelt_up, ubelt_down, lbelt_up, lbelt_down; + float er_r, er_r_before, er_l, er_feedback; + float lp, right, left, lright, lleft, upper, lower, upper_damp; + float llfo_out, llfo_nout, llfo_d_out, llfo_d_nout; + float lfo_out, lfo_nout, lfo_d_out, lfo_d_nout; + float last_out1, last_out2; + bool lfos_ok; + fxGenericFilter split; + fxGenericFilter horn_filt, damp; + fxDelay* wand_r, * wand_l, * delay1, * delay2, * delay3, * delay4; + fxLFO lfo1, lfo2, lfo3, lfo4; + + float gp_value; + int last_shape; + float last_r, last_l; + float* evt; + // stuff for event handling + float values[4], * ret; + bool has_events; + int event_pos, event_last_pos, event_next_pos, event_read_pos; + long delta[EVTBUFSIZE]; + unsigned char events[EVTBUFSIZE]; + float evalue1[EVTBUFSIZE]; + float evalue2[EVTBUFSIZE]; + float evalue3[EVTBUFSIZE]; + fxAllpass allpass_l[4], allpass_r[4]; + float lfo_phaser1, lfo_phaser2; + +#ifdef DEVELOP + float ctrl1, ctrl2, ctrl3, ctrl4; +#endif + +}; diff --git a/AZR3_vst2.4/effectMainAudioProcessing.cpp b/AZR3_vst2.4/effectMainAudioProcessing.cpp new file mode 100644 index 0000000..04f7fb0 --- /dev/null +++ b/AZR3_vst2.4/effectMainAudioProcessing.cpp @@ -0,0 +1,580 @@ +#include "effectMain.h" + +//void effectMain::process(float** inputs, float** outputs, long sampleFrames) +//{ +// // Do this hack only for VST instruments!!! +// processReplacing(inputs, outputs, sampleFrames); +//} + +void effectMain::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames) +{ + /* + OK, here we go. This is the order of actions in here: + - process event queue + - return zeroes if in "mute" state + - clock the "noteController" and get the combined sound output + from the voices. + We actually get three values, one for each keyboard. + They are added according to the assigned channel volume + control values. + - calculate switch smoothing to prevent clicks + - vibrato + - additional low pass "warmth" + - distortion + - speakers + */ + out1 = outputs[0]; + out2 = outputs[1]; + in1 = inputs[0]; + in2 = inputs[1]; + int x; + + while (--sampleFrames >= 0) + { +#ifdef DELAYED_PARAMS + if (setProgramDelayCount > 0) + { + setProgramDelayCount++; + // here we confirm a requested program change + if (setProgramDelayCount > 4096) + { + setProgramDelayCount = -1; + setProgram(curProgram); + } + } +#endif + // we need this variable further down + samplecount++; + if (fullyloaded) + { + if (samplecount > 10000) + samplecount = 0; + } + else + { + // This is one of the two methods to finally activate everything. + // We need some time in advance in order to fill all buffers with correct data. + // The other method is located at setParameter and responds to the editor + // event "n_mute". + if (samplecount > ((long)(samplerate * 1.5f))) + { + samplecount = 0; + if (fullyloaded == false) + { + fullyloaded = true; + resume(); + } + } + } + + // read events from our own event queue + while ((evt = this->event_clock()) != NULL) + { + int channel = (int)evt[3]; + float* tbl; + + // flash channel LEDs + if (channel <= 0) + setParameter(n_1_midi, 1); + if (channel == 1 || channel < 0) + setParameter(n_2_midi, 1); + if (channel == 2 || channel < 0) + setParameter(n_3_midi, 1); + + if (channel < 0 || channel>2) + channel = 0; + switch ((unsigned char)evt[0]) + { + case evt_noteon: + { + int note = (int)evt[1]; + bool percenable = false; + float sustain = my_p[n_sustain] + .0001f; + + // here we choose the correct wavetable according to the played note +#define foldstart 80 + if (note > foldstart + 12 + 12) + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL + WAVETABLESIZE * 7]; + else if (note > foldstart + 12 + 8) + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL + WAVETABLESIZE * 6]; + else if (note > foldstart + 12 + 5) + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL + WAVETABLESIZE * 5]; + else if (note > foldstart + 12) + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL + WAVETABLESIZE * 4]; + else if (note > foldstart + 8) + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL + WAVETABLESIZE * 3]; + else if (note > foldstart + 5) + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL + WAVETABLESIZE * 2]; + else if (note > foldstart) + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL + WAVETABLESIZE]; + else + tbl = &wavetable[channel * WAVETABLESIZE * TABLES_PER_CHANNEL]; + + if (channel == 0) + { + if (my_p[n_1_perc] > 0) + percenable = true; + if (my_p[n_1_sustain] < .5f) + sustain = 0; + } + else if (channel == 1) + { + if (my_p[n_2_perc] > 0) + percenable = true; + if (my_p[n_2_sustain] < .5f) + sustain = 0; + } + else if (channel == 2) + { + if (my_p[n_3_perc] > 0) + percenable = true; + if (my_p[n_3_sustain] < .5f) + sustain = 0; + } + + n1->note_on(note, + (long)this->evt[2], + tbl, WAVETABLESIZE, channel, percenable, click[channel], sustain); + } + break; + case evt_noteoff: + n1->note_off((long)evt[1], channel); + break; + case evt_alloff: + n1->all_notes_off(); + break; + case evt_pedal: + n1->set_pedal((int)evt[1], channel); + break; + case evt_progchange: + if (evt[1] < kNumPrograms && evt[1] != curProgram) + { + param_is_manual = true; + setProgram((long)evt[1]); + } + break; + case evt_pitch: + n1->set_pitch(evt[1], channel); + break; + case evt_modulation: + param_is_manual = true; + setParameterAutomated(n_speed, evt[1]); + param_is_manual = false; + break; + case evt_volume: + my_p[n_master] = evt[1]; + break; + case evt_channel_volume: + param_is_manual = true; + setParameterAutomated(n_vol1 + channel, evt[1] / 127.0f); + param_is_manual = false; + break; + case evt_drawbar: + if (channel == 2 && evt[1] > 4) + break; + if (evt[1] < 0 || evt[1]>8) + break; + if (evt[1] == 1) + evt[1] = 2; + else if (evt[1] == 2) + evt[1] = 1; + int offset = n_1_db1; + if (channel == 1) + offset = n_2_db1; + else if (channel == 2) + offset = n_3_db1; + param_is_manual = true; + setParameterAutomated(offset + (int)evt[1], evt[2] / 127.0f); + param_is_manual = false; + break; + } + } + + p_mono = n1->clock(); + mono1 = p_mono[0]; + mono1 += (*in1 + *in2) / 2; // mix in inputs + mono2 = p_mono[1]; + mono = p_mono[2]; + + // smoothing of vibrato switch 1 + if (vibchanged1 && samplecount % 10 == 0) + { + if (my_p[n_1_vibrato] == 1) + { + vmix1 += .01f; + if (vmix1 >= my_p[n_1_vmix]) + vibchanged1 = false; + } + else + { + vmix1 -= .01f; + if (vmix1 <= 0) + vibchanged1 = false; + } + } + + // smoothing of vibrato switch 2 + if (vibchanged2 && samplecount % 10 == 0) + { + if (my_p[n_2_vibrato] == 1) + { + vmix2 += .01f; + if (vmix2 >= my_p[n_2_vmix]) + vibchanged2 = false; + } + else + { + vmix2 -= .01f; + if (vmix2 <= 0) + vibchanged2 = false; + } + } + + // smoothing of OD switch + if (odchanged && samplecount % 10 == 0) + { + if (my_p[n_mrvalve] == 1) + { + odmix += .05f; + if (odmix >= my_p[n_mix]) + odchanged = false; + } + else + { + odmix -= .05f; + if (odmix <= 0) + odchanged = false; + } + n_odmix = 1 - odmix; + n2_odmix = 2 - odmix; + odmix75 = .75f * odmix; + n25_odmix = n_odmix * .25f; + } + + // Vibrato LFO + lfo_calced = false; + + // Vibrato 1 + if (my_p[n_1_vibrato] == 1 || vibchanged1) + { + if (samplecount % 5 == 0) + { + viblfo = vlfo.clock(); + lfo_calced = true; + vdelay1->set_delay(viblfo * 2 * my_p[n_1_vstrength]); + } + mono1 = (1 - vmix1) * mono1 + vmix1 * vdelay1->clock(mono1); + } + + // Vibrato 2 + if (my_p[n_2_vibrato] == 1 || vibchanged2) + { + if (samplecount % 5 == 0) + { + if (!lfo_calced) + viblfo = vlfo.clock(); + vdelay2->set_delay(viblfo * 2 * my_p[n_2_vstrength]); + } + mono2 = (1 - vmix2) * mono2 + vmix2 * vdelay2->clock(mono2); + } + + + // ...add a minimal offset to prevent denormalization. + // Don't know wether it's just superstition... + mono += mono1 + mono2 + .0001f; + + // Mr. Valve + /* + Completely rebuilt. + Multiband distortion: + The first atan() waveshaper is applied to a lower band. The second + one is applied to the whole spectrum as a clipping function (combined + with an fabs() branch). + The "warmth" filter is now applied _after_ distortion to flatten + down distortion overtones. It's only applied with activated distortion + effect, so we can switch warmth off and on without adding another parameter. + */ + if (my_p[n_mrvalve] == 1 || odchanged) + { + if (do_dist) + { + body_filt.clock(mono); + postbody_filt.clock(atanf(body_filt.lp() * dist8) * 6); + fuzz = atanf(mono * dist4) * .25f + postbody_filt.bp() + postbody_filt.hp(); + + if (_fabsf(mono) > my_p[n_set]) + { + fuzz = atanf(fuzz * 10); + } + fuzz_filt.clock(fuzz); + mono = ((fuzz_filt.lp() * odmix * sin_dist + mono * (n2_odmix)) * sin_dist) * i_dist; + } + else + { + fuzz_filt.clock(mono); + mono = fuzz_filt.lp() * odmix75 + mono * n25_odmix * i_dist; + } + warmth.clock(mono); + mono = DENORMALIZE(warmth.lp()); + } + + // Speakers + /* + I started the rotating speaker sim from scratch with just + a few sketches about how reality looks like: + Two horn speakers, rotating in a circle. Combined panning + between low and mid filtered sound and the volume. Add the + doppler effect. Let the sound of one speaker get reflected + by a wall and mixed with the other speakers' output. That's + all not too hard to calculate and to implement in C++, and + the results were already quite realistic. However, to get + more density and the explicit "muddy" touch I added some + phase shifting gags and some unexpected additions with + the other channels' data. The result did take many nights + of twiggling wih parameters. There are still some commented + alternatives; feel free to experiment with the emulation. + Never forget to mono check since there are so many phase + effects in here you might end up in the void. + I'm looking forward to the results... + */ + + /* + Update: + I added some phase shifting using allpass filters. + This should make it sound more realistic. + */ + + if (my_p[n_speakers] == 1) + { + if (samplecount % 100 == 0) + { + if (fastmode) + { + if (lspeed < lfast) + lspeed += lbelt_up; + if (lspeed > lfast) + lspeed = lfast; + + if (uspeed < ufast) + uspeed += ubelt_up; + if (uspeed > ufast) + uspeed = ufast; + } + else + { + if (lspeed > lslow) + lspeed -= lbelt_down; + if (lspeed < lslow) + lspeed = lslow; + if (uspeed > uslow) + uspeed -= ubelt_down; + if (uspeed < uslow) + uspeed = uslow; + } + + //recalculate mic positions when "spread" has changed + if (!lfos_ok) + { + float s = (my_p[n_spread] + .5f) * .8f; + spread = (s) * 2 + 1; + spread2 = (1 - spread) / 2; + lfo1.set_phase(0); + lfo2.set_phase(s / 2); + lfo3.set_phase(0); + lfo4.set_phase(s / 2); + cross1 = 1.5f - 1.2f * s; + // early reflections depend upon mic position. + // we want less e/r if mics are positioned on + // opposite side of speakers. + // when positioned right in front of them e/r + // brings back some livelyness. + // + // so "spread" does the following to the mic positions: + // minimum: mics are almost at same position (mono) but + // further away from cabinet. + // maximum: mics are on opposite sides of cabinet and very + // close to speakers. + // medium: mics form a 90° angle, heading towards cabinet at + // medium distance. + er_feedback = .1f * cross1; + lfos_ok = true; + } + + if (lspeed != lfo3.get_rate()) + { + lfo3.set_rate(lspeed * 5, 1); + lfo4.set_rate(lspeed * 5, 1); + } + + if (uspeed != lfo1.get_rate()) + { + lfo1.set_rate(uspeed * 5, 1); + lfo2.set_rate(uspeed * 5, 1); + } + } + + // split signal into upper and lower cabinet speakers + split.clock(mono); + lower = split.lp() * 5; + upper = split.hp(); + + + // upper speaker is kind of a nasty horn + horn_filt.clock(upper); + damp.clock(upper); + upper = upper + horn_filt.lp() * 0.3; + upper_damp = damp.lp(); + + // do fxLFO stuff + if (samplecount % 5 == 0) + { + lfo_d_out = lfo1.clock(); + lfo_d_nout = 1 - lfo_d_out; + + delay1->set_delay(10 + lfo_d_out * .8f); + delay2->set_delay(17 + lfo_d_nout * .8f); + + lfo_d_nout = lfo2.clock(); + + lfo_out = lfo_d_out * spread + spread2; + lfo_nout = lfo_d_nout * spread + spread2; + + // phase shifting lines + // A light bulb and some LDRs... + lfo_phaser1 = (1 - cosf(lfo_d_out * 1.8f) + 1) * .054f; + lfo_phaser2 = (1 - cosf(lfo_d_nout * 1.8f) + 1) * .054f; + for (x = 0; x < 4; x++) + { + allpass_r[x].set_delay(lfo_phaser1); + allpass_l[x].set_delay(lfo_phaser2); + } + + if (lslow > 0) + { + llfo_d_out = lfo3.clock(); + llfo_d_nout = 1 - llfo_d_out; + } + + // additional fxDelay lines in complex mode + if (my_p[n_complex] > .5f) + { + delay4->set_delay(llfo_d_out + 15); + delay3->set_delay(llfo_d_nout + 25); + } + + llfo_d_nout = lfo4.clock(); + llfo_out = llfo_d_out * spread + spread2; + llfo_nout = llfo_d_nout * spread + spread2; + } + + if (lslow > 0) + { + lright = (1 + .6f * llfo_out) * lower; + lleft = (1 + .6f * llfo_nout) * lower; + } + else + { + lright = lleft = lower; + } + + // emulate horn characteristics + // (sound is dampened when listened from aside) + //right = DENORMALIZE((3 + lfo_nout * 2.5f) * upper + 1.5f * upper_damp); + //left = DENORMALIZE((3 + lfo_out * 2.5f) * upper + 1.5f * upper_damp); + //right = DENORMALIZE((3 + lfo_nout * 1.5f) * upper + 1.5f * upper_damp); + //left = DENORMALIZE((3 + lfo_out * 1.5f) * upper + 1.5f * upper_damp); + right = DENORMALIZE((3 + lfo_nout) * upper * 3.3f - upper_damp * 16.5f * (3 + lfo_out)); + left = -DENORMALIZE((3 + lfo_out) * upper * 3.3f - upper_damp * 16.5f * (3 + lfo_nout)); + + //phaser... + last_r = allpass_r[0].clock( + allpass_r[1].clock( + allpass_r[2].clock( + allpass_r[3].clock(upper + last_r * .33f)))); + last_l = allpass_l[0].clock( + allpass_l[1].clock( + allpass_l[2].clock( + allpass_l[3].clock(upper + last_l * .33f)))); + + right += last_r; + left += last_l; + + // rotating speakers can only develop in a live room - + // wouldn't work without some early reflections. + er_r = wand_r->clock(right + lright - (left * .3f) - er_l * er_feedback); + er_r = DENORMALIZE(er_r); + er_l = wand_l->clock(left + lleft - (right * .3f) - er_r_before * er_feedback); + er_l = DENORMALIZE(er_l); + er_r_before = er_r; + + + // We use two additional fxDelay lines in "complex" mode + if (my_p[n_complex] > .5f) + { + right = right * .3f + 1.5f * er_r + delay1->clock(right) + delay3->clock(er_r) + (1.5 * upper) + (1.5 * lower); + left = left * .3f + 1.5f * er_l + delay2->clock(left) + delay4->clock(er_l) + (1.5 * upper) + (1.5 * lower); + } + else + { + right = right * .3f + 1.5f * er_r + delay1->clock(right) + lright + (1.5 * upper) + (1.5 * lower); + left = left * .3f + 1.5f * er_l + delay2->clock(left) + lleft + (1.5 * upper) + (1.5 * lower); + } + + right *= .033f; + left *= .033f; + + // spread crossover (emulates mic positions) + last_out1 = (left + cross1 * right) * my_p[n_master]; + last_out2 = (right + cross1 * left) * my_p[n_master]; + } + else + { + last_out1 = last_out2 = mono * my_p[n_master]; + } + if (mute) + { + last_out1 = 0; + last_out2 = 0; + } + + (*out1++) = last_out1; + (*out2++) = last_out2; + + in1++; + in2++; + } + +} + +void effectMain::resume() +{ + // wantEvents (); + if (fullyloaded) + { + mute = false; + } +} + +void effectMain::suspend() +{ + int x; + n1->suspend(); + mute = true; + + for (x = 0; x < 4; x++) + { + allpass_r[x].reset(); + allpass_l[x].reset(); + } + + delay1->flood(0); + delay2->flood(0); + delay3->flood(0); + delay4->flood(0); + vdelay1->flood(0); + vdelay2->flood(0); + wand_r->flood(0); + wand_l->flood(0); + + param_is_manual = false; +} diff --git a/AZR3_vst2.4/effectMainEventHandling.cpp b/AZR3_vst2.4/effectMainEventHandling.cpp new file mode 100644 index 0000000..3bfaf46 --- /dev/null +++ b/AZR3_vst2.4/effectMainEventHandling.cpp @@ -0,0 +1,247 @@ +#include "effectMain.h" + +VstInt32 effectMain::processEvents(VstEvents* ev) +{ + /* + Fairly linear stuff. Differing from the SDK example: + The SDK does not guarantee that all events arrive in correct order. + It's possible that a weird VST host sends a note off with a delta + of 500 followed by a note on with a delta of 100. If we process + the events in the order they arrive we would have a "hanging note" + with this example. So we want to do our own event handling and make + it sample accurate. Sample accuracy can only be provided inside the + process/processReplacing function. Now you know why. I have spoken. + */ + if (mute) + return(0); + for (long i = 0; i < ev->numEvents; i++) + { + if ((ev->events[i])->type != kVstMidiType) + continue; + VstMidiEvent* event = (VstMidiEvent*)ev->events[i]; + char* midiData = event->midiData; + + long status = midiData[0] & 0xf0; // strip channel + + float channel = (float)(midiData[0] & 0x0f); // strip command + if (channel > 2) + channel = 0; + + if (status == 0x90 || status == 0x80) // notes + { + long note = midiData[1] & 0x7f; + long velocity = midiData[2] & 0x7f; + if (status == 0x80) + velocity = 0; + if (!velocity || status == 0x80) + { + if (splitpoint > 0 && channel == 0 && note <= splitpoint) + channel = 2; + add_event(evt_noteoff, event->deltaFrames, (float)note, (float)velocity, channel); + } + else + { + if (waitforsplit && note > 0) + { + splitpoint = note; + setParameterAutomated(n_splitpoint, float(note) / 128.0f); + if (editor) + ((AEffGUIEditor*)editor)->setParameter(n_split, float(note) / 128.0f); + waitforsplit = false; + } + else + { + if (splitpoint > 0 && channel == 0 && note <= splitpoint) + channel = 2; + add_event(evt_noteon, event->deltaFrames, (float)note, (float)velocity, channel); + } + } + } + else if (status == 0xb0 && (midiData[1] == 0x78 + || midiData[1] == 0x79 + || midiData[1] == 0x7a + || midiData[1] == 0x7b + || midiData[1] == 0x7c + || midiData[1] == 0x7d + || midiData[1] == 0x7e + || midiData[1] == 0x7f)) // all notes off + { + add_event(evt_alloff, event->deltaFrames, 0, 0, -1); + } + else if (status == 0xb0 && midiData[1] == 0x07) // main volume + { + add_event(evt_volume, event->deltaFrames, (float)midiData[2] / 128, 0, -1); + } + else if (status == 0xb0 && midiData[1] == 0x40) // footswitch + { + float mp = 0; + if (midiData[2] > 64) + mp = 127; + if (my_p[n_pedalspeed] < .5f) + { + add_event(evt_pedal, event->deltaFrames, mp, 0, channel); + } + else + { + add_event(evt_modulation, event->deltaFrames, mp, 0, -1); + } + } +#ifndef DEVELOP + else if (status == 0xb0 && midiData[1] > 0x4a && midiData[1] < 0x54) // drawbar controllers + { + add_event(evt_drawbar, event->deltaFrames, (float)(midiData[1] - 0x4b), (float)midiData[2], channel); + } +#endif + else if (status == 0xb0 && midiData[1] == 0x03) // channel volume + { + add_event(evt_channel_volume, event->deltaFrames, (float)midiData[2], 0, channel); + } + else if (status == 0xb0 && midiData[1] == 0x01) // Modulation wheel + { + // We had problems with many hosts: + // Modulation was set to 0 during song start + // So we don't use modulation as volume control anymore + /* + if(my_p[n_pedalspeed]<.5f) + { + */ + if (midiData[2] < 63) + add_event(evt_modulation, event->deltaFrames, 0, 0, -1); + else + add_event(evt_modulation, event->deltaFrames, 1, 0, -1); + /* + } + else + add_event(evt_volume,event->deltaFrames,(float)midiData[2]/128,0,-1); + */ + } + else if (status == 0xc0) // Program Change + { + add_event(evt_progchange, event->deltaFrames, midiData[1], 0, -1); + } +#ifdef DEVELOP + else if (status == 0xb0 && midiData[1] == 0x4a) // Ozone Ctrl 1 + { + char t[100]; + ctrl1 = ((float)midiData[2]) / 127; + sprintf(t, "ctrl1=%f ctrl2=%f ctrl3=%f ctrl4=%f\n", ctrl1, ctrl2, ctrl3, ctrl4); + OutputDebugString(t); + } + else if (status == 0xb0 && midiData[1] == 0x47) // Ozone Ctrl 2 + { + char t[100]; + ctrl2 = ((float)midiData[2]) / 127; + sprintf(t, "ctrl1=%f ctrl2=%f ctrl3=%f ctrl4=%f\n", ctrl1, ctrl2, ctrl3, ctrl4); + OutputDebugString(t); + } + else if (status == 0xb0 && midiData[1] == 0x51) // Ozone Ctrl 3 + { + char t[100]; + ctrl3 = ((float)midiData[2]) / 127; + sprintf(t, "ctrl1=%f ctrl2=%f ctrl3=%f ctrl4=%f\n", ctrl1, ctrl2, ctrl3, ctrl4); + OutputDebugString(t); + } + else if (status == 0xb0 && midiData[1] == 0x5b) // Ozone Ctrl 4 + { + char t[100]; + ctrl4 = ((float)midiData[2]) / 127; + sprintf(t, "ctrl1=%f ctrl2=%f ctrl3=%f ctrl4=%f\n", ctrl1, ctrl2, ctrl3, ctrl4); + OutputDebugString(t); + } +#endif + else if (status == 0xe0) // pitch bend + { + float pitch = (float)(midiData[2] * 128 + midiData[1]); + + if (pitch > 8192 + 600) + { + float p = pitch / 8192 - 1; + pitch = p * (float)pow(1.059463094359, int(12 * my_p[n_bender])) + 1 - p; + } + else if (pitch < 8192 - 600) + { + float p = (8192 - pitch) / 8192; + pitch = 1 / (p * (float)pow(1.059463094359, int(12 * my_p[n_bender])) + 1 - p); + } + else + pitch = 1; + + add_event(evt_pitch, event->deltaFrames, pitch, 0, channel); + } + + event++; + } + return 1; // we want more events +} + +void effectMain::add_event(unsigned char type, long deltaframes, float value1, float value2, float value3) +{ + // a valid buffer entry is marked by a delta value >=0 + // to add an event we enter the values and set the pointer to the + // next position which has to be empty + + has_events = true; + + // get last event + event_last_pos = event_pos - 1; + if (event_last_pos < 0) + event_last_pos += EVTBUFSIZE; + + event_next_pos = event_pos + 1; + if (event_next_pos >= EVTBUFSIZE) + event_next_pos -= EVTBUFSIZE; + + if (delta[event_next_pos] >= 0) // event buffer is full + return; + + + if (delta[event_last_pos] >= 0) // there is an event before this one + { + if (deltaframes < delta[event_last_pos]) // error: event not in sequence + delta[event_pos] = delta[event_last_pos] - deltaframes; // delta difference + else + delta[event_pos] = deltaframes - delta[event_last_pos]; // delta difference + } + else + delta[event_pos] = deltaframes; + + + events[event_pos] = type; + evalue1[event_pos] = value1; + evalue2[event_pos] = value2; + evalue3[event_pos] = value3; + + event_pos++; + if (event_pos >= EVTBUFSIZE) + event_pos -= EVTBUFSIZE; +} + +float* effectMain::event_clock() +{ + if (!has_events) + return(0); + + if (delta[event_read_pos] < 0) // there are no events in the buffer + { + has_events = false; + return(NULL); + } + + delta[event_read_pos]--; // count delta frames (reset event if delta==0) + + if (delta[event_read_pos] < 0) // event is now + { + values[0] = (float)events[event_read_pos]; + values[1] = evalue1[event_read_pos]; + values[2] = evalue2[event_read_pos]; + values[3] = evalue3[event_read_pos]; + ret = values; + event_read_pos++; + if (event_read_pos >= EVTBUFSIZE) + event_read_pos -= EVTBUFSIZE; + } + else + ret = NULL; // no event yet + + return(ret); +} diff --git a/AZR3_vst2.4/effectMainFactorySounds.cpp b/AZR3_vst2.4/effectMainFactorySounds.cpp new file mode 100644 index 0000000..b6eec97 --- /dev/null +++ b/AZR3_vst2.4/effectMainFactorySounds.cpp @@ -0,0 +1,2285 @@ +#include "effectMain.h" + +/* + OK, this "factory sound" stuff looks weird, + but it works just perfect. I wrote a mini tool + which analyzes a Cubase program bank file and + writes just these lines. This makes it very easy + to implement "factory sounds". +*/ +void effectMain::setFactorySounds() +{ + int x = 0; + { + float mp[kNumParams] = + { + 0.0000f, + 0.5000f, + 0.2000f, + 0.4800f, + 0.4300f, + 0.3300f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.3400f, + 0.3000f, + 1.0000f, + 0.6500f, + 0.0000f, + 1.0000f, + 0.1900f, + 0.5400f, + 0.0000f, + 0.2300f, + 0.1500f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 1.0000f, + 0.2100f, + 0.3400f, + 0.3700f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3010f, + 0.3510f, + 0.0000f, + 1.0000f, + 0.5900f, + 0.9400f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.4400f, + 1.0000f, + 0.2700f, + 0.1800f, + 1.0000f, + 0.0000f, + 0.0900f, + 0.4800f, + 0.0470f, + 0.6500f, + 0.5000f, + 0.4200f, + 1.0000f, + 1.0000f, + 0.4609f, + 0.6700f, + 0.0000f, + 0.0000f, + 1.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "muddy moods SPLIT"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.5200f, + 0.2000f, + 0.4000f, + 0.5000f, + 1.0000f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.7900f, + 0.2300f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 1.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 1.0000f, + 0.2100f, + 0.3400f, + 0.3700f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3010f, + 0.3510f, + 0.0000f, + 1.0000f, + 0.2100f, + 0.6700f, + 0.0900f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.5000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0400f, + 0.4700f, + 0.0500f, + 0.6800f, + 0.5000f, + 0.5100f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "Volle Kante"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2200f, + 0.2000f, + 0.3000f, + 0.0000f, + 0.1000f, + 0.5000f, + 0.3700f, + 0.6000f, + 0.6600f, + 0.3900f, + 1.0000f, + 1.0000f, + 0.8800f, + 0.0000f, + 0.5700f, + 0.0000f, + 0.5500f, + 0.0000f, + 0.5100f, + 0.4600f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 1.0000f, + 0.2100f, + 0.3400f, + 0.3700f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3010f, + 0.3510f, + 0.0000f, + 1.0000f, + 0.3600f, + 0.4500f, + 0.0900f, + 0.0000f, + 0.0000f, + 0.4400f, + 1.0000f, + 0.1000f, + 0.2500f, + 1.0000f, + 0.0000f, + 0.0900f, + 0.4700f, + 0.0470f, + 0.6600f, + 0.4200f, + 0.3200f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "clean"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.5100f, + 0.2000f, + 0.0000f, + 0.7500f, + 0.2700f, + 1.0000f, + 0.3400f, + 0.6000f, + 0.3100f, + 0.5400f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0900f, + 0.4800f, + 0.0000f, + 0.3700f, + 0.1700f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 1.0000f, + 0.2100f, + 0.3400f, + 0.3700f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3010f, + 0.3510f, + 0.0000f, + 1.0000f, + 0.6300f, + 0.4100f, + 0.4400f, + 0.0000f, + 1.0000f, + 0.5600f, + 1.0000f, + 1.0000f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.0400f, + 0.6000f, + 0.0770f, + 0.7300f, + 1.0000f, + 0.6400f, + 0.0000f, + 1.0000f, + 0.4609f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "hollow SPLIT"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.3000f, + 0.3400f, + 0.3700f, + 1.0000f, + 0.6900f, + 0.6000f, + 0.0000f, + 0.5400f, + 1.0000f, + 0.2200f, + 1.0000f, + 0.0000f, + 0.0200f, + 0.0800f, + 0.0000f, + 0.2300f, + 0.1500f, + 0.1800f, + 1.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.2500f, + 0.4400f, + 1.0000f, + 0.0000f, + 0.0600f, + 0.5300f, + 0.0400f, + 0.7500f, + 0.5000f, + 0.1900f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "talking space"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.5000f, + 0.2000f, + 0.0000f, + 0.3600f, + 0.3900f, + 0.9700f, + 0.5300f, + 0.6000f, + 0.3400f, + 0.2100f, + 1.0000f, + 1.0000f, + 0.7800f, + 0.0000f, + 0.6500f, + 0.0000f, + 0.4961f, + 0.2300f, + 0.1200f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.6400f, + 0.4900f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.3100f, + 1.0000f, + 0.4500f, + 0.2700f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.4900f, + 0.0470f, + 0.6700f, + 0.2100f, + 0.5000f, + 1.0000f, + 1.0000f, + 0.4609f, + 0.0500f, + 0.0000f, + 0.0000f, + 1.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "fat amped SPLIT"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.3000f, + 0.2000f, + 0.6800f, + 0.6800f, + 0.7500f, + 0.1000f, + 0.5500f, + 0.6000f, + 0.0000f, + 0.2200f, + 1.0000f, + 0.6500f, + 1.0000f, + 1.0000f, + 0.4500f, + 0.0000f, + 0.4500f, + 1.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.4600f, + 0.1000f, + 0.3800f, + 0.2400f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0670f, + 0.7800f, + 0.5000f, + 0.2200f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "FLPs fiese Forfiesa"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.0000f, + 0.2000f, + 0.5000f, + 0.2200f, + 0.3900f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.4800f, + 1.0000f, + 1.0000f, + 0.4540f, + 0.2170f, + 0.3550f, + 0.1510f, + 0.3030f, + 0.0960f, + 0.1890f, + 0.0000f, + 1.0000f, + 0.5000f, + 0.3800f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.0000f, + 1.0000f, + 0.5100f, + 1.0000f, + 1.0000f, + 1.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7100f, + 1.0000f, + 0.1700f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "NHL"); + } + + { + float mp[kNumParams] = + { + 1.0000f, + 0.0000f, + 0.2000f, + 0.0000f, + 0.4300f, + 0.2000f, + 0.5000f, + 0.7000f, + 0.6000f, + 0.0000f, + 0.7000f, + 1.0000f, + 1.0000f, + 0.4300f, + 0.3050f, + 0.2400f, + 0.0990f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.6450f, + 0.0000f, + 0.7400f, + 0.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0300f, + 1.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "FLPs cool bass 1"); + } + + { + float mp[kNumParams] = + { + 1.0000f, + 0.0000f, + 0.2000f, + 0.0000f, + 0.5200f, + 0.1400f, + 0.5000f, + 0.7800f, + 0.6000f, + 0.0000f, + 0.7000f, + 1.0000f, + 1.0000f, + 0.4200f, + 0.3050f, + 0.1900f, + 0.1690f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.6450f, + 0.0000f, + 0.7400f, + 0.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "FLPs cool bass 2"); + } + + { + float mp[kNumParams] = + { + 1.0000f, + 0.0000f, + 0.2000f, + 0.0000f, + 0.5200f, + 0.2100f, + 0.5000f, + 0.7000f, + 0.6000f, + 0.0000f, + 0.4000f, + 1.0000f, + 1.0000f, + 0.2500f, + 0.1450f, + 0.0900f, + 0.0390f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.5400f, + 1.0000f, + 0.0000f, + 0.2600f, + 0.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.1000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "FLPs even cooler bass"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.7200f, + 0.2000f, + 0.0000f, + 1.0000f, + 0.3000f, + 0.0100f, + 0.5600f, + 0.6000f, + 0.0000f, + 0.2800f, + 1.0000f, + 0.1600f, + 0.5900f, + 1.0000f, + 0.0000f, + 0.9900f, + 0.3000f, + 0.4200f, + 0.8900f, + 0.2400f, + 1.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.3500f, + 1.0000f, + 0.3700f, + 0.6000f, + 1.0000f, + 1.0000f, + 0.1000f, + 0.3900f, + 0.0470f, + 1.0000f, + 1.0000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "cutter"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.7300f, + 0.0000f, + 1.0000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.1700f, + 1.0000f, + 0.7600f, + 0.3400f, + 0.0700f, + 0.1400f, + 0.5800f, + 0.2700f, + 1.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.5200f, + 0.2400f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.1100f, + 0.6800f, + 0.0570f, + 0.7700f, + 0.5000f, + 0.1100f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "MODEM"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.0400f, + 0.2000f, + 0.0000f, + 0.2100f, + 1.0000f, + 1.0000f, + 0.5200f, + 0.6000f, + 0.0000f, + 0.4500f, + 1.0000f, + 1.0000f, + 0.5900f, + 0.0000f, + 0.0000f, + 0.0500f, + 0.0000f, + 0.0200f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.7000f, + 0.2900f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.5700f, + 0.4700f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.2900f, + 0.6500f, + 0.1300f, + 0.7800f, + 0.5000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.9800f, + 1.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "sine vibra"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.5000f, + 0.2000f, + 0.4600f, + 0.5700f, + 0.3700f, + 0.2000f, + 0.6000f, + 0.6000f, + 0.4400f, + 0.2900f, + 1.0000f, + 1.0000f, + 0.8800f, + 0.3700f, + 0.7500f, + 0.0000f, + 0.5800f, + 0.5400f, + 0.0000f, + 0.0800f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.5300f, + 0.4100f, + 0.6500f, + 0.0000f, + 1.0000f, + 0.3900f, + 1.0000f, + 0.4500f, + 0.1900f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6800f, + 0.0470f, + 0.7200f, + 0.5000f, + 0.4200f, + 1.0000f, + 1.0000f, + 0.4297f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "some rotz SPLIT"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.3300f, + 0.2000f, + 1.0000f, + 0.7300f, + 0.2400f, + 1.0000f, + 0.4600f, + 0.6000f, + 0.0000f, + 0.3400f, + 1.0000f, + 1.0000f, + 0.2300f, + 0.0000f, + 0.1100f, + 0.6400f, + 0.0000f, + 0.4500f, + 0.8400f, + 0.4100f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.1600f, + 0.4800f, + 0.2100f, + 0.1000f, + 1.0000f, + 0.0000f, + 0.0400f, + 0.2500f, + 0.0570f, + 0.6100f, + 0.7100f, + 0.3800f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "thin"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.5500f, + 0.2000f, + 0.6000f, + 0.1800f, + 0.4400f, + 0.0000f, + 0.4900f, + 0.6000f, + 0.0000f, + 0.6000f, + 1.0000f, + 0.4400f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.2600f, + 0.4900f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.2800f, + 1.0000f, + 0.3400f, + 0.1900f, + 1.0000f, + 0.0000f, + 0.0400f, + 0.6400f, + 0.0770f, + 0.7700f, + 1.0000f, + 0.6900f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "angel hair"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.4500f, + 0.2000f, + 0.5300f, + 0.5600f, + 1.0000f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2400f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.2100f, + 0.2700f, + 0.6200f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0670f, + 0.7800f, + 0.7700f, + 0.4200f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "little duck"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.0000f, + 0.2000f, + 0.6200f, + 0.4500f, + 0.2400f, + 1.0000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.4500f, + 1.0000f, + 1.0000f, + 0.7900f, + 0.0000f, + 0.4300f, + 0.0000f, + 0.1800f, + 0.0000f, + 0.0000f, + 0.0800f, + 1.0000f, + 0.5700f, + 0.3500f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.4200f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "dead entertainer"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.9100f, + 0.2000f, + 0.4400f, + 0.6500f, + 0.3300f, + 0.6800f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.7900f, + 0.5800f, + 0.0000f, + 0.2600f, + 0.0000f, + 0.0000f, + 0.4400f, + 1.0000f, + 0.2100f, + 0.3400f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7200f, + 0.5000f, + 0.5000f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "resurrected entertainer"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.0100f, + 0.2000f, + 0.8500f, + 0.2300f, + 0.3600f, + 0.9900f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.3700f, + 1.0000f, + 1.0000f, + 0.4700f, + 0.3800f, + 0.2100f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.3000f, + 0.3000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "cheap B*ntempi"); + } + + { + float mp[kNumParams] = + { + 1.0000f, + 0.0000f, + 0.2000f, + 0.8600f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.5100f, + 0.6000f, + 0.0000f, + 0.6800f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0400f, + 0.0400f, + 1.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.6900f, + 1.0000f, + 0.9800f, + 0.1900f, + 1.0000f, + 0.0000f, + 0.0600f, + 0.6500f, + 0.0770f, + 0.7800f, + 0.5000f, + 0.2200f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "NDW lead"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "the rest is empty"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "make your own!"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "just turn the knobs-"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "-it's not very hard!"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "Still here?"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "Come on now!"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "You can't wait forever."); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "Give it a try."); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "Not?"); + } + + { + float mp[kNumParams] = + { + 0.0000f, + 0.2000f, + 0.2000f, + 0.0000f, + 0.0000f, + 0.7500f, + 0.5000f, + 0.6000f, + 0.6000f, + 0.0000f, + 0.2200f, + 0.0000f, + 1.0000f, + 1.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.3000f, + 0.3500f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.4000f, + 0.0000f, + 0.6600f, + 0.0000f, + 1.0000f, + 0.0000f, + 0.1000f, + 0.6500f, + 0.0470f, + 0.7800f, + 0.5000f, + 0.5000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + 0.0000f, + }; + memcpy(programs[x].p, mp, sizeof(mp)); + strcpy(programs[x++].name, "--init--"); + } + +} \ No newline at end of file diff --git a/AZR3_vst2.4/effectMainParameter.cpp b/AZR3_vst2.4/effectMainParameter.cpp new file mode 100644 index 0000000..d65cbb5 --- /dev/null +++ b/AZR3_vst2.4/effectMainParameter.cpp @@ -0,0 +1,411 @@ +#include "effectMain.h" + +void effectMain::getParameterLabel(VstInt32 index, char* label) +{ + // forget it, we don't fully support non-GUI interface... + // sprintf(label, "",index); + if (index < kNumParams) + strcpy(label, labels[index]); + else + strcpy(label, "---"); +} + +void effectMain::getParameterDisplay(VstInt32 index, char* text) +{ + text[0] = 0; + switch (index) + { + case n_bender: + parameterConversions::convert_bendrange(p[index], text); + break; + case n_tone: + parameterConversions::convert_tone(p[index], text); + break; + case n_l_slow: + case n_u_slow: + case n_l_fast: + case n_u_fast: + parameterConversions::convert_speed(p[index], text); + break; + case n_perc: + parameterConversions::convert_perc(p[index], text); + break; + case n_shape: + parameterConversions::convert_shape(p[index], text); + break; + default: + sprintf(text, "%3.1f %%", 100 * p[index]); + break; + } +} + +void effectMain::getParameterName(VstInt32 index, char* label) +{ + if (index < kNumParams) + strcpy(label, labels[index]); + else + strcpy(label, "---"); +} + +void effectMain::setInternalParameter(VstInt32 index, float value) +{ + if (index<0 || index > kNumParams || (!param_is_manual && setProgramDelayCount >= 0)) + return; + + if (compare) + { + vstProgram* ap = &programs[curProgram]; + value = ap->p[index]; // fetch value from program memory + my_p = ap->p; // let machine use program memory + } + else + { + p[index] = value; // put value into edit buffer + my_p = p; // let machine use edit buffer + } + + //if(value!=last_value[index]) + { + last_value[index] = value; + switch (index) + { + case n_1_db1: + case n_1_db2: + case n_1_db3: + case n_1_db4: + case n_1_db5: + case n_1_db6: + case n_1_db7: + case n_1_db8: + case n_1_db9: + rebuildWavetableSet(1); + rebuildClickWavetable(); + break; + case n_2_db1: + case n_2_db2: + case n_2_db3: + case n_2_db4: + case n_2_db5: + case n_2_db6: + case n_2_db7: + case n_2_db8: + case n_2_db9: + rebuildWavetableSet(2); + rebuildClickWavetable(); + break; + case n_3_db1: + case n_3_db2: + case n_3_db3: + case n_3_db4: + case n_3_db5: + rebuildWavetableSet(3); + rebuildClickWavetable(); + break; + case n_shape: + if (buildTonewheelSet(int(value * (NUM_OF_TONEWHEEL_SHAPES - 1) + 1) - 1)) + { + rebuildWavetableSet(1); + rebuildWavetableSet(2); + rebuildWavetableSet(3); + } + break; + case n_1_perc: + case n_2_perc: + case n_3_perc: + case n_perc: + case n_percvol: + case n_percfade: + { + int v = (int)(my_p[n_perc] * 10); + float pmult; + if (v < 1) + pmult = 0; + else if (v < 2) + pmult = 1; + else if (v < 3) + pmult = 2; + else if (v < 4) + pmult = 3; + else if (v < 5) + pmult = 4; + else if (v < 6) + pmult = 6; + else if (v < 7) + pmult = 8; + else if (v < 8) + pmult = 10; + else if (v < 9) + pmult = 12; + else + pmult = 16; + + n1->set_percussion(1.5f * my_p[n_percvol], pmult, my_p[n_percfade]); + } + break; + case n_click: + rebuildClickWavetable(); + break; + case n_vol1: + n1->set_volume(value * .3f, 0); + break; + case n_vol2: + n1->set_volume(value * .4f, 1); + break; + case n_vol3: + n1->set_volume(value * .6f, 2); + break; + case n_mono: + if (value != mono_before) + { + if (value >= .5f) + n1->set_numofvoices(1); + else + n1->set_numofvoices(NUMOFVOICES); + + n1->set_volume(my_p[n_vol1] * .3f, 0); + n1->set_volume(my_p[n_vol2] * .3f, 1); + n1->set_volume(my_p[n_vol3] * .6f, 2); + } + mono_before = value; + break; + case n_1_vibrato: + vibchanged1 = true; + break; + case n_1_vmix: + if (my_p[n_1_vibrato] == 1) + { + vmix1 = value; + vibchanged1 = true; + } + break; + case n_2_vibrato: + vibchanged2 = true; + break; + case n_2_vmix: + if (my_p[n_2_vibrato] == 1) + { + vmix2 = value; + vibchanged2 = true; + } + break; + case n_drive: + if (value > 0) + do_dist = true; + else + do_dist = false; + dist = 2 * (0.1f + value); + sin_dist = sinf(dist); + i_dist = 1 / dist; + dist4 = 4 * dist; + dist8 = 8 * dist; + break; + case n_mrvalve: + odchanged = true; + break; + case n_mix: + odmix = value; + if (my_p[n_mrvalve] == 1) + odchanged = true; + break; + case n_tone: + fuzz_filt.setparam(800 + value * 3000, .7f, samplerate); + break; + case n_speed: + if (value > .5f) + fastmode = true; + else + fastmode = false; + break; + case n_l_slow: + lslow = value * 10; + break; + case n_l_fast: + lfast = value * 10; + break; + case n_u_slow: + uslow = value * 10; + break; + case n_u_fast: + ufast = value * 10; + break; + case n_belt: + ubelt_up = (value * 3 + 1) * .012f; + ubelt_down = (value * 3 + 1) * .008f; + lbelt_up = (value * 3 + 1) * .0045f; + lbelt_down = (value * 3 + 1) * .0035f; + break; + case n_spread: + lfos_ok = false; + break; + case n_splitpoint: + splitpoint = (long)(value * 128); + break; + } + + if (editor) + ((AEffGUIEditor*)editor)->setParameter(index, value); + } +} + +void effectMain::setParameter(VstInt32 index, float value) +{ + /* + If you implement a plugin as suggested in the SDK you + will have the following side effect: + An automated or manually changed parameter will always + be written into the actual program. The original program + is lost. To prevent this we use several program buffers + and let the plugin decide wether the data will be + saved or not. This is the desired behaviour, similar + to all those hardware expanders. + + A new feature is delayed program change. When the host runs + several setProgram calls shortly after another we don't want + to perform real program and parameter changes. We store the + new program name in next_curProgram and let virtual_my_p point + to the according program memory. From setProgram we set + setProgramStep=sps_requested. The process routine sees this, + sets setProgramStep=sps_waiting, counts for a while, sets + setProgramStep=sps_acknowledged and runs a setProgram(next_curProgram). + Now setProgram and setParameter can decide whether to ignore + the change (if next_curProgram==curProgram) or to perform + a real, full program change with all parameter changes. + setProgramStep will be reset to sps_idle. + + ap program memory + p edit buffer + i_p buffer to save edit buffer (for compare function) + my_p points to any buffer. The "machine" always uses my_p. + */ + + /* + UPDATE: + Due to incompatibilities with several hosts we make the whole feature + compile-time switch dependent. We use delayed program change only if + DELAYED_PARAMS is defined. + */ + + vstProgram* ap = &programs[curProgram]; + my_p = p; // let machine use program memory + +// ...no "save" button without editor, so no delayed parameter changes... + if (!editor) + param_is_manual = true; + + if (index == n_mute) + { + if (value > 0) + mute = true; + else + { + // This is one of the two methods to finally activate everything. + // We need some time in advance in order to fill all buffers with correct data. + // The other method is located at processReplacing. + mute = false; + fullyloaded = true; + } + } + + if (index == n_param_is_manual) + { + if (value > .5f) // we have a manual parameter change + { + param_is_manual = true; + } + else + param_is_manual = false; + } + else if (index == n_1_midi || index == n_2_midi || index == n_3_midi) + { + if (editor) + ((AEffGUIEditor*)editor)->setParameter(index, value); + } + else if (index == n_split) + { + if (value == 1) + waitforsplit = true; + else + { + waitforsplit = false; + splitpoint = 0; + } + } + else if (index >= 0 && index < kNumParams) + { +#ifdef DELAYED_PARAMS + if (!param_is_manual) // not manual: bank or patch load +#endif + ap->p[index] = value; // copy value into program memory + + setInternalParameter(index, value); + } +#ifdef DELAYED_PARAMS + else if (index == n_compare) + { + if (value == 0) // compare button released + { + for (int i = 0; i < kNumParams; i++) + p[i] = i_p[i]; // recall edit buffer + compare = false; + my_p = p; // let machine use edit buffer + } + else // compare button pressed + { + for (int i = 0; i < kNumParams; i++) + i_p[i] = p[i]; // save edit buffer + compare = true; + my_p = ap->p; // let machine use program memory + } + + for (int i = 0; i < kNumParams; i++) + my_setParameter(i, my_p[i]); // let everyone know the new values + } + else if (index == n_save) // save button pressed + { + for (int i = 0; i < kNumParams; i++) + { + if (compare) + { + ap->p[i] = i_p[i]; // copy compare buffer params to program memory + } + else + { + ap->p[i] = my_p[i]; // copy current machine params to program memory + i_p[i] = my_p[i]; // copy current machine params to compare buffer + // We need this since there will be a setParameter + // to n_compare with value 0 which will write the + // compare buffer back to the edit buffer. + } + } + } + else if (index == n_display) +#else + if (index == n_display) +#endif + { + if (value < 0) + value = 0; + if (value > kNumPrograms - 1) + value = kNumPrograms - 1; + if ((long)value != getProgram()) + setProgram((long)value); + } +} + +float effectMain::getParameter(VstInt32 index) +{ + gp_value = 0; + if (index >= 0 && index < kNumParams) + gp_value = virtual_my_p[index]; + + if (index == n_output) + { + gp_value = fabsf(last_out1) * 7; + if (gp_value < 0 || mono == 0) + gp_value = 0; + if (gp_value > 1) + gp_value = 1; + } + + return gp_value; +} diff --git a/AZR3_vst2.4/effectMainProgram.cpp b/AZR3_vst2.4/effectMainProgram.cpp new file mode 100644 index 0000000..3e5f511 --- /dev/null +++ b/AZR3_vst2.4/effectMainProgram.cpp @@ -0,0 +1,101 @@ +#include "effectMain.h" + +void effectMain::setProgram(VstInt32 program) +{ + // this->setProgram(program,false); + this->setProgram(program, true); +} + +void effectMain::setProgram(VstInt32 program, bool force) +{ + long x; + + if (force) + actual_curProgram = -2; + + vstProgram* ap = &programs[program]; + + // prepare for delayed program change + virtual_my_p = ap->p; + curProgram = program; + +#ifndef DELAYED_PARAMS + setProgramDelayCount = -1; +#endif + + // has the program change fxDelay elapsed? + if (setProgramDelayCount == -1) + { + curProgram = program; + virtual_my_p = my_p; + } + + if (actual_curProgram != program) + { + for (x = 0; x < kNumParams; x++) + { +#ifdef DELAYED_PARAMS + param_is_manual = true; +#endif + setParameter(x, ap->p[x]); + } + } + + // set parameter display only after program change fxDelay has elapsed + // this must occur after the setParameter calls +#ifdef DELAYED_PARAMS + if (setProgramDelayCount == -1 || param_is_manual) + { + setProgramDelayCount = 0; +#endif + if (editor) + ((AEffGUIEditor*)editor)->setParameter(n_display, (float)curProgram); + actual_curProgram = program; +#ifdef DELAYED_PARAMS + } + // retrigger fxDelay if we are idle or during fxDelay + else + { + setProgramDelayCount = 1; + } +#endif + + param_is_manual = false; +} + +void effectMain::setProgramName(char* name) +{ + strcpy(programs[curProgram].name, name); + if (editor) + ((AEffGUIEditor*)editor)->setParameter(n_display, (float)curProgram); +} + +void effectMain::getProgramName(char* name) +{ + strcpy(name, programs[curProgram].name); +} + +bool effectMain::getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text) +{ + if (index < kNumPrograms) + { + strcpy(text, programs[index].name); + return true; + } + return false; +} + +bool effectMain::copyProgram(VstInt32 destination) +{ + if (destination < kNumPrograms) + { + programs[destination] = programs[curProgram]; + return true; + } + return false; +} + +VstInt32 effectMain::getProgram() +{ + return(curProgram); +} diff --git a/AZR3_vst2.4/effectMainWavetables.cpp b/AZR3_vst2.4/effectMainWavetables.cpp new file mode 100644 index 0000000..263c4d9 --- /dev/null +++ b/AZR3_vst2.4/effectMainWavetables.cpp @@ -0,0 +1,277 @@ +#include "effectMain.h" + +bool effectMain::buildTonewheelSet(int shape) +{ + long i; + float amp = .5f; + float tw = 0, twfuzz; + float twmix = .5f; + float twdist = .7f; + float tws = (float)WAVETABLESIZE; + + + if (shape == last_shape) + return(false); + last_shape = shape; + /* + We don't just produce flat sine curves but slightly distorted + and even a triangle wave can be choosen. + + Though this makes things sound more interesting it's _not_ a + tonewheel emulation. If we wanted that we would have to calculate + or otherwise define different waves for every playable note. If + anyone wants to implement real tonewheels you will have to make + drastic changes: + - implement many wavetables and a choosing algorithm + - construct wavetable data either through calculations + or from real wave files. Tha latter is what they do at + n@tive 1nstrument5. + */ + for (i = 0; i < WAVETABLESIZE; i++) + { + float ii = (float)i; + + if (shape == TONEWHEEL_SHAPE_SINE1) + { + tw = amp * + ( + sinf(ii * 2 * Pi / tws) + + .01f * sinf(ii * 8 * Pi / tws) + + .003f * sinf(ii * 12 * Pi / tws) + ); + tonewheel[i] = tw; + } + else if (shape == TONEWHEEL_SHAPE_SINE2 || shape == TONEWHEEL_SHAPE_SINE3) + { + tw = amp * + ( + sinf(ii * 2 * Pi / tws) + + .03f * sinf(ii * 8 * Pi / tws) + + .01f * sinf(ii * 12 * Pi / tws) + ); + + if (shape == TONEWHEEL_SHAPE_SINE2) + twdist = 1; + else if (shape == TONEWHEEL_SHAPE_SINE3) + twdist = 2; + + tw *= twdist; + twfuzz = 2 * tw - tw * tw * tw; + if (twfuzz > 1) + twfuzz = 1; + else if (twfuzz < -1) + twfuzz = -1; + tonewheel[i] = .5f * twfuzz / twdist; + } + else if (shape == TONEWHEEL_SHAPE_TRI) + { + if (iint(tws * .75f)) + tw += 2 / tws; + else + tw -= 2 / tws; + tonewheel[i] = tw; + } + else if (shape == TONEWHEEL_SHAPE_SAW) + { + tw = sinf(ii * Pi / tws); + if (i > int(tws / 2)) + { + tw = sinf((ii - tws / 2) * Pi / tws); + tw = 1 - tw; + } + + tonewheel[i] = tw - .5f; + } + else + { + // pure sine + tw = amp * + ( + sinf(ii * 2 * Pi / tws) + //+.01f*sinf( ii*8*Pi/tws ) + //+.003f*sinf( ii*12*Pi/tws ) + ); + tonewheel[i] = tw; + } + } + + for (i = 0; i < WAVETABLESIZE; i++) + { + // int f=TONEWHEELSIZE/WAVETABLESIZE; + int f = 1; + int icount; + int i2[9]; + + i2[0] = (int)(i * 1 * f); + i2[1] = (int)(i * 2 * f); + i2[2] = (int)(i * 3 * f); + i2[3] = (int)(i * 4 * f); + i2[4] = (int)(i * 6 * f); + i2[5] = (int)(i * 8 * f); + i2[6] = (int)(i * 10 * f); + i2[7] = (int)(i * 12 * f); + i2[8] = (int)(i * 16 * f); + + for (icount = 0; icount < 9; icount++) + { + while (i2[icount] >= WAVETABLESIZE) + i2[icount] -= WAVETABLESIZE; + } + + sin_16[i] = tonewheel[i2[0]]; + sin_8[i] = tonewheel[i2[1]]; + sin_513[i] = tonewheel[i2[2]]; + sin_4[i] = tonewheel[i2[3]]; + sin_223[i] = tonewheel[i2[4]]; + sin_2[i] = tonewheel[i2[5]]; + sin_135[i] = tonewheel[i2[6]]; + sin_113[i] = tonewheel[i2[7]]; + sin_1[i] = tonewheel[i2[8]]; + } + + return(true); +} + +/** +* Build one of the three waveform sets with four complete waves +* per set. "number" is 1..3 and references the waveform set +*/ +void effectMain::rebuildWavetableSet(int number) +{ + int i, c; + float* t; + float this_p[kNumParams]; + for (c = 0; c < kNumParams; c++) + this_p[c] = my_p[c]; + if (number == 2) + { + c = n_2_db1; + t = &wavetable[WAVETABLESIZE * TABLES_PER_CHANNEL]; + } + else if (number == 3) + { + t = &wavetable[WAVETABLESIZE * TABLES_PER_CHANNEL * 2]; + c = n_3_db1; + } + else + { + t = &wavetable[0]; + c = n_1_db1; + } + + // weight to each drawbar + this_p[c] *= 1.5f; + this_p[c + 1] *= 1.0f; + this_p[c + 2] *= .8f; + this_p[c + 3] *= .8f; + this_p[c + 4] *= .8f; + this_p[c + 5] *= .8f; + this_p[c + 6] *= .8f; + this_p[c + 7] *= .6f; + this_p[c + 8] *= .6f; + + for (i = 0; i < WAVETABLESIZE; i++) + { + t[i] = t[i + WAVETABLESIZE] = t[i + WAVETABLESIZE * 2] = t[i + WAVETABLESIZE * 3] = + t[i + WAVETABLESIZE * 4] = + t[i + WAVETABLESIZE * 5] = + t[i + WAVETABLESIZE * 6] = + t[i + WAVETABLESIZE * 7] = + sin_16[i] * this_p[c] + sin_8[i] * this_p[c + 1] + + sin_513[i] * this_p[c + 2]; + + /* + This is very important for a warm sound: + The "tone wheels" are a limited resource and they + supply limited pitch heights. If a drawbar register + is forced to play a tune above the highest possible + note it will simply be transposed one octave down. + In addition it will appear less loud; that's what + d2, d4 and d8 are for. + */ +#define d2 .5f +#define d4 .25f +#define d8 .125f + if (number == 3) + { + t[i] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4]; + t[i + WAVETABLESIZE] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4]; + t[i + WAVETABLESIZE * 2] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4]; + t[i + WAVETABLESIZE * 3] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4]; + t[i + WAVETABLESIZE * 4] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4]; + t[i + WAVETABLESIZE * 5] += sin_4[i] * this_p[c + 3] + sin_223[int(i / 2)] * d2 * this_p[c + 4]; + t[i + WAVETABLESIZE * 6] += sin_4[i] * this_p[c + 3] + sin_223[int(i / 2)] * d2 * this_p[c + 4]; + t[i + WAVETABLESIZE * 7] += sin_4[int(i / 2)] * d2 * this_p[c + 3] + sin_223[int(i / 2)] * d2 * this_p[c + 4]; + } + else + { + t[i] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4] + + sin_2[i] * this_p[c + 5] + + sin_135[i] * this_p[c + 6] + sin_113[i] * this_p[c + 7] + + sin_1[i] * this_p[c + 8]; + t[i + WAVETABLESIZE] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4] + + sin_2[i] * this_p[c + 5] + + sin_135[i] * this_p[c + 6] + sin_113[i] * this_p[c + 7] + + sin_1[int(i / 2)] * d2 * this_p[c + 8]; + t[i + WAVETABLESIZE * 2] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4] + + sin_2[i] * this_p[c + 5] + + sin_135[i] * this_p[c + 6] + sin_113[int(i / 2)] * d2 * this_p[c + 7] + + sin_1[int(i / 2)] * d2 * this_p[c + 8]; + t[i + WAVETABLESIZE * 3] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4] + + sin_2[i] * this_p[c + 5] + + sin_135[int(i / 2)] * d2 * this_p[c + 6] + sin_113[int(i / 2)] * d2 * this_p[c + 7] + + sin_1[int(i / 2)] * d2 * this_p[c + 8]; + t[i + WAVETABLESIZE * 4] += sin_4[i] * this_p[c + 3] + sin_223[i] * this_p[c + 4] + + sin_2[int(i / 2)] * d2 * this_p[c + 5] + + sin_135[int(i / 2)] * d2 * this_p[c + 6] + sin_113[int(i / 2)] * d2 * this_p[c + 7] + + sin_1[int(i / 4)] * d4 * this_p[c + 8]; + t[i + WAVETABLESIZE * 5] += sin_4[i] * this_p[c + 3] + sin_223[int(i / 2)] * d2 * this_p[c + 4] + + sin_2[int(i / 2)] * d2 * this_p[c + 5] + + sin_135[int(i / 2)] * d2 * this_p[c + 6] + sin_113[int(i / 4)] * d4 * this_p[c + 7] + + sin_1[int(i / 4)] * d4 * this_p[c + 8]; + t[i + WAVETABLESIZE * 6] += sin_4[i] * this_p[c + 3] + sin_223[int(i / 2)] * d2 * this_p[c + 4] + + sin_2[int(i / 2)] * d2 * this_p[c + 5] + + sin_135[int(i / 4)] * 0 * this_p[c + 6] + sin_113[int(i / 4)] * d4 * this_p[c + 7] + + sin_1[int(i / 4)] * d4 * this_p[c + 8]; + t[i + WAVETABLESIZE * 7] += sin_4[int(i / 2)] * d2 * this_p[c + 3] + sin_223[int(i / 2)] * d2 * this_p[c + 4] + + sin_2[int(i / 4)] * d4 * this_p[c + 5] + + sin_135[int(i / 4)] * 0 * this_p[c + 6] + sin_113[int(i / 4)] * d4 * this_p[c + 7] + + sin_1[int(i / 8)] * d8 * this_p[c + 8]; + } + } + /* + The grown up source code viewer will find that sin_135 is only + folded once (/2). Well, I had terrible aliasing problems when + folding it twice (/4), and the easiest solution was to set it to + zero instead. You can't claim you actually heard it, can you? + */ + wavetable[WAVETABLESIZE * 12] = 0; +} + +void effectMain::rebuildClickWavetable() +{ + /* + Click is not just click - it has to follow the underlying + note pitch. However, the click emulation is just "try and + error". Improve it if you can, but PLEAZE tell me how you + did it... + */ + click[0] = my_p[n_click] * + (my_p[n_1_db1] + my_p[n_1_db2] + + my_p[n_1_db3] + my_p[n_1_db4] + + my_p[n_1_db5] + my_p[n_1_db6] + + my_p[n_1_db7] + my_p[n_1_db8] + + my_p[n_1_db9]) / 9; + + click[1] = my_p[n_click] * + (my_p[n_2_db1] + my_p[n_2_db2] + + my_p[n_2_db3] + my_p[n_2_db4] + + my_p[n_2_db5] + my_p[n_2_db6] + + my_p[n_2_db7] + my_p[n_2_db8] + + my_p[n_2_db9]) / 9; + + click[2] = my_p[n_click] * + (my_p[n_3_db1] + my_p[n_3_db2] + + my_p[n_3_db3] + my_p[n_3_db4] + + my_p[n_1_db5]) / 22; +} diff --git a/AZR3_vst2.4/effectMainWavetables.h b/AZR3_vst2.4/effectMainWavetables.h new file mode 100644 index 0000000..e69de29 diff --git a/AZR3_vst2.4/fxDelay.cpp b/AZR3_vst2.4/fxDelay.cpp new file mode 100644 index 0000000..730660b --- /dev/null +++ b/AZR3_vst2.4/fxDelay.cpp @@ -0,0 +1 @@ +#include "fxDelay.h" diff --git a/AZR3_vst2.4/fxDelay.h b/AZR3_vst2.4/fxDelay.h new file mode 100644 index 0000000..afe7967 --- /dev/null +++ b/AZR3_vst2.4/fxDelay.h @@ -0,0 +1,5 @@ +#pragma once +class fxDelay +{ +}; + diff --git a/AZR3_vst2.4/noteController.cpp b/AZR3_vst2.4/noteController.cpp new file mode 100644 index 0000000..a45792a --- /dev/null +++ b/AZR3_vst2.4/noteController.cpp @@ -0,0 +1,319 @@ +/* + The voiceController producing machine, diverted into two blocks: + + VOICES actually calculate a single voiceController sound. They + do basic voiceController handling like ADSR, pitch and the unevitable + click and percussion effects. + + A NOTEMASTER instantiates as many voiceController class objects as needed + for the current instrument. The numbers are tunable in "Globals.h", + definition "NUMOFVOICES". It handles all incoming events like note + on and off, all notes off, pedal, pitch bend and so on. The events + will then be assigned to the corresponding voices. The noteController + assigns a specific wavetable to each voiceController. Only active voices + are handled by the noteController - that's the main reason why the CPU + meter goes up when you hold more notes. The positive effect is: The + meter goes down if you use less voices... +*/ +#include "noteController.h" +#include +#include +#include + +// -------- helper function +char* noteController::note2str(long note) +{ + static char notestr[4]; + int octave = int(note / 12); + switch (note % 12) + { + case 0: + sprintf(notestr, "C%1d", octave); + break; + case 1: + sprintf(notestr, "C#%1d", octave); + break; + case 2: + sprintf(notestr, "D%1d", octave); + break; + case 3: + sprintf(notestr, "D#%1d", octave); + break; + case 4: + sprintf(notestr, "E%1d", octave); + break; + case 5: + sprintf(notestr, "F%1d", octave); + break; + case 6: + sprintf(notestr, "F#%1d", octave); + break; + case 7: + sprintf(notestr, "G%1d", octave); + break; + case 8: + sprintf(notestr, "G#%1d", octave); + break; + case 9: + sprintf(notestr, "A%1d", octave); + break; + case 10: + sprintf(notestr, "A#%1d", octave); + break; + case 11: + sprintf(notestr, "B%1d", octave); + break; + } + return(notestr); +} + +noteController::noteController(int number) +{ + my_samplerate = 44100; + pitch = next_pitch = 1; + my_percussion = -1; + if (number < 1) + number = 1; + if (number > MAXVOICES) + number = MAXVOICES; + + for (x = 0; x <= MAXVOICES; x++) + voices[x] = NULL; + + for (x = 0; x <= number; x++) + { + voices[x] = new voiceController(); + if (voices[x] != NULL) + { + age[x] = 0; + chan[x] = 15; + voices[x]->reset(); + voices[x]->set_samplerate(my_samplerate); + volume[x] = 1; + } + } + + numofvoices = number; +} + +noteController::~noteController() +{ + for (x = 0; x < MAXVOICES; x++) + if (voices[x] != NULL) + voices[x]->~voiceController(); +} + +void noteController::set_numofvoices(int number) +{ + // we create one additional voiceController for channel 2 (bass pedal) + if (number < 1) + number = 1; + if (number > MAXVOICES) + number = MAXVOICES; + for (x = 0; x <= MAXVOICES; x++) + { + if (voices[x] != NULL) + { + voices[x]->~voiceController(); + } + voices[x] = NULL; + age[x] = 0; + } + for (x = 0; x <= number; x++) + { + voices[x] = new voiceController(); + if (voices[x] != NULL) + { + age[x] = 0; + chan[x] = 15; + voices[x]->reset(); + voices[x]->set_samplerate(my_samplerate); + voices[x]->set_percussion(my_percussion, my_perc_multiplier, my_percfade); + volume[x] = 1; + } + } + numofvoices = number; +} + +void noteController::note_on(long note, long velocity, float* table, int size1, int channel, bool percenable, float click, float sustain) +{ + /* + The most interesting part here is the note priority and "stealing" + algorithm. We do it this way: + If a new note on event is received we look for an idle voiceController. If + there's none available we choose the oldest active voiceController and let it + perform a fast note off followed by a note on. This "fast retrigger" + is entirely calculated by the voiceController itself. + + "Mono" mode is defined by numofvoices=1. + */ + int maxpos = 0, newpos; + unsigned long maxage; + + note -= 12; + + if (note < 0) + return; + if (note > 128) + return; + + if (channel == 2) + { + newpos = numofvoices; // reserved voiceController for bass pedal (channel 2) + } + else + { + maxage = 0; + newpos = -1; + maxpos = 0; + + // calculate newpos - the voiceController number to produce the note + for (x = 0; x < numofvoices; x++) + { + if (voices[x] == NULL) + continue; + + // do we have an existing note? + // -> retrigger + if (voices[x]->get_active() && voices[x]->check_note(note) && chan[x] == (unsigned char)channel) + { + newpos = x; + age[x] = 0; + } + + if (voices[x]->get_active()) + { + // age all active voices + age[x]++; + + // let maxpos hold number of oldest voiceController + if (age[x] > maxage) + { + maxpos = x; + maxage = age[x]; + } + } + else if (newpos == -1) // voiceController is not active. If we don't have + // to retrigger - this is our voiceController! + newpos = x; + } + + if (newpos == -1) // no free voiceController and nothing to retrigger + newpos = maxpos; // -> choose oldest voiceController + } + + // let the voiceController play the note. Fast retrigger is handled by the voiceController. + voices[newpos]->note_on(note, velocity, table, size1, pitch, percenable, click, sustain); + age[newpos] = 0; + if (channel > 0 && channel < 3) + chan[newpos] = (unsigned char)channel; + else + chan[newpos] = 0; +} + +void noteController::note_off(long note, int channel) +{ + note -= 12; + + if (note < 0) + return; + + if (channel == 2) + { + if (voices[numofvoices]->check_note(note)) + voices[numofvoices]->note_off(note); + } + else + { + for (x = 0; x < numofvoices; x++) + { + if (chan[x] == (unsigned char)channel && voices[x]->check_note(note)) + { + voices[x]->note_off(note); + age[x] = 0; + } + } + } +} + +float* noteController::clock() +{ + output[0] = output[1] = output[2] = 0; + for (x = 0; x <= numofvoices; x++) + if (chan[x] < 3) + output[chan[x]] += volume[chan[x]] * voices[x]->clock(); + return(output); +} + +void noteController::all_notes_off() +{ + pitch = next_pitch = 1; + for (x = 0; x <= numofvoices; x++) + { + voices[x]->force_off(); + age[x] = 0; + } +} + +void noteController::set_pedal(int pedal, int channel) +{ + bool my_pedal; + if (pedal < 64) + my_pedal = false; + else + my_pedal = true; + for (x = 0; x <= numofvoices; x++) + voices[x]->set_pedal(my_pedal); +} + +void noteController::set_samplerate(float samplerate) +{ + my_samplerate = samplerate; + for (x = 0; x <= numofvoices; x++) + voices[x]->set_samplerate(samplerate); +} + +void noteController::set_percussion(float percussion, float perc_multiplier, float percfade) +{ + my_percussion = percussion; // memorize percussion values + my_perc_multiplier = perc_multiplier; + my_percfade = percfade; + + for (x = 0; x < numofvoices; x++) + voices[x]->set_percussion(percussion, perc_multiplier, percfade); + + voices[numofvoices]->set_percussion(percussion * .3f, perc_multiplier, percfade); +} + +void noteController::set_pitch(float pitch, int channel) +{ + this->pitch = pitch; + for (x = 0; x <= numofvoices; x++) + { + if (chan[x] == channel) + voices[x]->set_pitch(pitch); + } +} + +void noteController::set_volume(float vol, int channel) +{ + volume[channel] = vol; +} + +void noteController::reset() +{ + for (x = 0; x <= numofvoices; x++) + voices[x]->reset(); +} + +void noteController::suspend() +{ + for (x = 0; x <= numofvoices; x++) + voices[x]->suspend(); +} + +void noteController::resume() +{ + for (x = 0; x <= numofvoices; x++) + voices[x]->resume(); +} diff --git a/AZR3_vst2.4/noteController.h b/AZR3_vst2.4/noteController.h new file mode 100644 index 0000000..f8a3890 --- /dev/null +++ b/AZR3_vst2.4/noteController.h @@ -0,0 +1,34 @@ +#pragma once +#include "voiceController.h" + +class noteController +{ +public: + noteController(int number); // Anzahl der Stimmen + ~noteController(); + static char* note2str(long note); + void set_numofvoices(int number); + void note_on(long note, long velocity, float *table, int size1, int channel, bool percenable, float click, float sustain); + void all_notes_off(); + float *clock(); + void note_off(long note, int channel); + void set_pedal(int pedal, int channel); + void set_percussion(float percussion,float perc_multiplier,float percfade); + void set_samplerate(float samplerate); + void set_pitch(float pitch, int channel); + void set_volume(float vol, int channel); + void reset(); + void suspend(); + void resume(); +private: + voiceController *voices[MAXVOICES+1]; + int numofvoices; + unsigned long age[MAXVOICES]; + unsigned char chan[MAXVOICES]; + float volume[MAXVOICES]; + float output[16]; + int x; + float pitch,next_pitch; + + float my_click,my_percussion,my_perc_multiplier,my_percfade,my_samplerate; +}; diff --git a/AZR3_vst2.4/parameterConversions.cpp b/AZR3_vst2.4/parameterConversions.cpp new file mode 100644 index 0000000..1646f1f --- /dev/null +++ b/AZR3_vst2.4/parameterConversions.cpp @@ -0,0 +1,50 @@ +#include "parameterConversions.h" + +void parameterConversions::convert_bendrange(float value, char* string) +{ + sprintf(string, " %2d ", int(value * 12)); +} + +void parameterConversions::convert_tone(float value, char* string) +{ + sprintf(string, "%4.0f", 300 + 3500 * value); +} + +void parameterConversions::convert_speed(float value, char* string) +{ + sprintf(string, " %2.1f", 10 * value); + if (!strcmp(string, " 10.0")) + sprintf(string, " 10.0"); +} + +void parameterConversions::convert_perc(float value, char* string) +{ + + int v; + v = (int)(value * 10); + if (v < 1) + sprintf(string, " 0"); + else if (v < 2) + sprintf(string, " 16"); + else if (v < 3) + sprintf(string, " 8"); + else if (v < 4) + sprintf(string, " 5.33"); + else if (v < 5) + sprintf(string, " 4"); + else if (v < 6) + sprintf(string, " 2.66"); + else if (v < 7) + sprintf(string, " 2"); + else if (v < 8) + sprintf(string, " 1.6"); + else if (v < 9) + sprintf(string, " 1.36"); + else + sprintf(string, " 1"); +} + +void parameterConversions::convert_shape(float value, char* string) +{ + sprintf(string, " %d ", int(value * (NUM_OF_TONEWHEEL_SHAPES - 1)) + 1); +} diff --git a/AZR3_vst2.4/parameterConversions.h b/AZR3_vst2.4/parameterConversions.h new file mode 100644 index 0000000..8a1b87d --- /dev/null +++ b/AZR3_vst2.4/parameterConversions.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include +#include + +#include "Globals.h" + +class parameterConversions +{ + +public: + static void parameterConversions::convert_bendrange(float value, char* string); + static void parameterConversions::convert_tone(float value, char* string); + static void parameterConversions::convert_speed(float value, char* string); + static void parameterConversions::convert_perc(float value, char* string); + static void parameterConversions::convert_shape(float value, char* string); +}; diff --git a/AZR3_vst2.4/res_azr3.aps b/AZR3_vst2.4/res_azr3.aps new file mode 100644 index 0000000..ac98373 Binary files /dev/null and b/AZR3_vst2.4/res_azr3.aps differ diff --git a/AZR3_vst2.4/res_azr3.netmodule b/AZR3_vst2.4/res_azr3.netmodule new file mode 100644 index 0000000..3dc5648 Binary files /dev/null and b/AZR3_vst2.4/res_azr3.netmodule differ diff --git a/AZR3_vst2.4/res_azr3.rc b/AZR3_vst2.4/res_azr3.rc new file mode 100644 index 0000000..7c96a9a --- /dev/null +++ b/AZR3_vst2.4/res_azr3.rc @@ -0,0 +1,132 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_cknob BITMAP "Resources/cknob.bmp" + +IDB_vonoff BITMAP "Resources/vonoff.bmp" + +IDB_dbbrown BITMAP "Resources/dbbrown.bmp" + +IDB_dbwhite BITMAP "Resources/dbwhite.bmp" + +IDB_inside BITMAP "Resources/inside.bmp" + +IDB_miniledred BITMAP "Resources/miniledred.bmp" + +IDB_minioffon BITMAP "Resources/minioffon.bmp" + +IDB_yellow BITMAP "Resources/num_yellow.bmp" + +IDB_onoffgreen BITMAP "Resources/onoffgreen.bmp" + +IDB_dbblack BITMAP "Resources/dbblack.bmp" + +IDB_panelfx BITMAP "Resources/panelfx.bmp" + +IDB_panelvoice BITMAP "Resources/panelvoice.bmp" + +IDB_vu BITMAP "Resources/make a change.bmp" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,0,0,0 + PRODUCTVERSION 2,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040704b0" + BEGIN + VALUE "CompanyName", "Rumpelrausch Täips" + VALUE "FileDescription", "VST plugin AZR3" + VALUE "FileVersion", "2.0.0.0" + VALUE "InternalName", "AZR3_vst2.4" + VALUE "LegalCopyright", "Copyright (C) 2021" + VALUE "OriginalFilename", "AZR3" + VALUE "ProductName", "AZR3" + VALUE "ProductVersion", "2.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x407, 1200 + END +END + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/AZR3_vst2.4/resource.h b/AZR3_vst2.4/resource.h new file mode 100644 index 0000000..ba85763 --- /dev/null +++ b/AZR3_vst2.4/resource.h @@ -0,0 +1,50 @@ +//{{NO_DEPENDENCIES}} +// Von Microsoft Visual C++ generierte Includedatei. +// Verwendet durch res_azr3.rc +// +#define BM_KNOPF1 104 +#define BM_PANEL 106 +#define BM_S_OFFON 107 +#define BM_135 108 +#define BM_1 109 +#define BM_16 110 +#define BM_223 111 +#define BM_2 112 +#define BM_4 113 +#define BM_513 114 +#define BM_8 115 +#define BM_M_OFFON 116 +#define BM_MIKRO 117 +#define BM_113 118 +#define BM_DIGITS 119 +#define BM_MIC 121 +#define BM_KNOPF2 125 +#define BM_INSIDE 126 +#define BM_MINI_OFFON 127 +#define BM_DBBLACK 129 +#define BM_DBBROWN 130 +#define BM_DBWHITE 132 +#define IDB_cknob 135 +#define IDB_vonoff 136 +#define IDB_dbbrown 137 +#define IDB_dbwhite 138 +#define IDB_inside 139 +#define IDB_miniledred 140 +#define IDB_minioffon 141 +#define IDB_yellow 142 +#define IDB_onoffgreen 143 +#define IDB_dbblack 144 +#define IDB_panelfx 146 +#define IDB_panelvoice 147 +#define IDB_vu 148 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 149 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/AZR3_vst2.4/voiceController.cpp b/AZR3_vst2.4/voiceController.cpp new file mode 100644 index 0000000..0e6c4ef --- /dev/null +++ b/AZR3_vst2.4/voiceController.cpp @@ -0,0 +1,391 @@ +#include "voiceController.h" + +void voiceController::reset() +{ + actual_note = -1; + next_note = -1; + perc_next_note = -1; + perc_ok = false; + vca_phase = VCA_PHASE_IDLE; + output = 0; + VCA = 0; + perc = 0; + perc_vca = 0; + percmultiplier = 0; + adsr_decay = 0; + click = 0; + status = VS_IDLE; + pedal = false; + pitch = 1; + phase = phaseinc = 0; + sustain = 0; +} + +void voiceController::suspend() +{ + actual_note = -1; + next_note = -1; + perc_next_note = -1; + vca_phase = VCA_PHASE_IDLE; + output = 0; + VCA = 0; + perc_vca = 0; + status = VS_IDLE; + pitch = 1; + phase = phaseinc = 0; +} + +void voiceController::resume() +{ +} + +voiceController::voiceController() +{ + midi_scaler = (1. / 127.); + + long i; + + double k = 1.059463094359; // 12th root of 2 + double a = 6.875; // a + a *= k; // b + a *= k; // bb + a *= k; // c, frequency of midi note 0 + for (i = 0; i < 128; i++) // 128 midi notes + { + freqtab[i] = (float)a; + a *= k; + } + samplecount1 = samplecount2 = 0; + sustain = 0; + perc_ok = false; +}; + +void voiceController::set_samplerate(float samplerate) +{ + this->samplerate = samplerate; + clicklp.set_samplerate(samplerate); +} + +void voiceController::voicecalc() +{ + /* + This "scaler" stuff is important to keep timing independant from + the actual samplerate. + */ + float scaler; + scaler = samplerate / 44100; + + clickattack = .004f / scaler; + adsr_attack = .10f / scaler; + + adsr_decay = 0 / scaler; + if (sustain > 0) + adsr_release = (.0001f + .0005f * (1 - sustain)) / scaler; + else + adsr_release = .95f / scaler; + + adsr_fast_release = .03f / scaler; + + perc_decay = perc_fade * .00035f / scaler; + + perc_decay *= 3; + + samplerate_scaler = (float)((double)my_size / (double)samplerate); + phaseinc = (float)freqtab[actual_note] * samplerate_scaler * pitch; + if (perc_phase == 0) + { + // fast sine calculation, precise enough for our percussion effect + float fact = percmultiplier * freqtab[actual_note]; + while (fact > 3800) + fact *= .5f; + a = 2 * sinf(3.14159265358979f * pitch * fact / samplerate); + s0 = .5f; + s1 = 0; + } +} + +float voiceController::clock() +{ + if (status == VS_IDLE || actual_note < 0) // nothing to do... + return(0); + + output = 0; + /* + This is the part where we read a value from the assigned wavetable. + We use a very simple interpolation to determine the actual sample + value. Since we use almost pure sine waves we don't have to take care + about anti-aliasing here. The few aliasing effects we receive sound just + like those real hardware tonewheels... + */ + iphase = int(phase); + fract = phase - iphase; + y0 = my_table[iphase]; + y1 = my_table[iphase + 1]; + output = (y0 + fract * (y1 - y0)) * VCA; + + phase += phaseinc; + + /* + No, we don't use the bit mask stuff as mentioned in the SDK. + It's _not_ slower this way, and we can have random wavetable sizes. + */ + if (phase > my_size) + phase -= my_size; + + samplecount1++; + if (samplecount1 > 5) + { + samplecount1 = 0; + + if (vca_phase == VCA_PHASE_ATTACK) // attack + { + if (click <= 0) + { + VCA += adsr_attack; + } + + if (VCA > 1) + { + VCA = 1; + vca_phase = VCA_PHASE_DECAY; + } + } + else if (vca_phase == VCA_PHASE_DECAY) + { + vca_phase = VCA_PHASE_SUSTAIN; + } + else if (vca_phase == VCA_PHASE_SUSTAIN) + { + } + else if (vca_phase == VCA_PHASE_RELEASE) // release + { + if (perc > 0) + { + if (sustain == 0) + perc_phase = 3; + } + + if (click > 0 && sustain == 0) + { + static unsigned long randSeed = 22222, maxrand = (unsigned long)-1; + float rand = 0; + randSeed = (randSeed * 196314165) + 907633515; + rand = (float)randSeed / 0xffffffff; + clicklp.clock(click * rand * .3f); + noise = clicklp.bp() * clickvol * .2f; + output += noise; + } + + if (sustain > 0) + VCA -= adsr_release; + else + VCA *= adsr_release; + + if (VCA <= 0.001f) + { + VCA = 0; + actual_note = -1; + phase = 0; + vca_phase = VCA_PHASE_IDLE; + output = 0; + status = VS_IDLE; + } + } + else if (vca_phase == VCA_PHASE_FAST_RELEASE) // fast release + { + VCA -= adsr_fast_release; + if (VCA <= 0) + { + VCA = 0; + actual_note = -1; + if (next_note >= 0) + { + actual_note = next_note; + next_note = -1; + vca_phase = VCA_PHASE_ATTACK; + phase = 0; + perc_phase = 0; + this->voicecalc(); + if (perc_ok && perc > 0 && percmultiplier > 0) // retrigger percussion + { + perc_phase = 1; + perc_vca = 0; + } + } + else + status = VS_IDLE; + } + } + } + if (vca_phase == VCA_PHASE_ATTACK && click > 0) + { + static unsigned long randSeed = 22222, maxrand = (unsigned long)-1; + float rand = 0; + float mattack = 0; + if (mattack < 1) + mattack = VCA * 8; + if (mattack > 1) + mattack = 1; + randSeed = (randSeed * 196314165) + 907633515; + rand = (float)randSeed / 0xffffffff; + clicklp.clock(click * rand * .3f); + noise = clicklp.bp(); + noise *= clickvol; + output = mattack * (2 - VCA) * (output + noise); + VCA += clickattack; + } + + if (perc_ok && perc_phase > 0) + { + s0 = s0 - a * s1; // calculate sine wave + s1 = s1 + a * s0; // + output += perc * s0 * perc_vca * perc_vca; + + samplecount2++; + if (samplecount2 > 5) + { + samplecount2 = 0; + if (perc_phase == 1) // percussion attack + { + perc_vca += adsr_attack; + if (perc_vca >= 1) + perc_phase = 2; // switch to percussion decay + } + else if (perc_phase == 2) // percussion decay + { + perc_vca -= perc_decay; + if (perc_vca <= 0) + { + perc_vca = 0; + perc_phase = 0; // percussion finished + } + } + else if (perc_phase == 3) // percussion fast release + { + perc_vca -= adsr_fast_release; + if (perc_vca <= 0) + { + perc_vca = 0; + perc_phase = 0; // percussion finished + } + } + } + } + + output = DENORMALIZE(output); + return(output); +} + +long voiceController::get_note() +{ + return(actual_note); +} + +bool voiceController::check_note(long note) +{ + if (note == actual_note || note == next_note) + return(true); + else + return(false); +} + +bool voiceController::get_active() +{ + if (status == VS_IDLE) + return(false); + else + return(true); +} + +void voiceController::note_on(long note, long velocity, float* table, int size, float pitch, bool percenable, float sclick, float sust) +{ + my_table = table; + my_size = size; + click = sclick; + perc_ok = percenable; + sustain = sust; + + if (note >= 0 && note < 128) + { + if (click > 0) + { + float clickfreq = (freqtab[note] + 70) * 16; + if (clickfreq > 5000) + clickfreq = 5000; + //clicklp.setparam(3000+clickfreq*.3f,.1f,samplerate); + clicklp.setparam(clickfreq, .1f, samplerate); + clickvol = note * note * .0008f; + } + if (actual_note >= 0) // fast retrigger + { + next_note = note; + vca_phase = VCA_PHASE_FAST_RELEASE; + perc_phase = 3; + } + else // normal note on + { + VCA = 0; + phase = 0; + phaseinc = 0; + vca_phase = VCA_PHASE_ATTACK; + + actual_note = note & 0x7f; + perc_phase = 0; + this->voicecalc(); + perc_phase = 1; + } + + status = VS_PLAYING; + } + else + note_off(-1); +} + +void voiceController::note_off(long note) +{ + if (note == actual_note && next_note >= 0) + { + vca_phase = VCA_PHASE_FAST_RELEASE; + return; + } + + if (!pedal) + vca_phase = VCA_PHASE_RELEASE; + else + status = VS_WAIT_PUP; + +} + +void voiceController::force_off() +{ + next_note = -1; + vca_phase = VCA_PHASE_FAST_RELEASE; +} + +void voiceController::set_pedal(bool pedal) +{ + if (pedal != this->pedal) + { + if (!pedal) + if (status == VS_WAIT_PUP) + vca_phase = VCA_PHASE_RELEASE; + + this->pedal = pedal; + } +} + +void voiceController::set_percussion(float percussion, float perc_multiplier, float percfade) +{ + if (percussion >= 0) + perc = percussion * 2; + if (perc_multiplier >= 0) + percmultiplier = perc_multiplier; + if (percfade >= 0) + perc_fade = 1 - percfade + .5f; +} + +void voiceController::set_pitch(float pitch) +{ + this->pitch = pitch; + this->voicecalc(); +} diff --git a/AZR3_vst2.4/voiceController.h b/AZR3_vst2.4/voiceController.h new file mode 100644 index 0000000..a637a09 --- /dev/null +++ b/AZR3_vst2.4/voiceController.h @@ -0,0 +1,89 @@ +#pragma once +#include "FX/fxGenericFilter.h" +#include + +#define MAXVOICES 32 + +// voiceController stati (status) +#define VS_IDLE 0 +#define VS_PLAYING 1 +#define VS_WAIT_PUP 2 // has note_off and waits for pedal up + +// VCA phases (vca_phase) +#define VCA_PHASE_IDLE 0 +#define VCA_PHASE_ATTACK 1 // attack +#define VCA_PHASE_DECAY 2 // decay +#define VCA_PHASE_SUSTAIN 3 // sustain = main phase +#define VCA_PHASE_RELEASE 4 // release +#define VCA_PHASE_FAST_RELEASE 5 // fast release +#define VCA_PHASE_FAST_ATTACK 6 // fast attack + +#include + +char* note2str(long note); + +class voiceController +{ +public: + voiceController(); + ~voiceController() {} + float clock(); + void reset(); + void suspend(); + void resume(); + void note_on(long note, long velocity, float* table, int size, float pitch, bool percenable, float sclick, float sust); + void note_off(long note); + void force_off(); + long get_note(); + bool check_note(long note); + bool get_active(); + void set_samplerate(float samplerate); + void set_attack(float attack); + void set_decay(float decay); + void set_release(float release); + void set_pedal(bool pedal); + void set_percussion(float percussion, float perc_multiplier, float percfade); + void set_pitch(float pitch); + void voicecalc(); +private: + unsigned char samplecount1, samplecount2; + int status; + int iphase; + float y0, y1, fract; + float samplerate_scaler; // Anpassung der Wavetable-Logik an Samplerate + float phase; // Position in der Wavetable + float phaseinc; // increment for phase + float output; // Ausgang + float click; // click strength + float hertz, a, s0, s1; // percussion sine values + float percmultiplier; // percussion octave multiplier + float perc; // percussion volume + bool perc_ok; + float perc_decay; + float perc_vca; + int perc_phase; + float perc_attack; + float perc_fade; + long actual_note; // Note-Daten + long next_note; // Vorbesetzung von actual_note. + long perc_next_note; + float* my_table; // die Wavetable + long mask, my_size; // Maske und Größe der Wavetable + float samplerate; + double midi_scaler; // Umrechung Midi->float-Faktor [0..1] + float freqtab[128]; // Umrechnung Midi->Frequenz + float noise; + float clickattack; + float clickvol; + float adsr_attack; + float adsr_decay; + float adsr_sustain; + float adsr_release; + float adsr_fast_release; + float sustain; + float VCA; // VCA-Faktor. Wird durch attack und release beeinflußt + int vca_phase; // 1:Attack 2:Release + bool pedal; // Pedalzustand + float pitch; + fxGenericFilter clicklp; +}; diff --git a/AZR3_vst2.4/voice_classes_cpp b/AZR3_vst2.4/voice_classes_cpp new file mode 100644 index 0000000..1e6a781 --- /dev/null +++ b/AZR3_vst2.4/voice_classes_cpp @@ -0,0 +1,3 @@ +-- E:\Dokumente\VC++\flp2_2.5\voice_classes.cpp : E:\Dokumente\VC++\flp4_0.1\voice_classes.cpp -- includes left-only,right-only,differing files +.\voice_classes.cpp different (E:\Dokumente\VC++\flp4_0.1\voice_classes.cpp is more recent) c9997fd2 45d1da9b +-- 1 files listed diff --git a/AZR3_vst2.4/vstProgram.h b/AZR3_vst2.4/vstProgram.h new file mode 100644 index 0000000..c406404 --- /dev/null +++ b/AZR3_vst2.4/vstProgram.h @@ -0,0 +1,10 @@ +#pragma once +#include "Globals.h" + +class vstProgram +{ + friend class effectMain; + private: + float p[kNumParams]; + char name[24]; +};