// native_bridge/include/SharedMemoryIPC.h #pragma once #include #define AUDIO_BLOCK_SIZE 256 // WARNING: volatile is NOT a sync primitive. Real impl should use an // interlocked/index-flag pair or a Win32 event (SetEvent) signalled by the // writer. This struct follows the spec layout so Rust/JS mapping stays in sync. struct SharedAudioBufferIPC { // Synchronization Flags volatile uint32_t clientReadIndex; volatile uint32_t bridgeWriteIndex; // PCM Float32 Audio Buffers float masterLeft[AUDIO_BLOCK_SIZE]; float masterRight[AUDIO_BLOCK_SIZE]; // Latency probe: bridge stamps every rendered block (QueryPerformanceCounter) volatile uint64_t blockTimestamp; // MIDI Event Exchange Queue struct MidiEventIPC { uint8_t command; // 0x9 note on / 0x8 note off / 0xB CC / 0xC program / 0xE pitch bend uint8_t channel; uint8_t pitch; // note number (0x9/0x8) or CC number (0xB) uint8_t velocity; // 0-127 (0x9 + vel=0 == note off) uint8_t data2; // CC value / program number / PB LSB uint8_t data3; // PB MSB (0xE only) uint8_t reserved[2]; // explicit padding — keeps C/Rust layout stable uint32_t sampleOffset; } midiQueue[64]; volatile uint32_t midiQueueCount; // Transport / Control (added vs spec: Stop/Play flush, instrument switch) struct ControlEventIPC { uint32_t type; // 0 = NONE, 1 = PANIC/ALL_NOTES_OFF, 2 = LOAD_INSTRUMENT, // 3 = TRANSPORT, 4 = OPEN_GUI uint32_t arg0; // LOAD: instrument type (InstrumentType); // TRANSPORT: 0=STOP, 1=PLAY, 2=SET_POSITION uint32_t arg1; // LOAD: string length (bytes) of path; // TRANSPORT: playheadSamples (for timeline sync) uint32_t channel; // LOAD: MIDI channel to assign instrument to (A10) char arg2[1024]; // LOAD: UTF-8 path } controlQueue[8]; volatile uint32_t controlQueueCount; };