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:
1 parent
989812ba36
commit
a24eaa0cd9
58 files changed
+3334
-151
No files matched your search
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 = '"');
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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
|
||||
Reference in new issue
Block a user