From 288afd93711e0a2a7ca4841417752f9d037b92d4 Mon Sep 17 00:00:00 2001 From: nidefawl Date: Thu, 2 Jun 2016 20:00:10 +0200 Subject: [PATCH] Add code --- Debug.cpp | 187 +++++++++ FSM_KickXP.vcxproj | 282 +++++++++++++ FSM_KickXP.vcxproj.filters | 27 ++ FSM_KickXP.vcxproj.user | 22 + plugin.cpp | 834 +++++++++++++++++++++++++++++++++++++ plugin.h | 249 +++++++++++ vstplug.def | 3 + 7 files changed, 1604 insertions(+) create mode 100644 Debug.cpp create mode 100644 FSM_KickXP.vcxproj create mode 100644 FSM_KickXP.vcxproj.filters create mode 100644 FSM_KickXP.vcxproj.user create mode 100644 plugin.cpp create mode 100644 plugin.h create mode 100644 vstplug.def diff --git a/Debug.cpp b/Debug.cpp new file mode 100644 index 0000000..5dc1045 --- /dev/null +++ b/Debug.cpp @@ -0,0 +1,187 @@ + +#include "plugin.h" +#include +using namespace std; +#ifdef DEBUG +#ifdef DEBUG_CONSOLE +void FSM_VST_Plugin::startConsoleWin(int width, int height, char* fname) +{ + + + int hConHandle; + long lStdHandle; + FILE *fp; + + // Try to attach to a console + AllocConsole(); + SetConsoleTitle("Debug Window"); + hout = GetStdHandle(STD_OUTPUT_HANDLE); + DeleteMenu(GetSystemMenu(GetConsoleWindow(), 0), SC_CLOSE, MF_BYCOMMAND); + COORD co = {width,height}; + SetConsoleScreenBufferSize(hout, co); + // redirect unbuffered STDOUT to the console + lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + fp = _fdopen( hConHandle, "w" ); + *stdout = *fp; + setvbuf( stdout, NULL, _IONBF, 0 ); + + // redirect unbuffered STDIN to the console + lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + fp = _fdopen( hConHandle, "r" ); + *stdin = *fp; + setvbuf( stdin, NULL, _IONBF, 0 ); + + // redirect unbuffered STDERR to the console + lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + fp = _fdopen( hConHandle, "w" ); + *stderr = *fp; + setvbuf( stderr, NULL, _IONBF, 0 ); + fprintf(stdout, "Test output to stdout\n"); + fprintf(stderr, "Test output to stderr\n"); +} +#endif // DEBUG_CONSOLE +#ifdef DISPATCHER_DEBUG_TRACE + +//----------------------------------------------------------------------------------------------------------------- +VstIntPtr FSM_VST_Plugin::dispatcher (VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) +{ + std::string debug = ""; + switch (opcode) { + ///< no arguments @see AudioEffect::open + case effOpen: debug = "effOpen"; break; + ///< no arguments @see AudioEffect::close + case effClose: debug = "effClose"; break; + ///< [value]: new program number @see AudioEffect::setProgram + case effSetProgram: debug = "effSetProgram"; break; + ///< [return value]: current program number @see AudioEffect::getProgram + case effGetProgram: debug = "effGetProgram"; break; + ///< [ptr]: char* with new program name, limited to #kVstMaxProgNameLen @see AudioEffect::setProgramName + case effSetProgramName: debug = "effSetProgramName"; break; + ///< [ptr]: char buffer for current program name, limited to #kVstMaxProgNameLen @see AudioEffect::getProgramName + case effGetProgramName: debug = "effGetProgramName"; break; + ///< [ptr]: char buffer for parameter label, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterLabel + case effGetParamLabel: debug = "effGetParamLabel"; break; + ///< [ptr]: char buffer for parameter display, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterDisplay + //case effGetParamDisplay: debug = "effGetParamDisplay"; break; + ///< [ptr]: char buffer for parameter name, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterName + case effGetParamName: debug = "effGetParamName"; break; + ///< [opt]: new sample rate for audio processing @see AudioEffect::setSampleRate + case effSetSampleRate: debug = "effSetSampleRate"; break; + ///< [value]: new maximum block size for audio processing @see AudioEffect::setBlockSize + case effSetBlockSize: debug = "effSetBlockSize"; break; + ///< [value]: 0 means "turn off", 1 means "turn on" @see AudioEffect::suspend @see AudioEffect::resume + case effMainsChanged: debug = "effMainsChanged"; break; + ///< [ptr]: #ERect** receiving pointer to editor size @see ERect @see AEffEditor::getRect + case effEditGetRect: debug = "effEditGetRect"; break; + ///< [ptr]: system dependent Window pointer, e.g. HWND on Windows @see AEffEditor::open; + case effEditOpen: debug = "effEditOpen"; break; + ///< no arguments @see AEffEditor::close + case effEditClose: debug = "effEditClose"; break; + ///< no arguments @see AEffEditor::idle + case effEditIdle: debug = ""; break; + ///< [ptr]: void** for chunk data address [index]: 0 for bank, 1 for program @see AudioEffect::getChunk + case effGetChunk: debug = "effGetChunk"; break; + ///< [ptr]: chunk data [value]: byte size [index]: 0 for bank, 1 for program @see AudioEffect::setChunk + case effSetChunk: debug = ""; break; + ///< [ptr]: #VstEvents* @see AudioEffectX::processEvents + case effProcessEvents: debug = "effProcessEvents"; break; + ///< [index]: parameter index [return value]: 1=true, 0=false @see AudioEffectX::canParameterBeAutomated + case effCanBeAutomated: debug = "effCanBeAutomated"; break; + ///< [index]: parameter index [ptr]: parameter string [return value]: true for success @see AudioEffectX::string2parameter + case effString2Parameter: debug = "effString2Parameter"; break; + ///< [index]: program index [ptr]: buffer for program name, limited to #kVstMaxProgNameLen [return value]: true for success @see AudioEffectX::getProgramNameIndexed + case effGetProgramNameIndexed: debug = "effGetProgramNameIndexed"; break; + ///< [index]: input index [ptr]: #VstPinProperties* [return value]: 1 if supported @see AudioEffectX::getInputProperties + case effGetInputProperties: debug = "effGetInputProperties"; break; + ///< [index]: output index [ptr]: #VstPinProperties* [return value]: 1 if supported @see AudioEffectX::getOutputProperties + case effGetOutputProperties: debug = "effGetOutputProperties"; break; + ///< [return value]: category @see VstPlugCategory @see AudioEffectX::getPlugCategory + case effGetPlugCategory: debug = "effGetPlugCategory"; break; + ///< [ptr]: #VstAudioFile array [value]: count [index]: start flag @see AudioEffectX::offlineNotify + case effOfflineNotify: debug = "effOfflineNotify"; break; + ///< [ptr]: #VstOfflineTask array [value]: count @see AudioEffectX::offlinePrepare + case effOfflinePrepare: debug = "effOfflinePrepare"; break; + ///< [ptr]: #VstOfflineTask array [value]: count @see AudioEffectX::offlineRun + case effOfflineRun: debug = "effOfflineRun"; break; + ///< [ptr]: #VstVariableIo* @see AudioEffectX::processVariableIo + case effProcessVarIo: debug = "effProcessVarIo"; break; + ///< [value]: input #VstSpeakerArrangement* [ptr]: output #VstSpeakerArrangement* @see AudioEffectX::setSpeakerArrangement + case effSetSpeakerArrangement: debug = "effSetSpeakerArrangement"; break; + ///< [value]: 1 = bypass, 0 = no bypass @see AudioEffectX::setBypass + case effSetBypass: debug = "effSetBypass"; break; + ///< [ptr]: buffer for effect name, limited to #kVstMaxEffectNameLen @see AudioEffectX::getEffectName + case effGetEffectName: debug = "effGetEffectName"; break; + ///< [ptr]: buffer for effect vendor string, limited to #kVstMaxVendorStrLen @see AudioEffectX::getVendorString + case effGetVendorString: debug = "effGetVendorString"; break; + ///< [ptr]: buffer for effect vendor string, limited to #kVstMaxProductStrLen @see AudioEffectX::getProductString + case effGetProductString: debug = "effGetProductString"; break; + ///< [return value]: vendor-specific version @see AudioEffectX::getVendorVersion + case effGetVendorVersion: debug = "effGetVendorVersion"; break; + ///< no definition, vendor specific handling @see AudioEffectX::vendorSpecific + case effVendorSpecific: debug = "effVendorSpecific"; break; + ///< [ptr]: "can do" string [return value]: 0: "don't know" -1: "no" 1: "yes" @see AudioEffectX::canDo# + case effCanDo: debug = "effCanDo"; break; + ///< [return value]: tail size (for example the reverb time of a reverb plug-in); 0 is default (return 1 for 'no tail') + case effGetTailSize: debug = "effGetTailSize"; break; + ///< [index]: parameter index [ptr]: #VstParameterProperties* [return value]: 1 if supported @see AudioEffectX::getParameterProperties + case effGetParameterProperties: debug = "effGetParameterProperties"; break; + ///< [return value]: VST version @see AudioEffectX::getVstVersion + case effGetVstVersion: debug = "effGetVstVersion"; break; + ///< \deprecated deprecated in VST 2.4 + // DECLARE_VST_DEPRECATED (effGetVu) + // DECLARE_VST_DEPRECATED (effEditTop) + // DECLARE_VST_DEPRECATED (effEditSleep) + // DECLARE_VST_DEPRECATED (effIdentify) + // DECLARE_VST_DEPRECATED (effGetNumProgramCategories) + // DECLARE_VST_DEPRECATED (effCopyProgram) + // DECLARE_VST_DEPRECATED (effConnectInput) + // DECLARE_VST_DEPRECATED (effConnectOutput) + // DECLARE_VST_DEPRECATED (effEditDraw) + // DECLARE_VST_DEPRECATED (effEditMouse) + // DECLARE_VST_DEPRECATED (effEditKey) + // DECLARE_VST_DEPRECATED (effGetCurrentPosition) + // DECLARE_VST_DEPRECATED (effGetDestinationBuffer) + // DECLARE_VST_DEPRECATED (effSetBlockSizeAndSampleRate) + // DECLARE_VST_DEPRECATED (effGetErrorText) + // DECLARE_VST_DEPRECATED (effIdle) + // DECLARE_VST_DEPRECATED (effGetIcon) + // DECLARE_VST_DEPRECATED (effSetViewPosition) + // DECLARE_VST_DEPRECATED (effKeysRequired) +#if VST_2_1_EXTENSIONS + case effEditKeyDown: debug = "effEditKeyDown"; break; ///< [index]: ASCII character [value]: virtual key [opt]: modifiers [return value]: 1 if key used @see AEffEditor::onKeyDown + case effEditKeyUp: debug = "effEditKeyUp"; break; ///< [index]: ASCII character [value]: virtual key [opt]: modifiers [return value]: 1 if key used @see AEffEditor::onKeyUp + case effSetEditKnobMode: debug = "effSetEditKnobMode"; break; ///< [value]: knob mode 0: circular, 1: circular relativ, 2: linear (CKnobMode in VSTGUI) @see AEffEditor::setKnobMode + case effGetMidiProgramName: debug = "effGetMidiProgramName"; break; ///< [index]: MIDI channel [ptr]: #MidiProgramName* [return value]: number of used programs, 0 if unsupported @see AudioEffectX::getMidiProgramName + case effGetCurrentMidiProgram: debug = "effGetCurrentMidiProgram"; break; ///< [index]: MIDI channel [ptr]: #MidiProgramName* [return value]: index of current program @see AudioEffectX::getCurrentMidiProgram + case effGetMidiProgramCategory: debug = "effGetMidiProgramCategory"; break; ///< [index]: MIDI channel [ptr]: #MidiProgramCategory* [return value]: number of used categories, 0 if unsupported @see AudioEffectX::getMidiProgramCategory + case effHasMidiProgramsChanged: debug = "effHasMidiProgramsChanged"; break; ///< [index]: MIDI channel [return value]: 1 if the #MidiProgramName(s) or #MidiKeyName(s) have changed @see AudioEffectX::hasMidiProgramsChanged + case effGetMidiKeyName: debug = "effGetMidiKeyName"; break; ///< [index]: MIDI channel [ptr]: #MidiKeyName* [return value]: true if supported, false otherwise @see AudioEffectX::getMidiKeyName + case effBeginSetProgram: debug = "effBeginSetProgram"; break; ///< no arguments @see AudioEffectX::beginSetProgram + case effEndSetProgram: debug = "effEndSetProgram"; break; ///< no arguments @see AudioEffectX::endSetProgram +#endif // VST_2_1_EXTENSIONS +#if VST_2_3_EXTENSIONS + case effGetSpeakerArrangement: debug = "effGetSpeakerArrangement"; break; ///< [value]: input #VstSpeakerArrangement* [ptr]: output #VstSpeakerArrangement* @see AudioEffectX::getSpeakerArrangement + case effShellGetNextPlugin: debug = "effShellGetNextPlugin"; break; ///< [ptr]: buffer for plug-in name, limited to #kVstMaxProductStrLen [return value]: next plugin's uniqueID @see AudioEffectX::getNextShellPlugin + case effStartProcess: debug = "effStartProcess"; break; ///< no arguments @see AudioEffectX::startProcess + case effStopProcess: debug = "effStopProcess"; break; ///< no arguments @see AudioEffectX::stopProcess + case effSetTotalSampleToProcess: debug = "effSetTotalSampleToProcess"; break; ///< [value]: number of samples to process, offline only! @see AudioEffectX::setTotalSampleToProcess + case effSetPanLaw: debug = "effSetPanLaw"; break; ///< [value]: pan law [opt]: gain @see VstPanLawType @see AudioEffectX::setPanLaw + case effBeginLoadBank: debug = "effBeginLoadBank"; break; ///< [ptr]: #VstPatchChunkInfo* [return value]: -1: bank can't be loaded, 1: bank can be loaded, 0: unsupported @see AudioEffectX::beginLoadBank + case effBeginLoadProgram: debug = "effBeginLoadProgram"; break; ///< [ptr]: #VstPatchChunkInfo* [return value]: -1: prog can't be loaded, 1: prog can be loaded, 0: unsupported @see AudioEffectX::beginLoadProgram +#endif // VST_2_3_EXTENSIONS +#if VST_2_4_EXTENSIONS + case effSetProcessPrecision: debug = "effSetProcessPrecision"; break; ///< [value]: @see VstProcessPrecision @see AudioEffectX::setProcessPrecision + case effGetNumMidiInputChannels: debug = "effGetNumMidiInputChannels"; break; ///< [return value]: number of used MIDI input channels (1-15) @see AudioEffectX::getNumMidiInputChannels + case effGetNumMidiOutputChannels: debug = "effGetNumMidiOutputChannels"; break; ///< [return value]: number of used MIDI output channels (1-15) @see AudioEffectX::getNumMidiOutputChannels +#endif // VST_2_4_EXTENSIONS + } + if (!debug.empty()) { + printf("%s\n", debug.c_str()); + } + return AudioEffectX::dispatcher(opcode, index, value, ptr, opt); +} +#endif // DISPATCHER_DEBUG_TRACE +#endif // DEBUG diff --git a/FSM_KickXP.vcxproj b/FSM_KickXP.vcxproj new file mode 100644 index 0000000..6600617 --- /dev/null +++ b/FSM_KickXP.vcxproj @@ -0,0 +1,282 @@ + + + + + Debug_UNIT + Win32 + + + Debug_UNIT + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + {A16E687B-3DE3-41E4-A8E1-C6059CCB3A90} + Win32Proj + FSM_KickXP + + + + Application + true + v120 + Unicode + + + Application + true + v120 + Unicode + + + DynamicLibrary + true + v120 + NotSet + + + DynamicLibrary + true + v120 + NotSet + + + Application + false + v120 + true + Unicode + + + DynamicLibrary + false + v120 + true + NotSet + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + .dll + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\ + $(ProjectName).$(Platform) + + + false + .dll + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\ + $(ProjectName).$(Platform) + + + false + + + false + $(VC_SourcePath); + C:\Program Files (x86)\AMD APP\include\;D:\boost_1_51_0;$(IncludePath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + + + Console + true + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\$(ProjectName).x64.dll + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + + + Console + true + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\$(ProjectName).x64.dll + + + + + + + Level3 + Full + WINDOWS;_WINDOWS;WIN32;_USRDLL;_USE_MATH_DEFINES;DEBUG;DEBUG=1;_DEBUG=1;_CRT_SECURE_NO_DEPRECATE;VST_64BIT_PLATFORM;%(PreprocessorDefinitions) + C:\Users\Michael\Desktop\VSTDEV\INCLUDES\VST GUI\;C:\Users\Michael\Desktop\VSTDEV\INCLUDES\VST3 SDK\;%(AdditionalIncludeDirectories) + AnySuitable + Speed + false + Default + MultiThreadedDebugDLL + 16Bytes + false + Fast + true + All + + + Console + true + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\$(ProjectName).x64.dll + msvcrtd.lib;%(AdditionalDependencies) + false + libcmtd.lib + vstplug.def + true + true + true + false + false + + + + + + + Level3 + Full + WINDOWS;_WINDOWS;WIN32;_USRDLL;_USE_MATH_DEFINES;DEBUG;DEBUG=1;_DEBUG=1;_CRT_SECURE_NO_DEPRECATE;VST_64BIT_PLATFORM;%(PreprocessorDefinitions) + C:\Users\Michael\Desktop\VSTDEV\INCLUDES\VST GUI\;C:\Users\Michael\Desktop\VSTDEV\INCLUDES\VST3 SDK\;%(AdditionalIncludeDirectories) + AnySuitable + Speed + false + Default + MultiThreadedDebugDLL + 16Bytes + false + Fast + true + All + + + Console + true + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\$(ProjectName).x64.dll + msvcrtd.lib;%(AdditionalDependencies) + false + libcmtd.lib + vstplug.def + true + true + true + false + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;STRICT;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;VST_64BIT_PLATFORM;%(PreprocessorDefinitions) + C:\Users\Michael\Desktop\VSTDEV\INCLUDES\VST GUI\;C:\Users\Michael\Desktop\VSTDEV\INCLUDES\VST3 SDK\;%(AdditionalIncludeDirectories) + + AnySuitable + Speed + false + true + 16Bytes + false + Fast + + + Console + false + false + false + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\$(ProjectName).x64.dll + msvcrt.lib;%(AdditionalDependencies) + libcmt.lib;%(IgnoreSpecificDefaultLibraries) + vstplug.def + false + $(OutDir)$(TargetName).pdb + + + + + + \ No newline at end of file diff --git a/FSM_KickXP.vcxproj.filters b/FSM_KickXP.vcxproj.filters new file mode 100644 index 0000000..3de6924 --- /dev/null +++ b/FSM_KickXP.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + + deps + + + deps + + + deps + + + + + + + + + + + + {dd5be145-dc73-4511-a9fa-e4e4775dd620} + + + \ No newline at end of file diff --git a/FSM_KickXP.vcxproj.user b/FSM_KickXP.vcxproj.user new file mode 100644 index 0000000..7360f1f --- /dev/null +++ b/FSM_KickXP.vcxproj.user @@ -0,0 +1,22 @@ + + + + true + + + C:\Users\Michael\Desktop\VSTDEV\vsthostx64\savihost.exe + /noload /nosave /noasio /nomidi /noexc /noft -noexc -noft C:\PluginManager\configs\default\hosts\Ableton\categories\dev\FSM_KickXP.x64.dll + WindowsLocalDebugger + false + false + Auto + + + C:\Users\Michael\Desktop\VSTDEV\VST-Plugin Unit Test (x64).exe + C:\PluginManager\configs\default\hosts\Ableton\categories\dev\FSM_KickXP.x64.dll + WindowsLocalDebugger + false + false + Auto + + \ No newline at end of file diff --git a/plugin.cpp b/plugin.cpp new file mode 100644 index 0000000..9d3c8da --- /dev/null +++ b/plugin.cpp @@ -0,0 +1,834 @@ +#include +#include "plugin.h" + +#include +#include +#include +#include "plugin.h" +#include "dbglog.h" + + +SynthParameter const paraStartFrq = +{ + "StartFrq", + "Start frequency", + 1, + 240, + 99 +}; + +SynthParameter const paraEndFrq = +{ + "EndFrq", + "End frequency", + 1, + 240, + 66 +}; + +SynthParameter const paraBuzzAmt = +{ + "Buzz", + "Amount of Buzz", + 0, + 100, + 0 +}; + +SynthParameter const paraClickAmt = +{ + "Click", + "Amount of Click", + 0, + 100, + 0 +}; + +SynthParameter const paraPunchAmt = +{ + "Punch", + "Amount of Punch", + 0, + 100, + 17 +}; + +SynthParameter const paraToneDecay = +{ + "ToneDecR", + "Tone decay rate", + 1, + 240, + 104, +}; + +SynthParameter const paraToneShape = +{ + "ToneDecS", + "Tone decay shape", + 1, + 240, + 17 +}; + +SynthParameter const paraBDecay = +{ + "BuzzDecR", + "Buzz decay rate", + 1, + 240, + 69 +}; + +SynthParameter const paraCDecay = +{ + "C+P DecR", + "Click+Punch decay rate", + 1, + 240, + 164 +}; + +SynthParameter const paraDecSlope = +{ + "DecSlope", + "Amplitude decay slope", + 1, + 240, + 94 +}; + +SynthParameter const paraDecTime = +{ + "DecTime", + "Amplitude decay time", + 1, + 240, + 41 +}; + +SynthParameter const paraRelSlope = +{ + "RelSlope", + "Amplitude release slope", + 1, + 240, + 139 +}; + +SynthParameter const *synthParameters[] = +{ + ¶StartFrq, + ¶EndFrq, + ¶BuzzAmt, + ¶ClickAmt, + ¶PunchAmt, + ¶ToneDecay, + ¶ToneShape, + ¶BDecay, + ¶CDecay, + ¶DecSlope, + ¶DecTime, + ¶RelSlope, +}; + + +float to_range(float floatVal, const SynthParameter ¶m) { + float fByte = (float)param.MinValue + floatVal*(float)(param.MaxValue - param.MinValue); + return fByte < param.MinValue ? param.MinValue : fByte > param.MaxValue ? param.MaxValue : fByte; +} +float from_range(byte byteVal, const SynthParameter ¶m) { + float fByte = byteVal; + fByte = fByte - param.MinValue; + fByte = fByte / (float)(param.MaxValue - param.MinValue); + return fByte < 0.0f ? 0.0f : fByte > 1.0f ? 1.0f : fByte; +} + +typedef unsigned long int u4; +typedef struct ranctx { u4 a; u4 b; u4 c; u4 d; } ranctx; + +#define rot(x,k) (((x)<<(k))|((x)>>(32-(k)))) +u4 ranval(ranctx *x) { + u4 e = x->a - rot(x->b, 27); + x->a = x->b ^ rot(x->c, 17); + x->b = x->c + x->d; + x->c = x->d + e; + x->d = e + x->a; + return x->d; +} + +void raninit(ranctx *x, u4 seed) { + u4 i; + x->a = 0xf1ea5eed, x->b = x->c = x->d = seed; + for (i = 0; i<20; ++i) { + (void)ranval(x); + } +} +static ranctx rctx; +AudioEffect* createEffectInstance (audioMasterCallback audioMaster) +{ + return new FSM_VST_Plugin (audioMaster); +} + +void FSM_VST_Program::set(char* _name, int start, int end, + int buzz, int click, int punch, int tDecR, int tDecS, + int bDecR, int CPDecR, int ADecS, int ADecT, int ARelS) { + vst_strncpy(this->name, _name, kVstMaxProgNameLen); + bStartFrq = from_range(start, paraStartFrq); + bEndFrq = from_range(end, paraEndFrq); + bBuzzAmt = from_range(buzz, paraBuzzAmt); + bClickAmt = from_range(click, paraClickAmt); + bPunchAmt = from_range(punch, paraPunchAmt); + + bToneDecay = from_range(tDecR, paraToneDecay); + bToneShape = from_range(tDecS, paraToneShape); + + bBDecay = from_range(bDecR, paraBDecay); + bCDecay = from_range(CPDecR, paraCDecay); + bDecSlope = from_range(ADecS, paraDecSlope); + bDecTime = from_range(ADecT, paraDecTime); + bRelSlope = from_range(ARelS, paraRelSlope); +} +#define RND(x) (ranval(&rctx)%x) +FSM_VST_Plugin::FSM_VST_Plugin (audioMasterCallback audioMaster) + : AudioEffectX(audioMaster, kNumPrograms, kNumParams) +{ + + raninit(&rctx, 238947); + programs = new FSM_VST_Program[kNumPrograms]; + fVolume = 0.8f; + issetprogram = false; +#ifdef DEBUG_CONSOLE + hout = NULL; +#endif // DEBUG_CONSOLE + // initialize programs + programs[0].set("Init", 145, 50, 55, 28, 47, 30, 27, 55, 55, 1, 32, 105); + programs[1].set("Soft", 99, 66,0, 0, 17, 104, 17, 69, 164, 94, 41, 139); + for (int i = 2; i < kNumPrograms; i++) { + char presetname[16]; + sprintf_s(presetname, kVstMaxProgNameLen, "Random %i", i); + programs[i].set(presetname, + 64 + RND(64), + RND(96), + RND(100), + RND(100), + RND(100), + 1 + RND(240), + 1 + RND(240), + 1 + RND(240), + 1 + RND(240), + 1 + RND(240), + 1 + RND(240), + 1 + RND(240)); + } + setProgram(0); + + if (audioMaster) + { + setNumInputs (0); // no inputs + setNumOutputs (kNumOutputs); // 2 outputs, 1 for each oscillator + canProcessReplacing (); + isSynth (); + setUniqueID ('FSMX'); // <<= kNumPrograms) + return; + allNotesOff(false); + curProgram = program; +} + +void FSM_VST_Plugin::setProgramName (char* name) +{ + //if (name != NULL && programs != NULL && curProgram >= 0 && curProgram < kNumPrograms && programs[curProgram].name != NULL) + // vst_strncpy (programs[curProgram].name, name, kVstMaxProgNameLen); + //if (name != NULL) { + + // //dbprintf("setProgramName %s\n", name); + //} +} + +void FSM_VST_Plugin::getProgramName (char* name) +{ + if (name != NULL && programs != NULL && curProgram >= 0 && programs[curProgram].name != NULL ) + vst_strncpy (name, programs[curProgram].name, kVstMaxProgNameLen); +} + +void FSM_VST_Plugin::getParameterLabel (VstInt32 index, char* label) +{ + vst_strncpy(label, "", kVstMaxParamStrLen); +} + +void FSM_VST_Plugin::getParameterDisplay (VstInt32 index, char* text) +{ + text[0] = 0; + switch (index) + { + case kVolume: float2string(fVolume, text, kVstMaxParamStrLen); break; + case kStartFrq: float2string(to_range(current()->bStartFrq, paraStartFrq), text, kVstMaxParamStrLen); break; + case kEndFrq: float2string(to_range(current()->bEndFrq, paraEndFrq), text, kVstMaxParamStrLen); break; + case kBuzzAmt: float2string(to_range(current()->bBuzzAmt, paraBuzzAmt), text, kVstMaxParamStrLen); break; + case kClickAmt: float2string(to_range(current()->bClickAmt, paraClickAmt), text, kVstMaxParamStrLen); break; + case kPunchAmt: float2string(to_range(current()->bPunchAmt, paraPunchAmt), text, kVstMaxParamStrLen); break; + case kToneDecay: float2string(to_range(current()->bToneDecay, paraToneDecay), text, kVstMaxParamStrLen); break; + case kToneShape: float2string(to_range(current()->bToneShape, paraToneShape), text, kVstMaxParamStrLen); break; + case kBDecay: float2string(to_range(current()->bBDecay, paraBDecay), text, kVstMaxParamStrLen); break; + case kCDecay: float2string(to_range(current()->bCDecay, paraCDecay), text, kVstMaxParamStrLen); break; + case kDecSlope: float2string(to_range(current()->bDecSlope, paraDecSlope), text, kVstMaxParamStrLen); break; + case kDecTime: float2string(to_range(current()->bDecTime, paraDecTime), text, kVstMaxParamStrLen); break; + case kRelSlope: float2string(to_range(current()->bRelSlope, paraRelSlope), text, kVstMaxParamStrLen); break; + } +} + +void FSM_VST_Plugin::getParameterName (VstInt32 index, char* label) +{ + switch (index) + { + case kVolume: vst_strncpy(label, "Volume", kVstMaxParamStrLen); return; + } + + if (index > 0 && index < kNumParams) { + const SynthParameter* param = synthParameters[index-1]; + vst_strncpy(label, param->Name, kVstMaxParamStrLen); + } +} + +void FSM_VST_Plugin::setParameter (VstInt32 index, float value) +{ + FSM_VST_Program *ap = &programs[curProgram]; + switch (index) + { + case kVolume: fVolume = value; break; + case kStartFrq: current()->bStartFrq = value; break; + case kEndFrq: current()->bEndFrq = value; break; + case kBuzzAmt: current()->bBuzzAmt = value; break; + case kClickAmt: current()->bClickAmt = value; break; + case kPunchAmt: current()->bPunchAmt = value; break; + case kToneDecay: current()->bToneDecay = value; break; + case kToneShape: current()->bToneShape = value; break; + case kBDecay: current()->bBDecay = value; break; + case kCDecay: current()->bCDecay = value; break; + case kDecSlope: current()->bDecSlope = value; break; + case kDecTime: current()->bDecTime = value; break; + case kRelSlope: current()->bRelSlope = value; break; + } +} + +float FSM_VST_Plugin::getParameter (VstInt32 index) +{ + float value = 0; + switch (index) + { + case kVolume: value = fVolume; break; + case kStartFrq: value = current()->bStartFrq; break; + case kEndFrq: value = current()->bEndFrq; break; + case kBuzzAmt: value = current()->bBuzzAmt; break; + case kClickAmt: value = current()->bClickAmt; break; + case kPunchAmt: value = current()->bPunchAmt; break; + case kToneDecay: value = current()->bToneDecay; break; + case kToneShape: value = current()->bToneShape; break; + case kBDecay: value = current()->bBDecay; break; + case kCDecay: value = current()->bCDecay; break; + case kDecSlope: value = current()->bDecSlope; break; + case kDecTime: value = current()->bDecTime; break; + case kRelSlope: value = current()->bRelSlope; break; + } + return value; +} + +void FSM_Voice::setParameters(ProgramParameters *ptval, float srate) +{ + this->StartFrq = (float)(33.0*pow(128, to_range(ptval->bStartFrq, paraStartFrq) / 240.0)); + this->EndFrq = (float)(33.0*pow(16, to_range(ptval->bEndFrq, paraEndFrq) / 240.0)); + this->TDecay = (float)(to_range(ptval->bToneDecay, paraToneDecay) / 240.0)*((1.0 / 400.0)*(44100.0 / srate)); + this->TShape = (float)(to_range(ptval->bToneShape, paraToneShape) / 240.0); + this->DSlope = (float)pow(20, to_range(ptval->bDecSlope, paraDecSlope) / 240.0 - 1) * 25 / srate; + this->DTime = (float)to_range(ptval->bDecTime, paraDecTime)*srate / 240.0; + this->RSlope = (float)pow(20, to_range(ptval->bRelSlope, paraRelSlope) / 240.0 - 1) * 25 / srate; + this->BDecay = (float)(to_range(ptval->bBDecay, paraBDecay) / 240.0); + this->CDecay = (float)(to_range(ptval->bCDecay, paraCDecay) / 240.0); + this->ClickAmt = (float)(to_range(ptval->bClickAmt, paraClickAmt) / 100.0); + this->BuzzAmt = 3 * (float)(to_range(ptval->bBuzzAmt, paraBuzzAmt) / 100.0); + this->PunchAmt = (float)(to_range(ptval->bPunchAmt, paraPunchAmt) / 100.0); + if (this->currentNote != NOTE_OFF) + { + int v = this->currentNote-24; + v = (v & 15) - 1 + 12 * (v >> 4); + this->PitchLimit = (float)(440.0*pow(2, (v - 69) / 12.0)); + } +} + +bool FSM_VST_Plugin::getOutputProperties (VstInt32 index, VstPinProperties* properties) +{ + if (index == 0 || index == 1) + { + properties->flags = kVstPinIsActive | kVstPinIsStereo; + } + if (index == 0) + { + strcpy(properties->label, "Left output"); + strcpy(properties->shortLabel, "L out"); + return true; + } + else if (index == 1) + { + strcpy(properties->label, "Right output"); + strcpy(properties->shortLabel, "R out"); + return true; + } + return false; +} + +bool FSM_VST_Plugin::getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text) +{ + if (index >= 0 && index < kNumPrograms) + { + vst_strncpy (text, programs[index].name, kVstMaxProgNameLen); + return true; + } + return false; +} + +bool FSM_VST_Plugin::getEffectName (char* name) +{ + vst_strncpy(name, "DrumSynth", kVstMaxEffectNameLen); + return true; +} + +bool FSM_VST_Plugin::getVendorString (char* text) +{ + vst_strncpy(text, PLUGIN_VENDOR_NAME, kVstMaxVendorStrLen); + return true; +} + +bool FSM_VST_Plugin::getProductString (char* text) +{ + vst_strncpy(text, PLUGIN_PRODUCT_NAME, kVstMaxProductStrLen); + return true; +} + +VstInt32 FSM_VST_Plugin::getVendorVersion () +{ + return 1000; +} + +VstInt32 FSM_VST_Plugin::canDo (char* text) +{ + if (!strcmp (text, "receiveVstEvents")) + return 1; + if (!strcmp(text, "receiveVstMidiEvent")) + return 1; + if (!strcmp(text, "receiveVstTimeInfo")) + return 1; + return -1; // explicitly can't do; 0 => don't know +} + +VstInt32 FSM_VST_Plugin::getNumMidiInputChannels () +{ + return 1; // we are monophonic +} + +VstInt32 FSM_VST_Plugin::getNumMidiOutputChannels () +{ + return 0; // no MIDI output back to Host app +} + +void FSM_VST_Plugin::setSampleRate (float sampleRate) +{ + allNotesOff(true); + AudioEffectX::setSampleRate (sampleRate); +} + +void FSM_VST_Plugin::setBlockSize (VstInt32 blockSize) +{ + allNotesOff(true); + AudioEffectX::setBlockSize (blockSize); +} + +VstInt32 FSM_VST_Plugin::processEvents(VstEvents* ev) +{ + for (VstInt32 i = 0; i < ev->numEvents; i++) + { + if ((ev->events[i])->type != kVstMidiType) + continue; + + VstMidiEvent* event = (VstMidiEvent*)ev->events[i]; + char* midiData = event->midiData; + VstInt32 status = midiData[0] & 0xf0; // ignoring channel + if (status == 0x90 || status == 0x80) // we only look at notes + { + VstInt32 note = midiData[1] & 0x7f; + VstInt32 velocity = midiData[2] & 0x7f; + if (status == 0x80) + velocity = 0; // note off by velocity 0 + if (!velocity) { + noteOff(note); + } + else { + noteOn(note, velocity, event->deltaFrames); + } + } + else if (status == 0xb0) + { + if (midiData[1] == 0x7e || midiData[1] == 0x7b) { // all notes off + allNotesOff(true); + } + } + event++; + } + return 1; +} + +void FSM_VST_Plugin::noteOff(VstInt32 note) { + + std::vector::iterator it = voices.begin(); + while (it != voices.end()) + { + FSM_Voice *voice = *it; + if (voice->currentNote == note) { + voice->release(); + } + it++; + } +} + +void FSM_VST_Plugin::noteOn(VstInt32 note, VstInt32 velocity, VstInt32 delta) { + if (issetprogram) + return; + FSM_Voice* voice; + voice = new FSM_Voice(note, velocity, delta); + voice->setParameters(current(), sampleRate); + voice->trigger(); + voices.push_back(voice); +} + +void FSM_VST_Plugin::allNotesOff(bool decay) { + std::vector::iterator it = voices.begin(); + while (it != voices.end()) + { + FSM_Voice *_note = *it; + if (decay) { + _note->release(); + it++; + } + else { + delete _note; + it = voices.erase(it); + } + } +} + +#define INTERPOLATE(pos,start,end) ((start)+(pos)*((end)-(start))) + +bool FSM_VST_Plugin::processVoice(FSM_Voice *trk, float *pout, int c, float gain) +{ + + trk->OscPhase = fmod(trk->OscPhase, 1.0); + float Ratio = trk->ThisEndFrq / trk->ThisStartFrq; + if (trk->AntiClick<-64000) trk->AntiClick = -64000; + if (trk->AntiClick >= 64000) trk->AntiClick = 64000; + int i = 0; + double xSin = trk->xSin, xCos = trk->xCos; + double dxSin = trk->dxSin, dxCos = trk->dxCos; + float LVal = 0; + float AClick = trk->AntiClick; + float Amp = trk->Amp; + float DecAmp = trk->DecAmp; + float BAmp = trk->BAmp; + float MulBAmp = trk->MulBAmp; + float CAmp = trk->CAmp; + float MulCAmp = trk->MulCAmp; + float Vol = 0.5*trk->ThisCurVolume*gain; + bool amphigh = Amp >= 16; + int Age = trk->Age; + float sr = this->getSampleRate(); + float odsr = 1.0f / sr; + int proc = 0; + while (iSamplesToGo == 1) + { + trk->trigger(); + AClick = trk->AntiClick; + Age = trk->Age; + Amp = trk->Amp; + dbprintf("retrigger.\n"); + } + if (trk->LeftOver <= 0) + { + trk->LeftOver = 32; + double EnvPoint = trk->EnvPhase*trk->ThisTDecay; + double ShapedPoint = pow(EnvPoint, trk->ThisTShape*2.0); + trk->Frequency = (float)(trk->ThisStartFrq*pow((double)Ratio, ShapedPoint)); + if (trk->Frequency>10000.f) trk->EnvPhase = 6553600; + if (trk->EnvPhaseThisDTime) + { + trk->DecAmp = DecAmp = trk->ThisDSlope; + trk->Amp = Amp = (float)(1 - DecAmp*trk->EnvPhase); + } + else + { + DecAmp = trk->ThisDSlope; + Amp = (float)(1 - DecAmp*trk->ThisDTime); + if (Amp>0) + { + trk->DecAmp = DecAmp = trk->ThisRSlope; + trk->Amp = Amp = Amp - DecAmp*(trk->EnvPhase - trk->ThisDTime); + } + } + if (trk->Amp <= 0) + { + trk->Amp = 0; + trk->DecAmp = 0; + if (fabs(AClick)<0.00012f && !trk->SamplesToGo) + return amphigh; + } + + trk->BAmp = BAmp = trk->BuzzAmt*(float)(pow(1.0f / 256.0f, trk->ThisBDecay*trk->EnvPhase*(odsr * 10))); + float CVal = (float)(pow(1.0f / 256.0f, trk->ThisCDecay*trk->EnvPhase*(odsr * 20))); + trk->CAmp = CAmp = trk->ClickAmt*CVal; + trk->Frequency *= (1 + 2 * trk->PunchAmt*CVal*CVal*CVal); + if (trk->Frequency>10000) trk->Frequency = 10000; + if (trk->FrequencyThisPitchLimit) trk->Frequency = trk->ThisPitchLimit; + + trk->MulBAmp = MulBAmp = (float)pow(1.0f / 256.0f, trk->ThisBDecay*(10 * odsr)); + trk->MulCAmp = MulCAmp = (float)pow(1.0f / 256.0f, trk->ThisCDecay*(10 * odsr)); + xSin = (float)sin(2.0*3.141592665*trk->OscPhase); + xCos = (float)cos(2.0*3.141592665*trk->OscPhase); + dxSin = (float)sin(2.0*3.141592665*trk->Frequency / sr); + dxCos = (float)cos(2.0*3.141592665*trk->Frequency / sr); + LVal = 0.0; + trk->dxSin = dxSin, trk->dxCos = dxCos; + } + int max = min(i + trk->LeftOver, c); + if (trk->SamplesToGo>0) + max = min(max, i + trk->SamplesToGo - 1); + + if (Amp>0.00001f && Vol>0) + { + proc++; + amphigh = true; + float OldAmp = Amp; + if (BAmp>0.01f) + { + for (int j = i; j0) + { + float D = (float)(Amp*Vol*BAmp*xSin*xCos); + pout[j] -= D; + LVal -= D; + } + double xSin2 = double(xSin*dxCos + xCos*dxSin); + double xCos2 = double(xCos*dxCos - xSin*dxSin); + xSin = xSin2; xCos = xCos2; + Amp -= DecAmp; + BAmp *= MulBAmp; + AClick *= 0.98f; + } + } + else + for (int j = i; j0.1f && CAmp>0.001f) + { + int max2 = i + min(max - i, 1024 - Age); + float LVal2 = 0.f; + for (int j = i; jthumpdata1[Age]); + OldAmp -= DecAmp; + CAmp *= MulCAmp; + Age++; + } + LVal += LVal2; + } + } + if (Amp) + { + trk->OscPhase += (max - i)*trk->Frequency / sr; + trk->EnvPhase += max - i; + trk->LeftOver -= max - i; + } + else + trk->LeftOver = 32000; + if (trk->SamplesToGo>0) trk->SamplesToGo -= max - i; + i = max; + } + + trk->xSin = xSin, trk->xCos = xCos; + trk->LastValue = LVal; + trk->AntiClick = AClick; + trk->Amp = Amp; + trk->BAmp = BAmp; + trk->CAmp = CAmp; + trk->Age = Age; + return amphigh; +} + +void FSM_VST_Plugin::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames) +{ + memset(outputs[0], 0, sampleFrames * sizeof(float)); + memset(outputs[1], 0, sampleFrames * sizeof(float)); + if (issetprogram) + return; + + float gain = powf(fVolume*SCALE_GAIN_OVERHEAD, 1.F / LOG_SCALE_GAIN); + for (std::vector::iterator it = this->voices.begin(); it != this->voices.end(); ) { + FSM_Voice* voice = *it; + float* out1 = outputs[0]; + int samples = sampleFrames; + if (voice->currentDelta >= sampleFrames) // future + { + voice->currentDelta -= sampleFrames; + ++it; + continue; + } + if (voice->currentDelta > 0) + { + out1 += voice->currentDelta; + samples -= voice->currentDelta; + voice->currentDelta = 0; + } + if (samples > 0) { + + bool amplitudeHigh = this->processVoice(voice, out1, samples, gain); + if (voice->released && !amplitudeHigh) { + delete voice; + it = voices.erase(it); + continue; + } + } + ++it; + } + memcpy(outputs[1], outputs[0], sizeof(float)*sampleFrames); +} + + +FSM_Voice::FSM_Voice(VstInt32 note, VstInt32 velocity, VstInt32 delta) { + currentNote = note; + currentDelta = delta; + currentVelocity = velocity; + released = false; + CurVolume = 32000.0; + Age = 0; + Amp = 0; + LeftOver = 32000; + EnvPhase = 6553600; + Retrig = 0; + SamplesToGo = 0; + EnvPhase = 0; + OscPhase = 0; + CurVolume = 32000; + LastValue = 0; + AntiClick = 0; + LeftOver = 0; + Age = 0; + Amp = 0; + DecAmp = 0; + BAmp = 0; + MulBAmp = 0; + CAmp = 0; + MulCAmp = 0; + Frequency = 0; + xSin = 0; + xCos = 0; + dxSin = 0; + dxCos = 0; +} + +void FSM_Voice::trigger() +{ + if (this->Retrig && this->RetrigCount>0) + { + this->SamplesToGo = this->Retrig; + this->RetrigCount--; + } + else + this->SamplesToGo = 0; + this->AntiClick = this->LastValue; + this->EnvPhase = 0; + this->OscPhase = this->ClickAmt; + this->LeftOver = 0; + this->Age = 0; + this->Amp = 32; + this->CurVolume = this->velocity(); + this->ThisPitchLimit = this->PitchLimit; + this->ThisDTime = this->DTime; + this->ThisDSlope = this->DSlope; + this->ThisRSlope = this->RSlope; + this->ThisBDecay = this->BDecay; + this->ThisCDecay = this->CDecay; + this->ThisTDecay = this->TDecay; + this->ThisTShape = this->TShape; + this->ThisStartFrq = this->StartFrq; + this->ThisEndFrq = this->EndFrq; + this->ThisCurVolume = this->CurVolume; +} + +void FSM_Voice::release() { + released = true; + if (this->EnvPhaseThisDTime) + { + this->ThisDTime = this->EnvPhase; + } +} + +FSM_VST_Program::FSM_VST_Program() +{ + vst_strncpy(name, "Init", kVstMaxProgNameLen); + + bStartFrq = from_range(paraStartFrq.DefValue, paraStartFrq); + bEndFrq = from_range(paraEndFrq.DefValue, paraEndFrq); + bBuzzAmt = from_range(paraBuzzAmt.DefValue, paraBuzzAmt); + bClickAmt = from_range(paraClickAmt.DefValue, paraClickAmt); + bPunchAmt = from_range(paraPunchAmt.DefValue, paraPunchAmt); + + bToneDecay = from_range(paraToneDecay.DefValue, paraToneDecay); + bToneShape = from_range(paraToneShape.DefValue, paraToneShape); + + bBDecay = from_range(paraBDecay.DefValue, paraBDecay); + bCDecay = from_range(paraCDecay.DefValue, paraCDecay); + bDecSlope = from_range(paraDecSlope.DefValue, paraDecSlope); + bDecTime = from_range(paraDecTime.DefValue, paraDecTime); + bRelSlope = from_range(paraRelSlope.DefValue, paraRelSlope); +} diff --git a/plugin.h b/plugin.h new file mode 100644 index 0000000..8a3fc7b --- /dev/null +++ b/plugin.h @@ -0,0 +1,249 @@ +#ifndef __VST_PLUGIN_H__ +#define __VST_PLUGIN_H__ + +#include +#include + +#ifdef DEBUG +#include +#include +#include +#include +#define DEBUG_CONSOLE +#define dprintf(...) printf (__VA_ARGS__) +#define DISPATCHER_DEBUG_TRACE +#else +#define dprintf(...) {} +#endif + + +#define PLUGIN_EFFECT_NAME "None" +#define PLUGIN_VENDOR_NAME "FSM" +#define PLUGIN_PRODUCT_NAME "FSM Kick XP" +#define LOG_SCALE_GAIN (0.3) +#define SCALE_GAIN_OVERHEAD (1.3) + +#define NOTE_OFF 255 + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long dword; + +class FSM_VST_Plugin; + +enum +{ + // Global + kNumPrograms = 100, + kNumOutputs = 2, +}; + +enum +{ + kVolume, + kStartFrq, + kEndFrq, + kBuzzAmt, + + kClickAmt, + kPunchAmt, + kToneDecay, + kToneShape, + kBDecay, + + kCDecay, + kDecSlope, + kDecTime, + kRelSlope, + kNumParams +}; + +class SynthParameter +{ +public: + char const *Name; // Short name: "Cutoff" + char const *Description;// Longer description: "Cutoff Frequency (0-7f)" + int MinValue; // 0 + int MaxValue; // 127 + int DefValue; // default value for params that have MPF_STATE flag set +}; + + +class ProgramParameters +{ +public: + float bStartFrq; + float bEndFrq; + float bBuzzAmt; + + float bClickAmt; + float bPunchAmt; + float bToneDecay; + float bToneShape; + float bBDecay; + + float bCDecay; + float bDecSlope; + float bDecTime; + float bRelSlope; +}; + + +class VoiceParameters +{ +public: + float PitchLimit; + float ThisPitchLimit; + float StartFrq; + float ThisStartFrq; + float EndFrq; + float ThisEndFrq; + float TDecay; + float ThisTDecay; + float TShape; + float ThisTShape; + float DSlope; + float ThisDSlope; + float DTime; + float ThisDTime; + float RSlope; + float ThisRSlope; + float BDecay; + float ThisBDecay; + float CDecay; + float ThisCDecay; + float CurVolume; + float ThisCurVolume; + float LastValue; + float AntiClick; + float ClickAmt; + float PunchAmt; + float BuzzAmt; + float Amp; + float DecAmp; + float BAmp; + float MulBAmp; + float CAmp; + float MulCAmp; + float Frequency; + int SamplesToGo; + int Retrig; + int RetrigCount; + + double xSin, xCos, dxSin, dxCos; + + int EnvPhase; + int LeftOver; + int Age; + double OscPhase; +}; + +class FSM_Voice : public VoiceParameters +{ +public: + VstInt32 currentNote; + VstInt32 currentVelocity; + VstInt32 currentDelta; + bool released; + FSM_Voice(VstInt32 note, VstInt32 velocity, VstInt32 delta); + void release(); + void setParameters(ProgramParameters* vals, float sr); + void trigger(); + double velocity()const + { + return currentVelocity / 127.0; + } + +}; + + +//------------------------------------------------------------------------------------------ +// FSM_VST_Program +//------------------------------------------------------------------------------------------ + +class FSM_VST_Program : public ProgramParameters +{ + friend class FSM_VST_Plugin; +public: + FSM_VST_Program (); + ~FSM_VST_Program() {} + void set(char* _name, int start, int end, + int buzz, int click, int punch, int tDecR, int tDecS, + int bDecR, int CPDecR, int ADecS, int ADecT, int ARelS); + +private: + char name[kVstMaxProgNameLen+1]; +}; + + +//------------------------------------------------------------------------------------------ +// FSM_VST_Plugin +//------------------------------------------------------------------------------------------ + +class FSM_VST_Plugin : public AudioEffectX { + +public: + FSM_VST_Plugin (audioMasterCallback audioMaster); + ~FSM_VST_Plugin (); + + virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames); + virtual VstInt32 processEvents (VstEvents* events); + + virtual void setProgram(VstInt32 program); + virtual void setProgramName(char* name); + virtual void getProgramName(char* name); + virtual bool beginSetProgram() { this->issetprogram = true; return false; } ///< Called before a program is loaded + virtual bool endSetProgram() { this->issetprogram = false; return false; } ///< Called after a program was loaded + virtual bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text); + + 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 setBlockSize (VstInt32 blockSize); + + virtual bool getOutputProperties (VstInt32 index, VstPinProperties* properties); + + virtual bool getEffectName (char* name); + virtual bool getVendorString (char* text); + virtual bool getProductString (char* text); + virtual VstInt32 getVendorVersion (); + virtual VstInt32 canDo (char* text); + + virtual VstInt32 getNumMidiInputChannels (); + virtual VstInt32 getNumMidiOutputChannels (); + + FSM_VST_Program* current() { + return &(curProgram >= 0 && curProgram < kNumPrograms ? programs[curProgram] : programs[0]); + } + +#ifdef DISPATCHER_DEBUG_TRACE + VstIntPtr dispatcher(VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); +#endif // DEBUG + +private: + +#ifdef DEBUG_CONSOLE + void startConsoleWin(int width, int height, char* fname); + HANDLE hout; +#endif // DEBUG_CONSOLE + +private: + void noteOn(VstInt32 note, VstInt32 velocity, VstInt32 delta); + void noteOff(VstInt32 note); + void allNotesOff(bool decay); + void initProcess(); + bool processVoice(FSM_Voice *trk, float *pout, int c, float gain); + + FSM_VST_Program* programs; + std::vector voices; + float fVolume; + bool issetprogram; + float thumpdata1[1024]; + +}; + +#endif diff --git a/vstplug.def b/vstplug.def new file mode 100644 index 0000000..7bff835 --- /dev/null +++ b/vstplug.def @@ -0,0 +1,3 @@ +EXPORTS +VSTPluginMain +main=VSTPluginMain \ No newline at end of file