// 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 #include #include #include "vestige.h" namespace { struct FakeState { float phase = 0.0f; int32 sampleRate = 44100; float gain = 0.5f; // param 0 — "Gain" (0..1) }; FakeState g_state; void* g_audioMaster = nullptr; void VSTCALLBACK fakeSetParameter (AEffect* effect, int32 index, float value) { if (index == 0) { g_state.gain = value; // Báo host: param đổi từ editor/plugin (T11) — chống loop host-side. if (g_audioMaster) { typedef VstIntPtr (VSTCALLBACK* AMFn) (AEffect*, int32, int32, VstIntPtr, void*, float); reinterpret_cast (g_audioMaster) (effect, audioMasterAutomate, index, 0, nullptr, value); } } } float VSTCALLBACK fakeGetParameter (AEffect*, int32 index) { if (index == 0) return g_state.gain; return 0.0f; } 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 (opt); return 1; case effMainsChanged: return 1; case effStartProcess: case effStopProcess: return 1; case effEditGetRect: { static ERect rect = {0, 0, 300, 400}; *reinterpret_cast (ptr) = ▭ return 1; } case effEditOpen: return 1; case effEditClose: return 1; case effProcessEvents: return 1; case effGetEffectName: std::strncpy (static_cast (ptr), "FakeVST2", 64); return 1; case effGetVendorString: std::strncpy (static_cast (ptr), "SonicForgeStudio", 64); return 1; case effGetProductString: std::strncpy (static_cast (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 (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* audioMaster) { g_audioMaster = audioMaster; 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.setParameter = &fakeSetParameter; g_effect.getParameter = &fakeGetParameter; g_effect.numInputs = [] (AEffect*) -> int32 { return 0; }; g_effect.numOutputs = [] (AEffect*) -> int32 { return 2; }; g_effect.numParams = [] (AEffect*) -> int32 { return 1; }; 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) { return createInstance (audioMaster); }