Files
SonicForgeStudio/native_bridge/vestige/aeffect.h
T
admin 4111995a5c Add VST2 hosting to native bridge; fix CC7 data2 routing verified via SHM test
VST2 (Steinberg 2.4 ABI) host via Vst2Instrument: aeffect.h, dispatcher,
process events/replacing, kEffectStartProcess, headless GUI skip.
- create_instrument returns Vst2Instrument for InstrumentType::VST2
- 64B-aligned scratch buffers for SIMD plugins; SEH crash capture module+stack
- plugins.py: VST2 resolves .dll/.so; vst_engine.py reports VST2 type
- app.jsx: derive instrumentType from scan (VST3 vs VST2), not hardcoded
- Install exes refreshed from Release build

SF2 FluidSynth audio verified end-to-end through SHM ring (energy 1.33):
silence was a test-harness bug (CC7 value written to velocity field, bridge
reads data2) — app sends data2 correctly. All temporary diagnostics removed.
2026-08-17 07:55:46 +07:00

177 lines
6.1 KiB
C++

// native_bridge/vestige/aeffect.h
// Clean-room VST2.4 host ABI header (64-bit Windows).
//
// Written from the public VST2.4 interface specification (structure layout,
// dispatcher opcode numbers, flag bits) — NOT copied from Steinberg's SDK or
// from LMMS's vestige (LMMS is GPL-2.0+; reusing it would re-taint the bridge
// with GPL, defeating this repo's license cleanup). Only ABI facts are
// encoded here; all prose is original.
//
// A VST2 plugin is a DLL exporting `VSTPluginMain` (modern) or `main`
// (legacy): AEffect* VSTPluginMain(audioMasterCallback host).
#ifndef VESTIGE_AEFFECT_H
#define VESTIGE_AEFFECT_H
#include <cstdint>
struct AEffect; // forward decl so the callback typedefs below can reference it
// intptr_t: VST2 ABI uses pointer-sized integers on 64-bit hosts.
typedef intptr_t (*dispatcherProc)(AEffect* effect, int32_t opcode,
int32_t index, intptr_t value,
void* ptr, float opt);
typedef void (*processProc)(AEffect* effect, float** inputs, float** outputs,
int32_t sampleFrames);
typedef void (*setParameterProc)(AEffect* effect, int32_t index, float value);
typedef float (*getParameterProc)(AEffect* effect, int32_t index);
typedef void (*processReplacingProc)(AEffect* effect, float** inputs,
float** outputs, int32_t sampleFrames);
typedef void (*processDoubleReplacingProc)(AEffect* effect, double** inputs,
double** outputs,
int32_t sampleFrames);
typedef intptr_t (*audioMasterCallback)(AEffect* effect, int32_t opcode,
int32_t index, intptr_t value,
void* ptr, float opt);
struct AEffect {
int32_t magic; // 'VstP' == 0x56737450
dispatcherProc dispatcher;
processProc process;
setParameterProc setParameter;
getParameterProc getParameter;
int32_t numPrograms;
int32_t numParams;
int32_t numInputs;
int32_t numOutputs;
int32_t flags;
intptr_t resvd1; // pointer-sized per VST2.4 ABI
intptr_t resvd2;
int32_t initialDelay;
int32_t realQualities;
int32_t offQualities;
float ioRatio;
void* object;
void* user;
int32_t uniqueID;
int32_t version;
processReplacingProc processReplacing;
processDoubleReplacingProc processDoubleReplacing;
char future[56]; // reserved for future use (must stay intact)
};
// Plugin capability flag bits (AEffect::flags).
#define kEffectFlagsHasEditor (1 << 0)
#define kEffectFlagsHasClip (1 << 1)
#define kEffectFlagsHasVu (1 << 2)
#define kEffectFlagsCanMono (1 << 3)
#define kEffectFlagsCanReplacing (1 << 4)
#define kEffectFlagsProgramChunks (1 << 5)
#define kEffectFlagsIsSynth (1 << 8)
#define kEffectFlagsNoSoundInStop (1 << 9)
#define kEffectFlagsCanDoubleReplacing (1 << 12)
// Dispatcher opcodes (VST 2.4 numbering).
enum {
kEffectOpen = 0, // effOpen
kEffectClose = 1, // effClose
kEffectSetProgram = 2, // effSetProgram
kEffectGetProgram = 3, // effGetProgram
kEffectSetSampleRate = 10, // effSetSampleRate
kEffectSetBlockSize = 11, // effSetBlockSize
kEffectMainsChanged = 12, // effMainsChanged (value 1 = on, 0 = off)
kEffectGetChunk = 23, // effGetChunk
kEffectSetChunk = 24, // effSetChunk
kEffectProcessEvents = 25, // effProcessEvents
kEffectGetPlugCategory = 35,
kEffectGetEffectName = 45,
kEffectGetVendorString = 47,
kEffectGetProductString = 48,
kEffectGetVendorVersion = 49,
kEffectCanDo = 51,
kEffectGetVstVersion = 58,
kEffectStartProcess = 71,
kEffectStopProcess = 72
};
// audioMaster opcodes (host callback).
enum {
kAudioMasterAutomate = 0,
kAudioMasterVersion = 1,
kAudioMasterCurrentId = 2,
kAudioMasterIdle = 3,
kAudioMasterWantMidi = 6,
kAudioMasterGetTime = 7,
kAudioMasterProcessEvents = 8,
kAudioMasterGetSampleRate = 16,
kAudioMasterGetBlockSize = 17,
kAudioMasterGetCurrentProcessLevel = 23,
kAudioMasterGetVendorString = 32,
kAudioMasterGetProductString = 33,
kAudioMasterGetVendorVersion = 34,
kAudioMasterVendorSpecific = 35,
kAudioMasterCanDo = 37,
kAudioMasterGetLanguage = 38
};
// MIDI event passed via effProcessEvents. The plugin receives a VstEvents
// array; each event starts with a VstEvent header, VstMidiEvent extends it.
struct VstEvent {
int32_t type; // kVstMidiType == 1 for MIDI events
int32_t byteSize; // sizeof(VstMidiEvent)
int32_t deltaFrames;
int32_t flags;
};
struct VstMidiEvent {
int32_t type; // kVstMidiType == 1
int32_t byteSize; // sizeof(VstMidiEvent)
int32_t deltaFrames;
int32_t flags;
int32_t noteLength; // in sample frames, if available, else 0
int32_t noteOffset; // offset into note, if available, else 0
char midiData[4]; // 1-3 MIDI bytes; midiData[3] reserved (zero)
char detune; // -64..+63 cents
char noteOffVelocity;
char reserved1;
char reserved2;
};
struct VstEvents {
int32_t numEvents;
intptr_t reserved;
VstEvent* events[2];
};
// Time info returned to kAudioMasterGetTime (host fills this).
struct VstTimeInfo {
double samplePos;
double sampleRate;
double nanoSeconds;
double ppqPos;
double tempo;
double barStartPos;
double cycleStartPos;
double cycleEndPos;
int32_t timeSigNumerator;
int32_t timeSigDenominator;
int32_t smpteOffset;
int32_t smpteFrameRate;
int32_t samplesToNextClock;
int32_t flags;
};
#define kVstMidiType 1
#define kEffectMagic 0x56737450 // 'VstP'
// VstTimeInfo::flags bits (kAudioMasterGetTime).
#define kVstTransportPlaying 1
#define kVstTransportCycleActive 2
#define kVstTransportChanged 4
#define kVstTempoValid 8
// Host responses for the plugin's capability probes (kEffectCanDo).
#define kCanDoYes 1
#define kCanDoNo 0
#endif // VESTIGE_AEFFECT_H