Added: VST Plugin support. Add and configure plugins via Configuration Editor. The plugin's architecture has to match the OS architecture, so most people will need 64-bit plugins. The subdirectory plugins is offered to put plugins into, but they can be opened from any directory with sufficient permissions.

Fixed: When trying to add a high-pass filter in the Configuration Editor, it was instead configured to be a low-pass filter.
This commit is contained in:
jthedering committed 2017-06-17 13:04:35 +00:00
1 parent 989812ba36
commit a24eaa0cd9
58 files changed
+3334 -151

No files matched your search

+113
View File
@@ -0,0 +1,113 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "stdafx.h"
#include <Imagehlp.h>
#include "AbstractLibrary.h"
#include "helpers/LogHelper.h"
using namespace std;
AbstractLibrary::~AbstractLibrary()
{
if (module != NULL)
{
wchar_t path[MAX_PATH];
GetModuleFileNameW(module, path, MAX_PATH);
FreeLibrary(module);
module = NULL;
TraceF(L"Unloaded library %s", path);
}
}
int AbstractLibrary::initialize()
{
if (module == NULL)
{
wstring libPath = getLibPath();
if (GetFileAttributesW(libPath.c_str()) == INVALID_FILE_ATTRIBUTES)
return FILE_NOT_FOUND;
module = LoadLibraryW(libPath.c_str());
if (module == NULL)
{
unsigned short arch = getFileArchitecture(libPath);
#ifdef _WIN64
int bitDepth = 64;
#else
int bitDepth = 32;
#endif
if (arch != 0 && (bitDepth == 64 && arch != IMAGE_FILE_MACHINE_AMD64
|| bitDepth == 32 && arch != IMAGE_FILE_MACHINE_I386))
return WRONG_ARCHITECTURE;
return LOADING_FAILED;
}
if (!loadFunctions())
{
FreeLibrary(module);
module = NULL;
return FUNCTIONS_MISSING;
}
int res = customInitialize();
if (res < 0)
return res;
TraceF(L"Loaded library %s", libPath.c_str());
return 1;
}
return 0;
}
int AbstractLibrary::customInitialize()
{
// overwrite if needed
return 0;
}
unsigned short AbstractLibrary::getFileArchitecture(const wstring& filePath)
{
unsigned short result = 0;
HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
HANDLE hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMap != NULL)
{
void* mapAddr = MapViewOfFileEx(hMap, FILE_MAP_READ, 0, 0, 0, NULL);
if (mapAddr != NULL)
{
PIMAGE_NT_HEADERS ntHeaders = ImageNtHeader(mapAddr);
if (ntHeaders != NULL)
result = ntHeaders->FileHeader.Machine;
UnmapViewOfFile(mapAddr);
}
CloseHandle(hMap);
}
CloseHandle(hFile);
}
return result;
}
+45
View File
@@ -0,0 +1,45 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <string>
class AbstractLibrary
{
public:
static const int FILE_NOT_FOUND = -1;
static const int LOADING_FAILED = -2;
static const int FUNCTIONS_MISSING = -3;
static const int WRONG_ARCHITECTURE = -4;
virtual ~AbstractLibrary();
int initialize();
virtual std::wstring getLibPath() = 0;
protected:
virtual bool loadFunctions() = 0;
virtual int customInitialize();
HMODULE module = NULL;
private:
unsigned short getFileArchitecture(const std::wstring& filePath);
};
+5 -1
View File
@@ -85,7 +85,11 @@ double GainIterator::gainAt(double freq)
else
{
double t = (log(freq) - logLeft) / logRightMinusLeft;
dbGain = nodeLeft->dbGain + t * (nodeRight->dbGain - nodeLeft->dbGain);
// to support dbGain == -INF for both nodes
if (nodeLeft->dbGain == nodeRight->dbGain)
dbGain = nodeLeft->dbGain;
else
dbGain = nodeLeft->dbGain + t * (nodeRight->dbGain - nodeLeft->dbGain);
}
return dbGain;
+2
View File
@@ -109,6 +109,8 @@ void LogHelper::log(const char* file, int line, const void* caller, bool trace,
if (presetFP == NULL)
fclose(fp);
else
fflush(fp);
}
void LogHelper::reset()
+34
View File
@@ -163,3 +163,37 @@ wstring StringHelper::getSystemErrorString(long status)
else
return L"";
}
vector<wstring> StringHelper::splitQuoted(const wstring& s, wchar_t splitChar, wchar_t quoteChar)
{
vector<wstring> result;
bool inQuotes = false;
wstring current;
for (size_t i = 0; i < s.length(); i++)
{
wchar_t c = s[i];
if (c == splitChar && !inQuotes)
{
if (current != L"")
{
result.push_back(current);
current = L"";
}
}
else if (c == quoteChar)
{
inQuotes = !inQuotes;
if (inQuotes && i > 0 && s[i - 1] == quoteChar)
current += quoteChar;
}
else
{
current += c;
}
}
if (current != L"")
result.push_back(current);
return result;
}
+1
View File
@@ -35,4 +35,5 @@ public:
static std::vector<std::wstring> split(const std::wstring& s, wchar_t splitChar, bool skipEmpty = true);
static std::wstring join(const std::vector<std::wstring>& strings, const std::wstring& separator);
static std::wstring getSystemErrorString(long status);
static std::vector<std::wstring> splitQuoted(const std::wstring& s, wchar_t splitChar, wchar_t quoteChar = '"');
};
+397
View File
@@ -0,0 +1,397 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "stdafx.h"
#include <wincrypt.h>
#include "StringHelper.h"
#include "version.h"
#include "VSTPluginLibrary.h"
#include "VSTPluginInstance.h"
using namespace std;
#define equalizerApoVSTID CCONST('E', 'A', 'P', 'O');
static intptr_t callback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
{
VSTPluginInstance* instance = effect != NULL ? (VSTPluginInstance*)effect->user : NULL;
#ifdef _DEBUG
printf("vst: %p opcode: %d index: %d value: %d ptr: %p opt: %f user: %p\n",
effect, opcode, index, value, ptr, opt, effect != NULL ? effect->user : NULL);
fflush(stdout);
#endif
switch (opcode)
{
case audioMasterVersion:
return 2400;
case audioMasterCurrentId:
return equalizerApoVSTID;
case audioMasterGetProductString:
strcpy_s((char*) ptr, 64, "Equalizer APO");
return 1;
case audioMasterGetVendorVersion:
return (intptr_t) (MAJOR << 24 | MINOR << 16 | REVISION << 8 | 0);
case audioMasterPinConnected:
if (instance != NULL)
return index < instance->getUsedChannelCount() ? 0 : 1;
else
return 0;
case audioMasterNeedIdle:
return effect->dispatcher(effect, effIdle, 0, 0, NULL, 0.0f);
case audioMasterUpdateDisplay:
return effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
case audioMasterGetTime:
return 0;
case audioMasterGetSampleRate:
if (instance != NULL)
return (intptr_t)instance->getSampleRate();
return 0;
case audioMasterGetCurrentProcessLevel:
if (instance != NULL)
return instance->getProcessLevel();
return 0;
case audioMasterGetLanguage:
if (instance != NULL)
return instance->getLanguage();
return 0;
case audioMasterWillReplaceOrAccumulate:
return 1;
case audioMasterSizeWindow:
if (instance != NULL)
instance->onSizeWindow((int)index, (int)value);
return 1;
case audioMasterCanDo:
{
char* s = (char*)ptr;
#ifdef _DEBUG
printf("VST canDo: %s\n", s);
fflush(stdout);
#endif
if (strcmp(s, "startStopProcess") == 0 ||
strcmp(s, "sizeWindow") == 0)
return 1;
}
return 0;
case audioMasterAutomate:
if (instance != NULL)
instance->onAutomate();
return 0;
case audioMasterBeginEdit:
case audioMasterEndEdit:
case audioMasterIdle:
case audioMasterWantMidi:
return 0;
}
return 0;
}
VSTPluginInstance::VSTPluginInstance(const std::shared_ptr<VSTPluginLibrary>& library, int processLevel)
: library(library), processLevel(processLevel)
{
}
VSTPluginInstance::~VSTPluginInstance()
{
if (effect != NULL)
{
effect->dispatcher(effect, effClose, 0, 0, NULL, 0.0f);
effect = NULL;
}
}
bool VSTPluginInstance::initialize()
{
bool result = true;
__try
{
effect = library->VSTPluginMain(callback);
effect->user = this;
if (effect->magic == kEffectMagic)
{
effect->dispatcher(effect, effOpen, 0, 0, NULL, 0.0f);
usedChannelCount = max(numInputs(), numOutputs());
}
else
{
effect = NULL;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
result = false;
}
return result;
}
int VSTPluginInstance::numInputs() const
{
if (effect == NULL)
return 0;
return effect->numInputs;
}
int VSTPluginInstance::numOutputs() const
{
if (effect == NULL)
return 0;
return effect->numOutputs;
}
bool VSTPluginInstance::canReplacing() const
{
if (effect == NULL)
return true;
return (effect->flags & effFlagsCanReplacing) != 0;
}
int VSTPluginInstance::uniqueID() const
{
if (effect == NULL)
return 0;
return effect->uniqueID;
}
std::wstring VSTPluginInstance::getName() const
{
if (effect == NULL)
return L"";
char buf[256];
memset(buf, 0, sizeof(buf));
effect->dispatcher(effect, effGetEffectName, 0, 0, buf, 0.0f);
return StringHelper::toWString(buf, CP_UTF8);
}
int VSTPluginInstance::getUsedChannelCount() const
{
return usedChannelCount;
}
void VSTPluginInstance::setUsedChannelCount(int count)
{
usedChannelCount = count;
}
float VSTPluginInstance::getSampleRate() const
{
return sampleRate;
}
int VSTPluginInstance::getProcessLevel() const
{
return processLevel;
}
void VSTPluginInstance::setProcessLevel(int value)
{
processLevel = value;
}
int VSTPluginInstance::getLanguage() const
{
return language;
}
void VSTPluginInstance::setLanguage(int value)
{
language = value;
}
void VSTPluginInstance::prepareForProcessing(float sampleRate, int blockSize)
{
if (effect == NULL)
return;
this->sampleRate = sampleRate;
effect->dispatcher(effect, effSetSampleRate, 0, 0, NULL, sampleRate);
effect->dispatcher(effect, effSetBlockSize, 0, blockSize, NULL, 0.0f);
}
void VSTPluginInstance::writeToEffect(const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap)
{
if (effect == NULL)
return;
if (effect->flags & effFlagsProgramChunks)
{
if (chunkData != L"")
{
DWORD bufSize = 0;
CryptStringToBinaryW(chunkData.c_str(), 0, CRYPT_STRING_BASE64, NULL, &bufSize, NULL, NULL);
BYTE* buf = new BYTE[bufSize];
if (CryptStringToBinaryW(chunkData.c_str(), 0, CRYPT_STRING_BASE64, buf, &bufSize, NULL, NULL) == TRUE)
effect->dispatcher(effect, effSetChunk, 1, bufSize, buf, 0.0f);
delete[]buf;
}
}
else
{
for (int i = 0; i < effect->numParams; i++)
{
char buf[256];
effect->dispatcher(effect, effGetParamName, i, 0, buf, 0.0f);
wstring name = StringHelper::toWString(buf, CP_UTF8);
auto it = paramMap.find(name);
if (it != paramMap.end())
effect->setParameter(effect, i, it->second);
}
}
}
void VSTPluginInstance::readFromEffect(std::wstring& chunkData, std::unordered_map<std::wstring, float>& paramMap) const
{
if (effect == NULL)
return;
chunkData = L"";
paramMap.clear();
if (effect->flags & effFlagsProgramChunks)
{
BYTE* chunk = NULL;
int size = (int)effect->dispatcher(effect, effGetChunk, 1, 0, &chunk, 0.0f);
DWORD stringLength;
CryptBinaryToStringW(chunk, size, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &stringLength);
wchar_t* string = new wchar_t[stringLength];
if (CryptBinaryToStringW(chunk, size, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, string, &stringLength) == TRUE)
chunkData = string;
delete[]string;
}
else
{
for (int i = 0; i < effect->numParams; i++)
{
char buf[256];
effect->dispatcher(effect, effGetParamName, i, 0, buf, 0.0f);
float value = effect->getParameter(effect, i);
paramMap[StringHelper::toWString(buf, CP_UTF8)] = value;
}
}
}
void VSTPluginInstance::startProcessing()
{
if (effect == NULL)
return;
effect->dispatcher(effect, effMainsChanged, 0, 1, NULL, 0.0f);
effect->dispatcher(effect, effStartProcess, 0, 0, NULL, 0.0f);
}
void VSTPluginInstance::processReplacing(float** inputArray, float** outputArray, int frameCount)
{
if (effect == NULL)
return;
effect->processReplacing(effect, inputArray, outputArray, frameCount);
}
void VSTPluginInstance::process(float** inputArray, float** outputArray, int frameCount)
{
if (effect == NULL)
return;
effect->process(effect, inputArray, outputArray, frameCount);
}
void VSTPluginInstance::stopProcessing()
{
if (effect == NULL)
return;
effect->dispatcher(effect, effStopProcess, 0, 0, NULL, 0.0f);
effect->dispatcher(effect, effMainsChanged, 0, 0, NULL, 0.0f);
}
void VSTPluginInstance::startEditing(HWND hWnd, short* width, short* height)
{
if (effect == NULL)
return;
VstRect* rect;
effect->dispatcher(effect, effEditGetRect, 0, 0, &rect, 0.0f);
effect->dispatcher(effect, effEditOpen, 0, 0, hWnd, 0.0f);
effect->dispatcher(effect, effEditGetRect, 0, 0, &rect, 0.0f);
*width = rect->right - rect->left;
*height = rect->bottom - rect->top;
}
void VSTPluginInstance::doIdle()
{
if (effect == NULL)
return;
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
}
void VSTPluginInstance::stopEditing()
{
if (effect == NULL)
return;
effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f);
}
void VSTPluginInstance::setAutomateFunc(std::function<void()> func)
{
automateFunc = func;
}
void VSTPluginInstance::onAutomate()
{
if (automateFunc)
automateFunc();
}
void VSTPluginInstance::setSizeWindowFunc(std::function<void(int, int)> func)
{
sizeWindowFunc = func;
}
void VSTPluginInstance::onSizeWindow(int w, int h)
{
if (sizeWindowFunc)
sizeWindowFunc(w, h);
}
+78
View File
@@ -0,0 +1,78 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <string>
#include <memory>
#include <functional>
#include "aeffectx.h"
class VSTPluginLibrary;
class VSTPluginInstance
{
public:
VSTPluginInstance(const std::shared_ptr<VSTPluginLibrary>& library, int processLevel);
~VSTPluginInstance();
bool initialize();
int numInputs() const;
int numOutputs() const;
bool canReplacing() const;
int uniqueID() const;
std::wstring getName() const;
int getUsedChannelCount() const;
void setUsedChannelCount(int count);
float getSampleRate() const;
int getProcessLevel() const;
void setProcessLevel(int value);
int getLanguage() const;
void setLanguage(int value);
void prepareForProcessing(float sampleRate, int blockSize);
void writeToEffect(const std::wstring& chunkData, const std::unordered_map<std::wstring, float>& paramMap);
void readFromEffect(std::wstring& chunkData, std::unordered_map<std::wstring, float>& paramMap) const;
void startProcessing();
void processReplacing(float** inputArray, float** outputArray, int frameCount);
void process(float** inputArray, float** outputArray, int frameCount);
void stopProcessing();
void startEditing(HWND hWnd, short* width, short* height);
void doIdle();
void stopEditing();
void setAutomateFunc(std::function<void()> func);
void onAutomate();
void setSizeWindowFunc(std::function<void(int, int)> func);
void onSizeWindow(int w, int h);
private:
std::shared_ptr<VSTPluginLibrary> library;
AEffect* effect;
std::function<void()> automateFunc;
std::function<void(int, int)> sizeWindowFunc;
float sampleRate = 0.0f;
int usedChannelCount;
int processLevel = 0;
int language = 1;
};
+76
View File
@@ -0,0 +1,76 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "stdafx.h"
#include "RegistryHelper.h"
#include "LogHelper.h"
#include "VSTPluginLibrary.h"
using namespace std;
std::unordered_map<std::wstring, std::weak_ptr<VSTPluginLibrary> > VSTPluginLibrary::instanceMap;
std::wstring VSTPluginLibrary::defaultPluginPath;
std::shared_ptr<VSTPluginLibrary> VSTPluginLibrary::getInstance(const wstring& libPath)
{
shared_ptr<VSTPluginLibrary> ptr;
auto it = instanceMap.find(libPath);
if (it != instanceMap.end())
{
weak_ptr<VSTPluginLibrary> instance = it->second;
ptr = instance.lock();
}
if (ptr == NULL)
{
ptr = shared_ptr<VSTPluginLibrary>(new VSTPluginLibrary(libPath));
instanceMap[libPath] = ptr;
}
return ptr;
}
wstring VSTPluginLibrary::getDefaultPluginPath()
{
if (defaultPluginPath == L"")
{
wstring installPath = RegistryHelper::readValue(APP_REGPATH, L"InstallPath");
defaultPluginPath = installPath + L"\\plugins";
}
return defaultPluginPath;
}
std::wstring VSTPluginLibrary::getLibPath()
{
return libPath;
}
bool VSTPluginLibrary::loadFunctions()
{
VSTPluginMain = (vstPluginMain)GetProcAddress(module, "VSTPluginMain");
return VSTPluginMain != NULL;
}
VSTPluginLibrary::VSTPluginLibrary(const wstring& libPath)
: libPath(libPath)
{
}
+49
View File
@@ -0,0 +1,49 @@
/*
This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <memory>
#include <string>
#include <unordered_map>
#include "AbstractLibrary.h"
#include "aeffectx.h"
#include <queue>
#include "VSTPluginInstance.h"
class VSTPluginLibrary : public AbstractLibrary
{
public:
static std::shared_ptr<VSTPluginLibrary> getInstance(const std::wstring& libPath);
static std::wstring getDefaultPluginPath();
std::wstring getLibPath() override;
typedef AEffect* (* vstPluginMain)(audioMasterCallback audioMaster);
vstPluginMain VSTPluginMain;
protected:
bool loadFunctions() override;
private:
VSTPluginLibrary(const std::wstring& libPath);
static std::unordered_map<std::wstring, std::weak_ptr<VSTPluginLibrary> > instanceMap;
static std::wstring defaultPluginPath;
std::wstring libPath;
};
+391
View File
@@ -0,0 +1,391 @@
/*
* aeffectx.h - simple header to allow VeSTige compilation and eventually work
*
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef _AEFFECTX_H
#define _AEFFECTX_H
#define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \
( ( (int) b ) << 16 ) | \
( ( (int) c ) << 8 ) | \
( ( (int) d ) << 0 ) )
const int audioMasterAutomate = 0;
const int audioMasterVersion = 1;
const int audioMasterCurrentId = 2;
const int audioMasterIdle = 3;
const int audioMasterPinConnected = 4;
// unsupported? 5
const int audioMasterWantMidi = 6;
const int audioMasterGetTime = 7;
const int audioMasterProcessEvents = 8;
const int audioMasterSetTime = 9;
const int audioMasterTempoAt = 10;
const int audioMasterGetNumAutomatableParameters = 11;
const int audioMasterGetParameterQuantization = 12;
const int audioMasterIOChanged = 13;
const int audioMasterNeedIdle = 14;
const int audioMasterSizeWindow = 15;
const int audioMasterGetSampleRate = 16;
const int audioMasterGetBlockSize = 17;
const int audioMasterGetInputLatency = 18;
const int audioMasterGetOutputLatency = 19;
const int audioMasterGetPreviousPlug = 20;
const int audioMasterGetNextPlug = 21;
const int audioMasterWillReplaceOrAccumulate = 22;
const int audioMasterGetCurrentProcessLevel = 23;
const int audioMasterGetAutomationState = 24;
const int audioMasterOfflineStart = 25;
const int audioMasterOfflineRead = 26;
const int audioMasterOfflineWrite = 27;
const int audioMasterOfflineGetCurrentPass = 28;
const int audioMasterOfflineGetCurrentMetaPass = 29;
const int audioMasterSetOutputSampleRate = 30;
// unsupported? 31
const int audioMasterGetSpeakerArrangement = 31; // deprecated in 2.4?
const int audioMasterGetVendorString = 32;
const int audioMasterGetProductString = 33;
const int audioMasterGetVendorVersion = 34;
const int audioMasterVendorSpecific = 35;
const int audioMasterSetIcon = 36;
const int audioMasterCanDo = 37;
const int audioMasterGetLanguage = 38;
const int audioMasterOpenWindow = 39;
const int audioMasterCloseWindow = 40;
const int audioMasterGetDirectory = 41;
const int audioMasterUpdateDisplay = 42;
const int audioMasterBeginEdit = 43;
const int audioMasterEndEdit = 44;
const int audioMasterOpenFileSelector = 45;
const int audioMasterCloseFileSelector = 46; // currently unused
const int audioMasterEditFile = 47; // currently unused
const int audioMasterGetChunkFile = 48; // currently unused
const int audioMasterGetInputSpeakerArrangement = 49; // currently unused
const int effFlagsHasEditor = 1;
const int effFlagsCanReplacing = 1 << 4; // very likely
const int effFlagsProgramChunks = 1 << 5; // from Ardour
const int effFlagsIsSynth = 1 << 8; // currently unused
const int effOpen = 0;
const int effClose = 1; // currently unused
const int effSetProgram = 2; // currently unused
const int effGetProgram = 3; // currently unused
// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
const int effSetProgramName = 4;
const int effGetProgramName = 5; // currently unused
// The next two were gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
const int effGetParamLabel = 6;
const int effGetParamDisplay = 7;
const int effGetParamName = 8; // currently unused
const int effSetSampleRate = 10;
const int effSetBlockSize = 11;
const int effMainsChanged = 12;
const int effEditGetRect = 13;
const int effEditOpen = 14;
const int effEditClose = 15;
const int effEditIdle = 19;
const int effEditTop = 20;
const int effIdentify = 22; // from http://www.asseca.org/vst-24-specs/efIdentify.html
const int effGetChunk = 23; // from Ardour
const int effSetChunk = 24; // from Ardour
const int effProcessEvents = 25;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efCanBeAutomated.html
const int effCanBeAutomated = 26;
// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
const int effGetProgramNameIndexed = 29;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
const int effGetPlugCategory = 35;
const int effGetEffectName = 45;
const int effGetParameterProperties = 56; // missing
const int effGetVendorString = 47;
const int effGetProductString = 48;
const int effGetVendorVersion = 49;
const int effCanDo = 51; // currently unused
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efIdle.html
const int effIdle = 53;
const int effGetVstVersion = 58; // currently unused
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginSetProgram.html
const int effBeginSetProgram = 67;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efEndSetProgram.html
const int effEndSetProgram = 68;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efShellGetNextPlugin.html
const int effShellGetNextPlugin = 70;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadBank.html
const int effBeginLoadBank = 75;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
const int effBeginLoadProgram = 76;
// The next two were gleaned from http://www.kvraudio.com/forum/printview.php?t=143587&start=0
const int effStartProcess = 71;
const int effStopProcess = 72;
const int kEffectMagic = CCONST( 'V', 's', 't', 'P' );
const int kVstLangEnglish = 1;
const int kVstMidiType = 1;
const int kVstNanosValid = 1 << 8;
const int kVstPpqPosValid = 1 << 9;
const int kVstTempoValid = 1 << 10;
const int kVstBarsValid = 1 << 11;
const int kVstCyclePosValid = 1 << 12;
const int kVstTimeSigValid = 1 << 13;
const int kVstSmpteValid = 1 << 14; // from Ardour
const int kVstClockValid = 1 << 15; // from Ardour
const int kVstTransportPlaying = 1 << 1;
const int kVstTransportCycleActive = 1 << 2;
const int kVstTransportChanged = 1;
class RemoteVstPlugin;
class VstMidiEvent
{
public:
// 00
int type;
// 04
int byteSize;
// 08
int deltaFrames;
// 0c?
int flags;
// 10?
int noteLength;
// 14?
int noteOffset;
// 18
char midiData[4];
// 1c?
char detune;
// 1d?
char noteOffVelocity;
// 1e?
char reserved1;
// 1f?
char reserved2;
} ;
class VstEvent
{
char dump[sizeof( VstMidiEvent )];
} ;
class VstEvents
{
public:
// 00
int numEvents;
// 04
void *reserved;
// 08
VstEvent* events[1];
} ;
// Not finished, neither really used
class VstParameterProperties
{
public:
/* float stepFloat;
char label[64];
int flags;
int minInteger;
int maxInteger;
int stepInteger;
char shortLabel[8];
int category;
char categoryLabel[24];
char empty[128];*/
float stepFloat;
float smallStepFloat;
float largeStepFloat;
char label[64];
unsigned int flags;
unsigned int minInteger;
unsigned int maxInteger;
unsigned int stepInteger;
unsigned int largeStepInteger;
char shortLabel[8];
unsigned short displayIndex;
unsigned short category;
unsigned short numParametersInCategory;
unsigned short reserved;
char categoryLabel[24];
char future[16];
} ;
#include <stdint.h>
class AEffect
{
public:
// Never use virtual functions!!!
// 00-03
int magic;
// dispatcher 04-07
intptr_t (* dispatcher)( AEffect * , int , int , intptr_t, void * , float );
// process, quite sure 08-0b
void (* process)( AEffect * , float * * , float * * , int );
// setParameter 0c-0f
void (* setParameter)( AEffect * , int , float );
// getParameter 10-13
float (* getParameter)( AEffect * , int );
// programs 14-17
int numPrograms;
// Params 18-1b
int numParams;
// Input 1c-1f
int numInputs;
// Output 20-23
int numOutputs;
// flags 24-27
int flags;
// Fill somewhere 28-2b
void * ptr1;
void * ptr2;
int initialDelay;
// Zeroes 34-37 38-3b
int empty3a;
int empty3b;
// 1.0f 3c-3f
float unkown_float;
// An object? pointer 40-43
void *ptr3;
// Zeroes 44-47
void *user;
// Id 48-4b
int32_t uniqueID;
int32_t version;
// processReplacing 50-53
void (* processReplacing)( AEffect * , float * * , float * * , int );
} ;
class VstTimeInfo
{
public:
// 00
double samplePos;
// 08
double sampleRate;
// 10
double nanoSeconds;
// 18
double ppqPos;
// 20?
double tempo;
// 28
double barStartPos;
// 30?
double cycleStartPos;
// 38?
double cycleEndPos;
// 40?
int timeSigNumerator;
// 44?
int timeSigDenominator;
// unconfirmed 48 4c 50
char empty3[4 + 4 + 4];
// 54
int flags;
} ;
typedef intptr_t (* audioMasterCallback)( AEffect * , int32_t, int32_t, intptr_t, void * , float );
// from http://www.asseca.org/vst-24-specs/efGetParameterProperties.html
enum VstParameterFlags
{
kVstParameterIsSwitch = 1 << 0, // parameter is a switch (on/off)
kVstParameterUsesIntegerMinMax = 1 << 1, // minInteger, maxInteger valid
kVstParameterUsesFloatStep = 1 << 2, // stepFloat, smallStepFloat, largeStepFloat valid
kVstParameterUsesIntStep = 1 << 3, // stepInteger, largeStepInteger valid
kVstParameterSupportsDisplayIndex = 1 << 4, // displayIndex valid
kVstParameterSupportsDisplayCategory = 1 << 5, // category, etc. valid
kVstParameterCanRamp = 1 << 6 // set if parameter value can ramp up/down
};
// from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
struct VstPatchChunkInfo
{
int32_t version; // Format Version (should be 1)
int32_t pluginUniqueID; // UniqueID of the plug-in
int32_t pluginVersion; // Plug-in Version
int32_t numElements; // Number of Programs (Bank) or Parameters (Program)
char future[48]; // Reserved for future use
};
// from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
enum VstPlugCategory
{
kPlugCategUnknown = 0, // 0=Unknown, category not implemented
kPlugCategEffect, // 1=Simple Effect
kPlugCategSynth, // 2=VST Instrument (Synths, samplers,...)
kPlugCategAnalysis, // 3=Scope, Tuner, ...
kPlugCategMastering, // 4=Dynamics, ...
kPlugCategSpacializer, // 5=Panners, ...
kPlugCategRoomFx, // 6=Delays and Reverbs
kPlugSurroundFx, // 7=Dedicated surround processor
kPlugCategRestoration, // 8=Denoiser, ...
kPlugCategOfflineProcess, // 9=Offline Process
kPlugCategShell, // 10=Plug-in is container of other plug-ins @see effShellGetNextPlugin()
kPlugCategGenerator, // 11=ToneGenerator, ...
kPlugCategMaxCount // 12=Marker to count the categories
};
class VstRect
{
public:
short top;
short left;
short bottom;
short right;
} ;
#endif