Files
SonicForgeStudio/native_bridge/vestige/aeffect.h
T
admin 6efef85e47 fix(bridge): VST2 host dung ABI SDK — crash outs>2, NaN input, editOpen(NULL), opcodes; docs A14 MIDI-out + phan tich Ozone -Inf
- aeffect.h: bo sung opcodes 4-22, 53, 55 + audioMaster 15/41-44 + ERect (dung chuan VST2.4 SDK, DUNE load OK khong crash)
- Vst2Instrument: cap du pointer arrays theo numInputs/numOutputs (fix AV 0xC0000005 Qin outs=32), input fill 0.0f (het NaN poison effect), bo probe effEditOpen(NULL) (crash WaveObserver), GetDirectory + SizeWindow hook, canDo sendVstEvents/sendVstTimeInfo
- TASKS.md: A14 MIDI-out tu plugin (Scaler2/Instacomposer/MelodicFlow xuat MIDI khong phai audio)
- PLAN_MASTERBUS_FX_RACK_VST.md: phan tich Ozone -Inf — chain day du, nguyen nhan = audio DAW khong chay qua bridge master ring
2026-08-19 20:57:16 +07:00

210 lines
7.9 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
kEffectSetProgramName = 4, // effSetProgramName (ptr = char* name)
kEffectGetProgramName = 5, // effGetProgramName (ptr = char* buffer)
kEffectGetParamLabel = 6, // effGetParamLabel (ptr = char* buffer)
kEffectGetParamDisplay = 7, // effGetParamDisplay (ptr = char* buffer)
kEffectGetParamName = 8, // effGetParamName (ptr = char* buffer)
kEffectGetVu = 9, // effGetVu (deprecated; occupies the slot so
// the core opcodes below match the SDK)
kEffectSetSampleRate = 10, // effSetSampleRate (opt = sample rate)
kEffectSetBlockSize = 11, // effSetBlockSize (value = block size)
kEffectMainsChanged = 12, // effMainsChanged (value 1 = on, 0 = off)
kEffectEditGetRect = 13, // effEditGetRect (ptr = ERect**)
kEffectEditOpen = 14, // effEditOpen (ptr = host window HWND)
kEffectEditClose = 15, // effEditClose
kEffectEditDraw = 16, // effEditDraw (deprecated)
kEffectEditMouse = 17, // effEditMouse (deprecated)
kEffectEditKey = 18, // effEditKey (deprecated)
kEffectEditIdle = 19, // effEditIdle
kEffectEditTop = 20, // effEditTop (deprecated)
kEffectEditSleep = 21, // effEditSleep (deprecated)
kEffectIdentify = 22, // effIdentify (deprecated)
kEffectGetChunk = 23, // effGetChunk
kEffectSetChunk = 24, // effSetChunk
kEffectProcessEvents = 25, // effProcessEvents
kEffectGetPlugCategory = 35,
kEffectGetEffectName = 45,
kEffectGetVendorString = 47,
kEffectGetProductString = 48,
kEffectGetVendorVersion = 49,
kEffectCanDo = 51,
kEffectIdle = 53, // effIdle
kEffectSetViewPosition = 55, // effSetViewPosition
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,
kAudioMasterSizeWindow = 15, // index = width, value = height
kAudioMasterGetDirectory = 41, // ptr = char* (VST dir); 0 = none
kAudioMasterUpdateDisplay = 42, // request host display refresh
kAudioMasterBeginEdit = 43, // parameter automation begin
kAudioMasterEndEdit = 44 // parameter automation end
};
// Editor rectangle returned by effEditGetRect (short coords per VST2 ABI).
struct ERect {
short top;
short left;
short bottom;
short right;
};
// 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 kVstMidiEventIsRealtime 1 // VstMidiEvent::flags: live input (not sequencer playback)
#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