T10: VST2 engine bridge (vestige.h clean-room, VST2AudioEngine.cpp, fake_vst2 test plugin)
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
// fake_vst2.cpp — test plugin VST2 tối thiểu để verify bridge T10.
|
||||
// Sine 440Hz stereo qua processReplacing; editor trả rect giả.
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include "vestige.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct FakeState
|
||||
{
|
||||
float phase = 0.0f;
|
||||
int32 sampleRate = 44100;
|
||||
};
|
||||
|
||||
FakeState g_state;
|
||||
|
||||
int32 VSTCALLBACK fakeDispatcher (AEffect* effect, int32 opcode, int32 index,
|
||||
VstIntPtr value, void* ptr, float opt)
|
||||
{
|
||||
(void) index;
|
||||
(void) value;
|
||||
(void) ptr;
|
||||
(void) opt;
|
||||
switch (opcode)
|
||||
{
|
||||
case effOpen:
|
||||
return 1;
|
||||
case effClose:
|
||||
return 1;
|
||||
case effSetSampleRate:
|
||||
g_state.sampleRate = static_cast<int32> (opt);
|
||||
return 1;
|
||||
case effMainsChanged:
|
||||
return 1;
|
||||
case effStartProcess:
|
||||
case effStopProcess:
|
||||
return 1;
|
||||
case effEditGetRect:
|
||||
{
|
||||
static ERect rect = {0, 0, 300, 400};
|
||||
*reinterpret_cast<ERect**> (ptr) = ▭
|
||||
return 1;
|
||||
}
|
||||
case effEditOpen:
|
||||
return 1;
|
||||
case effEditClose:
|
||||
return 1;
|
||||
case effProcessEvents:
|
||||
return 1;
|
||||
case effGetEffectName:
|
||||
std::strncpy (static_cast<char*> (ptr), "FakeVST2", 64);
|
||||
return 1;
|
||||
case effGetVendorString:
|
||||
std::strncpy (static_cast<char*> (ptr), "SonicForgeStudio", 64);
|
||||
return 1;
|
||||
case effGetProductString:
|
||||
std::strncpy (static_cast<char*> (ptr), "FakeVST2", 64);
|
||||
return 1;
|
||||
case effGetVendorVersion:
|
||||
return 1;
|
||||
case effIdentify:
|
||||
return CCONST ('N', 'v', 'E', 'f');
|
||||
case effCanDo:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VSTCALLBACK fakeProcessReplacing (AEffect*, float** inputs, float** outputs,
|
||||
int32 sampleFrames)
|
||||
{
|
||||
(void) inputs;
|
||||
float* outL = outputs[0];
|
||||
float* outR = outputs[1];
|
||||
const float freq = 440.0f;
|
||||
const float dt = freq / static_cast<float> (g_state.sampleRate);
|
||||
for (int32 i = 0; i < sampleFrames; ++i)
|
||||
{
|
||||
float v = 0.25f * std::sin (2.0f * 3.14159265f * g_state.phase);
|
||||
g_state.phase += dt;
|
||||
if (g_state.phase >= 1.0f)
|
||||
g_state.phase -= 1.0f;
|
||||
outL[i] = v;
|
||||
outR[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
AEffect g_effect;
|
||||
|
||||
AEffect* VSTCALLBACK createInstance (void*)
|
||||
{
|
||||
std::memset (&g_effect, 0, sizeof (g_effect));
|
||||
g_effect.magic = CCONST ('V', 's', 't', 'P');
|
||||
g_effect.dispatcher = &fakeDispatcher;
|
||||
g_effect.processReplacing = &fakeProcessReplacing;
|
||||
g_effect.numInputs = [] (AEffect*) -> int32 { return 0; };
|
||||
g_effect.numOutputs = [] (AEffect*) -> int32 { return 2; };
|
||||
g_effect.numParams = [] (AEffect*) -> int32 { return 0; };
|
||||
g_effect.numPrograms = [] (AEffect*) -> int32 { return 0; };
|
||||
g_effect.flags = [] (AEffect*) -> int32 { return effFlagsCanReplacing | effFlagsIsSynth; };
|
||||
g_effect.uniqueID = CCONST ('F', 'k', '2', 'V');
|
||||
g_effect.version = 1;
|
||||
return &g_effect;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" __declspec (dllexport) AEffect* VSTPluginMain (void* audioMaster)
|
||||
{
|
||||
(void) audioMaster;
|
||||
return createInstance (audioMaster);
|
||||
}
|
||||
Reference in New Issue
Block a user