commit 4dcfcc80feb848d715ec4818f44c64454824ca7a Author: Jens Ahrensfeld Date: Tue Nov 11 15:04:27 2025 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9785597 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.cache diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..605a4ad --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "submodules/make"] + path = submodules/make + url = http://192.168.22.90:3001/jayfield/make.git +[submodule "dsp"] + path = submodules/dsp + url = http://192.168.22.90:3001/jayfield/dsp.git diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..cf7145d --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,11 @@ +{ + "C_Cpp.intelliSenseEngine": "disabled", + "clangd.path": "/usr/bin/clangd", + "clangd.arguments": + [ + "-log=verbose", + "-pretty", + "--background-index", + "--compile-commands-dir=${workspaceFolder}/build/compile_commands.json" + ] +} diff --git a/.vscode/compile_commands.json b/.vscode/compile_commands.json new file mode 100644 index 0000000..7f1b908 --- /dev/null +++ b/.vscode/compile_commands.json @@ -0,0 +1,132 @@ +[ + { + "arguments": [ + "/usr/bin/clang++", + "-fPIC", + "-std=c++11", + "-g", + "-O3", + "-DVST_2_4_EXTENSIONS=0", + "-DVST_2_3_EXTENSIONS=1", + "-I", + "/home/jens/work/repos/JayFilter/src", + "-I", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4", + "-c", + "-o", + "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/filter.o", + "src/filter.cpp" + ], + "directory": "/home/jens/work/repos/JayFilter", + "file": "/home/jens/work/repos/JayFilter/src/filter.cpp", + "output": "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/filter.o" + }, + { + "arguments": [ + "/usr/bin/clang++", + "-fPIC", + "-std=c++11", + "-g", + "-O3", + "-DVST_2_4_EXTENSIONS=0", + "-DVST_2_3_EXTENSIONS=1", + "-I", + "/home/jens/work/repos/JayFilter/src", + "-I", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4", + "-c", + "-o", + "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/filterMain.o", + "src/filterMain.cpp" + ], + "directory": "/home/jens/work/repos/JayFilter", + "file": "/home/jens/work/repos/JayFilter/src/filterMain.cpp", + "output": "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/filterMain.o" + }, + { + "arguments": [ + "/usr/bin/clang++", + "-fPIC", + "-std=c++11", + "-g", + "-O3", + "-DVST_2_4_EXTENSIONS=0", + "-DVST_2_3_EXTENSIONS=1", + "-I", + "/home/jens/work/repos/JayFilter/src", + "-I", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4", + "-c", + "-o", + "/home/jens/work/repos/JayFilter/build/linux/release/Filter//home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.o", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp" + ], + "directory": "/home/jens/work/repos/JayFilter", + "file": "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp", + "output": "/home/jens/work/repos/JayFilter/build/linux/release/Filter/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.o" + }, + { + "arguments": [ + "/usr/bin/clang++", + "-fPIC", + "-std=c++11", + "-g", + "-O3", + "-DVST_2_4_EXTENSIONS=0", + "-DVST_2_3_EXTENSIONS=1", + "-I", + "/home/jens/work/repos/JayFilter/src", + "-I", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4", + "-c", + "-o", + "/home/jens/work/repos/JayFilter/build/linux/release/Filter//home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.o", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.cpp" + ], + "directory": "/home/jens/work/repos/JayFilter", + "file": "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.cpp", + "output": "/home/jens/work/repos/JayFilter/build/linux/release/Filter/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.o" + }, + { + "arguments": [ + "/usr/bin/clang", + "-fPIC", + "-g", + "-O3", + "-DVST_2_4_EXTENSIONS=0", + "-DVST_2_3_EXTENSIONS=1", + "-I", + "/home/jens/work/repos/JayFilter/src", + "-I", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4", + "-c", + "-o", + "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/iir.o", + "src/iir.c" + ], + "directory": "/home/jens/work/repos/JayFilter", + "file": "/home/jens/work/repos/JayFilter/src/iir.c", + "output": "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/iir.o" + }, + { + "arguments": [ + "/usr/bin/clang", + "-fPIC", + "-g", + "-O3", + "-DVST_2_4_EXTENSIONS=0", + "-DVST_2_3_EXTENSIONS=1", + "-I", + "/home/jens/work/repos/JayFilter/src", + "-I", + "/home/jens/work/repos/JayFilter/sdk/vst/vstsdk2.4", + "-c", + "-o", + "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/paramutils.o", + "src/paramutils.c" + ], + "directory": "/home/jens/work/repos/JayFilter", + "file": "/home/jens/work/repos/JayFilter/src/paramutils.c", + "output": "/home/jens/work/repos/JayFilter/build/linux/release/Filter/src/paramutils.o" + } +] diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9cf9fa6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "test_buffer", + "type": "lldb", + "request": "launch", + "program": "${workspaceRoot}/build/linux/debug/test_main/test_main", + "args": [], + "cwd": "${workspaceRoot}" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f216e64 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "C_Cpp.intelliSenseEngine": "disabled" +} + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..128596b --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +include make/defaults.mk +NAME := Delay +CONFIG ?= debug +TARGET ?= JayDelay.so + +CFLAGS += -fPIC +CXXFLAGS += -fPIC +CXXFLAGS += -std=c++20 + +VST2_SDK_PATH := $(realpath sdk/vst/vstsdk2.4) +INCLUDES += -I $(realpath src) +INCLUDES += -I $(VST2_SDK_PATH) +INCLUDES += -I $(realpath submodules/dsp) + +DEFINES += -DVST_2_4_EXTENSIONS=0 -DVST_2_3_EXTENSIONS=1 + +GCC_SRCS := src/iir.c src/paramutils.c +CXX_SRCS := src/filter.cpp src/filterMain.cpp +CXX_SRCS += $(VST2_SDK_PATH)/public.sdk/source/vst2.x/audioeffect.cpp +CXX_SRCS += $(VST2_SDK_PATH)/public.sdk/source/vst2.x/audioeffectx.cpp + +LIBS := -lstdc++ -lm +LDFLAGS += $(TARGET_ARCH) $(LIBDIR) -shared + +all: link + +test: + make -C ./submodules/dsp/tests/ + +install: all + cp build/linux/$(CONFIG)/$(NAME)/$(TARGET) ~/.vst/ + +include $(MAKE_HOME)/compile.mk +include $(MAKE_HOME)/link.mk diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/make/defaults.mk b/make/defaults.mk new file mode 100644 index 0000000..6f12ad2 --- /dev/null +++ b/make/defaults.mk @@ -0,0 +1,6 @@ +include $(MAKE_HOME)/defaults.mk + +# Environment +CC=clang +CCC=clang++ +CXX=clang++ diff --git a/rebuild_compile_commands.sh b/rebuild_compile_commands.sh new file mode 100755 index 0000000..bc8d08e --- /dev/null +++ b/rebuild_compile_commands.sh @@ -0,0 +1,10 @@ +#/usr/bin/env bash +export MAKE_HOME=$HOME/work/repos/JayDelay/submodules/make +OUTPUT=build/compile_commands.json +make clean +bear --config /home/jens/work/repos/JayDelay/.vscode/c_cpp_properties.json --append --output $OUTPUT -- make + +make -C submodules/dsp/tests/ clean +bear --config /home/jens/work/repos/JayDelay/.vscode/c_cpp_properties.json --append --output $OUTPUT -- make -C submodules/dsp/tests/ + + diff --git a/sdk/vst/.gitignore b/sdk/vst/.gitignore new file mode 100644 index 0000000..60a08ff --- /dev/null +++ b/sdk/vst/.gitignore @@ -0,0 +1,2 @@ +vstsdk2.4 + diff --git a/sdk/vst/Makefile b/sdk/vst/Makefile new file mode 100644 index 0000000..1d6fe39 --- /dev/null +++ b/sdk/vst/Makefile @@ -0,0 +1,6 @@ +CONFIG ?= release +PKG_VER := vstsdk2.4 + +include pkg.mk + + diff --git a/sdk/vst/pkg.mk b/sdk/vst/pkg.mk new file mode 100644 index 0000000..aadddaa --- /dev/null +++ b/sdk/vst/pkg.mk @@ -0,0 +1,40 @@ +BUILD_DIR := ./build/${CONFIG} +PKG_ROOT := ./${PKG_VER} +OBJS := $(addprefix ${BUILD_DIR}/, $(subst .cpp,.o,$(SRCS))) + +.PHONY: ${PKG_VER}.patch +all: ${PKG_ROOT} +prepare: ${PKG_ROOT} +patch: ${PKG_VER}.patch + +${PKG_VER}.patch: + @rm -rf temp + @unzip ${PKG_VER}.zip -d temp >/dev/null + @diff -ruN temp/${PKG_VER}/ ${PKG_ROOT} > ${PKG_VER}.patch; [ $$? -eq 1 ] + @rm -rf temp + @echo "Created" ${PKG_VER}.patch + +CXXFLAGS += -std=c++11 +CXXFLAGS_debug := ${CXXFLAGS} -O0 -g +CXXFLAGS_release := ${CXXFLAGS} -O2 + +INCLUDES += -I./ -I/usr/include/freetype2 +DEFINES += -D${TARGET} + +${OBJS}: $(BUILD_DIR)/%.o : ${PKG_ROOT}/%.cpp + mkdir -p $(dir $@) + g++ ${CXXFLAGS_${CONFIG}} ${DEFINES} ${INCLUDES} -o $@ -c $< + +${PKG_ROOT}: + unzip ${PKG_VER}.zip + if [ -e ${PKG_VER}.patch ]; then \ + patch -p0 < ${PKG_VER}.patch;\ + fi + +clean: + rm -rf ${BUILD_DIR}/* + +distclean: + rm -rf ${BUILD_DIR} + rm -rf ${PKG_ROOT} + diff --git a/sdk/vst/vstsdk2.4.patch b/sdk/vst/vstsdk2.4.patch new file mode 100644 index 0000000..5b8371e --- /dev/null +++ b/sdk/vst/vstsdk2.4.patch @@ -0,0 +1,24 @@ +diff -ruN temp/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp ./vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp +--- temp/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp 2006-06-07 09:22:02.000000000 +0200 ++++ ./vstsdk2.4/public.sdk/source/vst2.x/audioeffect.cpp 2025-08-02 10:01:34.082302630 +0200 +@@ -7,7 +7,7 @@ + // Created by : Steinberg Media Technologies + // Description : Class AudioEffect (VST 1.0) + // +-// © 2006, Steinberg Media Technologies, All Rights Reserved ++// � 2006, Steinberg Media Technologies, All Rights Reserved + //------------------------------------------------------------------------------------------------------- + + #include "audioeffect.h" +@@ -507,9 +507,10 @@ + { + VstInt32 digit = value / div; + value -= digit * div; ++ const char digit8 = (char)(digit & 0xFF) + '0'; + if (state || digit > 0) + { +- char temp[2] = {'0' + (char)digit, '\0'}; ++ char temp[2] = {digit8, '\0'}; + vst_strncat (text, temp, maxLen); + state = true; + } diff --git a/sdk/vst/vstsdk2.4.zip b/sdk/vst/vstsdk2.4.zip new file mode 100644 index 0000000..8789bef Binary files /dev/null and b/sdk/vst/vstsdk2.4.zip differ diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/src/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/src/config.mk b/src/config.mk new file mode 100644 index 0000000..e69de29 diff --git a/src/filter.cpp b/src/filter.cpp new file mode 100755 index 0000000..b4bf6d9 --- /dev/null +++ b/src/filter.cpp @@ -0,0 +1,288 @@ +/*----------------------------------------------------------------------------- + +� 1999, Steinberg Soft und Hardware GmbH, All Rights Reserved + +-----------------------------------------------------------------------------*/ + +#ifdef WIN32 +#include +#endif +#include +#include +#include "iir.h" +#include "filter.hpp" +#include "paramutils.h" + +#define NUM_PARMS 7 +#define MAX_ORDER 10 +#define MAX_TYPES 4 +#define MAX_Q 10.0f +#define ALPHA 0.2f +#define BETA (1.0f-ALPHA) + +const char * const pFTypeString[8] = +{ + "Unknown", + "Lowpass", + "Highpass", + "Bandpass", + "Bandstop", + "Peaking", + "Low-Shelving", + "High-Shelving" +}; + +enum {ORDER, TYPE, FMIN, FMAX, FG, Q, TESTPARAM}; +char *pParmStr[NUM_PARMS] = {"Order","Filter-Type","Freq min","Freq max","Frequency","Resonance","Test-Param"}; + +AudioEffect* createEffectInstance (audioMasterCallback audioMaster) +{ + return new Filter (audioMaster); +} + +//----------------------------------------------------------------------------- +Filter::Filter(audioMasterCallback audioMaster) +: AudioEffectX(audioMaster, 1, NUM_PARMS) // 1 program, 1 parameter only +//, m_reverb_1({(uint)(48000*0.02), (uint)(48000*0.04), (uint)(48000*0.08), (uint)(48000*0.16)}, (uint)(48000*0.1), (uint)(48000*0.2)) +//, m_reverb_2({(uint)(48000*0.02), (uint)(48000*0.04), (uint)(48000*0.08), (uint)(48000*0.16)}, (uint)(48000*0.1), (uint)(48000*0.2)) +, m_reverb_1({(uint)(48000*0.48)}, (uint)(48000*0.1), (uint)(48000*0.2)) +, m_reverb_2({(uint)(48000*0.48)}, (uint)(48000*0.1), (uint)(48000*0.2)) +{ + sampleRate = 48000; + fg = 1000/sampleRate; // default to 1000 Hz + order = 4; + q = 1.0f/MAX_Q; + type = IIR_FILTERTYPE_LOWPASS; + setNumInputs(2); // stereo in + setNumOutputs(2); // stereo out + setUniqueID('Filt'); // identify + canMono(); // makes sense to feed both inputs with the same signal + canProcessReplacing(); // supports both accumulating and replacing output + strcpy(programName, "Default"); // default program name + IIRInit(filterCoeff_L, order); + IIRInit(filterCoeff_R, order); + sm_fg = fg; + sm_q = q; + testParam=0; + + IIRCalcFilterCoeff(filterCoeff_L, sampleRate, sm_fg*sampleRate, sm_q, order, type); + IIRCalcFilterCoeff(filterCoeff_R, sampleRate, sm_fg*sampleRate, sm_q, order, type); + forder = (0.5f/MAX_ORDER)*(float)(order -1); + ftype = (1.0f/MAX_TYPES)*(float)(type -1); + f_fmin = 0; + f_fmax = 17300.f/sampleRate; +} + +//----------------------------------------------------------------------------------------- +Filter::~Filter() +{ + // nothing to do here +} + +//----------------------------------------------------------------------------------------- +void Filter::setProgramName(char *name) +{ + strcpy(programName, name); +} + +//----------------------------------------------------------------------------------------- +void Filter::getProgramName(char *name) +{ + strcpy(name, programName); +} + +//----------------------------------------------------------------------------------------- +void Filter::setParameter(VstInt32 index, float value) +{ + fg = f_fmin + value*(f_fmax-f_fmin); + + + switch(index) + { + case TYPE: + + ftype = ParamQuantize(value,1.0f/(MAX_TYPES-1)); + + type = 1 + (VstInt32)(ftype*(MAX_TYPES-1)); + IIRCalcFilterCoeff(filterCoeff_L, sampleRate, 0.5f*fg*sampleRate, q*MAX_Q, order, type); + IIRCalcFilterCoeff(filterCoeff_R, sampleRate, 0.5f*fg*sampleRate, q*MAX_Q, order, type); + break; + + case ORDER: + forder = ParamQuantize(value,1.0f/(MAX_ORDER/2-1)); + order = 2*(VstInt32)(1+forder*MAX_ORDER/2); + sprintf(dbgStr, "value = %f, forder = %f, order = %d",value,forder,order); +// OutputDebugString(dbgStr); + IIRCalcFilterCoeff(filterCoeff_L, sampleRate, 0.5f*fg*sampleRate, q*MAX_Q, order, type); + IIRCalcFilterCoeff(filterCoeff_R, sampleRate, 0.5f*fg*sampleRate, q*MAX_Q, order, type); + break; + + case FMIN: + f_fmin = value; + break; + + case FMAX: + f_fmax = value; + break; + + case FG: + f_fg_param = value; + break; + + case Q: + q = value; + break; + + case TESTPARAM: + testParam=ParamQuantize(value,1.0f/3); + sprintf(dbgStr, "Set Param: %f",value); +// OutputDebugString(dbgStr); + break; + } + +} + +//----------------------------------------------------------------------------------------- +float Filter::getParameter(VstInt32 index) +{ + float value = 0; + + switch(index) + { + case TYPE: + value = (float)ftype; + break; + + case ORDER: + value = (float)forder; + break; + + case FMIN: + value = f_fmin; + break; + + case FMAX: + value = f_fmin; + break; + + case FG: + value = f_fg_param; + break; + + case Q: + value = q; + break; + + case TESTPARAM: + value = testParam; + sprintf(dbgStr, "Get Param: %f",value); +// OutputDebugString(dbgStr); + break; + } + return value; +} + +//----------------------------------------------------------------------------------------- +void Filter::getParameterName(VstInt32 index, char *label) +{ + strcpy(label,pParmStr[index]); +} + +//----------------------------------------------------------------------------------------- +void Filter::getParameterDisplay(VstInt32 index, char *text) +{ + + switch(index) + { + case TYPE: + strcpy(text, pFTypeString[type]); + break; + case ORDER: + snprintf(text, kVstMaxParamStrLen, "%d", order); + break; + case FMIN: + float2string(0.5f*f_fmin*sampleRate,text, kVstMaxParamStrLen); + break; + case FMAX: + float2string(0.5f*f_fmax*sampleRate,text, kVstMaxParamStrLen); + break; + case FG: + float2string(0.5f*fg*sampleRate,text, kVstMaxParamStrLen); + break; + case Q: + float2string(q*MAX_Q,text, kVstMaxParamStrLen); + break; + case TESTPARAM: + float2string(testParam,text, kVstMaxParamStrLen); + break; + + } +} + +//----------------------------------------------------------------------------------------- +void Filter::getParameterLabel(VstInt32 index, char *label) +{ + switch(index) + { + case TYPE: + strcpy(label, " "); + break; + case ORDER: + strcpy(label, " "); + break; + case FMIN: + strcpy(label, " Hz "); + break; + case FMAX: + strcpy(label, " Hz "); + break; + case FG: + strcpy(label, " Hz "); + break; + case Q: + strcpy(label, " "); + break; + case TESTPARAM: + strcpy(label, " Test "); + break; + } +} + +//----------------------------------------------------------------------------------------- +void Filter::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) +{ + float *in1 = inputs[0]; + float *in2 = inputs[1]; + float *out1 = outputs[0]; + float *out2 = outputs[1]; + + sm_fg = BETA*sm_fg+ALPHA*fg; + sm_q = BETA*sm_q+ALPHA*q*MAX_Q; + + IIRCalcFilterCoeff(filterCoeff_L, sampleRate, 0.5f*sm_fg*sampleRate, sm_q, order, type); + IIRCalcFilterCoeff(filterCoeff_R, sampleRate, 0.5f*sm_fg*sampleRate, sm_q, order, type); + +// IIR(filterCoeff_L, in1, out1, order, sampleFrames); +// IIR(filterCoeff_R, in2, out2, order, sampleFrames); + + m_reverb_1.setFeedbackGain(sm_fg); + m_reverb_2.setFeedbackGain(sm_fg); + m_reverb_1.process_multi(in1, out1, sampleFrames); + m_reverb_2.process_multi(in2, out2, sampleFrames); +} + +//----------------------------------------------------------------------------------------- +void Filter::setSampleRate(float sampleRate) +{ + this->sampleRate = sampleRate; + sprintf(dbgStr, "Sample Rate = %f",sampleRate); +// OutputDebugString(dbgStr); +} + +//----------------------------------------------------------------------------------------- +void Filter::setBlockSize(VstInt32 blockSize) +{ + this->blockSize = blockSize; + sprintf(dbgStr, "Block Size = %d",blockSize); +// OutputDebugString(dbgStr); +} diff --git a/src/filter.hpp b/src/filter.hpp new file mode 100755 index 0000000..fc760ad --- /dev/null +++ b/src/filter.hpp @@ -0,0 +1,50 @@ +/*----------------------------------------------------------------------------- + +� 1999, Steinberg Soft und Hardware GmbH, All Rights Reserved + +-----------------------------------------------------------------------------*/ +#ifndef __FILTER_H +#define __FILTER_H + +#include "public.sdk/source/vst2.x/audioeffectx.h" +#include +#include "iir.h" + +class Filter : public AudioEffectX +{ +public: + Filter(audioMasterCallback audioMaster); + ~Filter(); + + // Processing + virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames); + + // Program + virtual void setProgramName (char* name); + virtual void getProgramName (char* name); + + // Parameters + 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); + +protected: + float ftype, forder, fg, q, sm_fg, sm_q, testParam; + float f_fmin, f_fmax, f_fg_param; + VstInt32 type, order; + char programName[32]; + char dbgStr[80]; + IIRPARAM filterParms; + IIRCOEFF filterCoeff_L[8], filterCoeff_R[8]; + +private: + Reverb m_reverb_1; + Reverb m_reverb_2; +}; + +#endif diff --git a/src/filterMain.cpp b/src/filterMain.cpp new file mode 100755 index 0000000..41bf085 --- /dev/null +++ b/src/filterMain.cpp @@ -0,0 +1,32 @@ +/*----------------------------------------------------------------------------- + +� 1999, Steinberg Soft und Hardware GmbH, All Rights Reserved + +-----------------------------------------------------------------------------*/ +#include "filter.hpp" // *change* + +static AudioEffect *effect = 0; +bool oome = false; + +AEffect *VSTPluginMain (audioMasterCallback audioMaster) +{ + // get vst version + if (!audioMaster (0, audioMasterVersion, 0, 0, 0, 0)) + return 0; // old version + + effect = new Filter (audioMaster); + if (!effect) + return 0; + if (oome) + { + delete effect; + return 0; + } + return effect->getAeffect (); +} + +extern "C" __cdecl AEffect* deprecated_main( + audioMasterCallback audioMaster) asm("main"); +__cdecl AEffect* deprecated_main(audioMasterCallback audioMaster) { + return VSTPluginMain(audioMaster); +} diff --git a/src/iir.c b/src/iir.c new file mode 100644 index 0000000..88a7a59 --- /dev/null +++ b/src/iir.c @@ -0,0 +1,225 @@ +/************************************************************************* +** iir.c +**************************************************************************/ +#include "stdio.h" +#include "math.h" +#include "iir.h" + +/************************************************************************* +** Global Variables +**************************************************************************/ +const char *filterTypeString[] = +{ + "Unknown filter type", + "Butterworth-Lowpass", + "Butterworth-Highpass", + "Butterworth-Bandpass", + "Butterworth-Bandstop", + "Peaking-EQ", + "Low Shelving-EQ", + "High Shelving-EQ" +}; + +/******************************************************************************/ +void IIRCalcFilterCoeff(struct _sIIRCoeff *pCoeff, float fa, float fg, float q, unsigned order, unsigned filterType) +{ + unsigned p; + float qp; + + //IIRInit(pCoeff, order); + + for(p=0; p < order/2;p++) + { + qp = q * IIRCalcQp(p+1, order); + IIRCalcPartFilterCoeff2(&pCoeff[p], 1.0, fa, fg, qp, filterType); + } +} + +int IIRCalcPartFilterCoeff1(struct _sIIRCoeff *pCoeff, float fa, float fg, float Qi, unsigned filterType) +{ + float K, a0; + float alpha, omega, ks, kc; + unsigned error; + + omega = (float)(2*pi*fg/fa); + ks = (float)sin(omega); + kc = (float)cos(omega); + alpha = (float)(0.5*ks /Qi); + + K = IIRBilTrans(fg, fa); + a0 = K/Qi + 1; + + switch(filterType) + { + case IIR_FILTERTYPE_LOWPASS: + + pCoeff->ak0 = 1.0; + pCoeff->ak1 = (1 - K/Qi)/a0; + pCoeff->ak2 = 0.0; + + pCoeff->bk0 = (float)(1.0/a0); + pCoeff->bk1 = (float)(1.0/a0); + pCoeff->bk2 = (float)0.0; + + break; + + case IIR_FILTERTYPE_HIGHPASS: + + pCoeff->ak0 = 1.0; + pCoeff->ak1 = (1 - K/Qi) /a0; + pCoeff->ak2 = 0.0; + + pCoeff->bk0 = (float)(1.0*K /a0); + pCoeff->bk1 = (float)(-1.0*K /a0); + pCoeff->bk2 = (float)0.0; + + break; + + default: + error = -1; + break; + } + return error; +} + +int IIRCalcPartFilterCoeff2(struct _sIIRCoeff *pCoeff, float A, float fa, float fg, float qp, unsigned filterType) +{ + float a0; + float alpha, omega, ks, kc; + unsigned error; + + omega = (float)(2*pi*fg/fa); + ks = (float)sin(omega); + kc = (float)cos(omega); + alpha = (float)(0.5*ks /qp); + + error = 0; + switch(filterType) + { + case IIR_FILTERTYPE_LOWPASS: + + a0 = 1 + alpha; + pCoeff->ak0 = 1.0; + pCoeff->ak1 = (float)(-2.0*kc /a0); + pCoeff->ak2 = (1 - alpha) /a0; + + pCoeff->bk0 = (float)(0.5*(1 - kc) /a0); + pCoeff->bk1 = (1 - kc) /a0; + pCoeff->bk2 = (float)(0.5*(1 - kc) /a0); + + break; + + case IIR_FILTERTYPE_HIGHPASS: + + a0 = 1 + alpha; + pCoeff->ak0 = 1.0; + pCoeff->ak1 = (float)(-2.0*kc /a0); + pCoeff->ak2 = (1 - alpha) /a0; + + pCoeff->bk0 = (float)(0.5*(1 + kc) /a0); + pCoeff->bk1 = -(1 + kc) /a0; + pCoeff->bk2 = (float)(0.5*(1 + kc) /a0); + + break; + + case IIR_FILTERTYPE_BANDPASS: + + a0 = 1 + alpha; + pCoeff->ak0 = 1.0; + pCoeff->ak1 = (float)(-2.0*kc /a0); + pCoeff->ak2 = (1 - alpha) /a0; + + pCoeff->bk0 = alpha /a0; + pCoeff->bk1 = 0; + pCoeff->bk2 = -alpha /a0; + + break; + + case IIR_FILTERTYPE_BANDSTOP: + + a0 = 1 + alpha; + pCoeff->ak0 = 1.0; + pCoeff->ak1 = (float)(-2.0*kc /a0); + pCoeff->ak2 = (1 - alpha) /a0; + + pCoeff->bk0 = (float)(1.0 /a0); + pCoeff->bk1 = (float)(-2.0*kc /a0); + pCoeff->bk2 = (float)(1.0 /a0); + + break; + + case IIR_FILTERTYPE_PEAKING: + + a0 = 1 + (alpha/A); + pCoeff->ak0 = 1.0; + pCoeff->ak1 = (float)(-2.0*kc /a0); + pCoeff->ak2 = (1 - (alpha/A)) /a0; + + pCoeff->bk0 = (1 + (alpha*A)) /a0; + pCoeff->bk1 = (float)(-2.0*kc /a0); + pCoeff->bk2 = (1 - (alpha*A)) /a0; + + break; + + default: + error = -1; + break; + } + return error; +} + +void IIR(struct _sIIRCoeff *pCoeff, float *xn, float *yn, unsigned order, unsigned numPoints) +{ + float xp, yp; + unsigned i, p; + unsigned numSec = order/2; + + for (i=0; i + +#define pi 3.1415926535897932384626433832795 + +#define IIR_FILTERTYPE_UNKNOWN 0x00000000 +#define IIR_FILTERTYPE_LOWPASS 0x00000001 +#define IIR_FILTERTYPE_HIGHPASS 0x00000002 +#define IIR_FILTERTYPE_BANDPASS 0x00000003 +#define IIR_FILTERTYPE_BANDSTOP 0x00000004 +#define IIR_FILTERTYPE_PEAKING 0x00000005 +#define IIR_FILTERTYPE_LOWSHELF 0x00000006 +#define IIR_FILTERTYPE_HIGHSHELF 0x00000007 + +#if defined(__cplusplus) +extern "C" { +#endif +/******************************************************************************/ +typedef struct _sComplex +{ + float pRealData, pImagData; +} Complex; + +typedef struct _sIIRCoeff +{ + + float ak0, ak1, ak2; + float bk0, bk1, bk2; + float xn1, xn2; + float yn1, yn2; + +}IIRCOEFF; + +typedef struct _sIIRParam +{ + /* General Params */ + float fg, Qf; + + /* for shelving EQs */ + float beta; + + /* for peaking and shelving EQs */ + float A; +}IIRPARAM; + +/******************************************************************************/ +void IIRInit(struct _sIIRCoeff *pCoeff, unsigned order); +int IIRCalcPartFilterCoeff1(struct _sIIRCoeff *pCoeff, float fa, float fg, float qp, unsigned filterType); +int IIRCalcPartFilterCoeff2(struct _sIIRCoeff *pCoeff, float A, float fa, float fg, float qp, unsigned filterType); +void IIRCalcFilterCoeff(struct _sIIRCoeff *pCoeff, float fa, float fg, float q, unsigned order, unsigned filterType); + +float IIRBilTrans(float fg, float fa); +float IIRCalcQp(unsigned p, unsigned N); +void IIR(struct _sIIRCoeff *pCoeff, float *xn, float *yn, unsigned order, unsigned numPoints); +void IIRPrintCoeff(FILE *pFile, struct _sIIRCoeff *pCoeff, unsigned N); +void ScaleCoeff(struct _sIIRCoeff *pCoeff); +float MinMag(float val1, float val2); +float MaxMag(float val1, float val2); + +/******************************************************************************/ +#if defined(__cplusplus) +} +#endif + +#endif /* IIR_H */ diff --git a/src/paramutils.c b/src/paramutils.c new file mode 100755 index 0000000..5c92966 --- /dev/null +++ b/src/paramutils.c @@ -0,0 +1,13 @@ +#include + +float ParamQuantize(float value, float quantization) +{ + + float result = 1.0; + float k = (float) ceil(value / quantization); + + if ((k*quantization) < 1.0) + result = k*quantization; + + return result; +} diff --git a/src/paramutils.h b/src/paramutils.h new file mode 100755 index 0000000..0edff7e --- /dev/null +++ b/src/paramutils.h @@ -0,0 +1,19 @@ +/***************************************************************/ +/* paramutils.h +/***************************************************************/ +#ifndef PARAMUTILS_H +#define PARAMUTILS_H +#if defined(__cplusplus) +extern "C" { +#endif +/***************************************************************/ + +float ParamQuantize(float value, float quantization); + + +/***************************************************************/ +#if defined(__cplusplus) +} +#endif /* cplusplus */ + +#endif /* PARAMUTILS_H */