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
This commit is contained in:
@@ -23,6 +23,9 @@
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#ifdef _WIN32
|
||||
#include <malloc.h> // _heapchk (TEMP diag)
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// 1. SOUNDFONT ENGINE (.SF2 / .SF3) VIA FLUIDSYNTH C API
|
||||
@@ -108,7 +111,7 @@ void FluidSynthInstrument::programChange(uint32_t channel, uint32_t program) {
|
||||
|
||||
void FluidSynthInstrument::pitchBend(uint32_t channel, uint32_t bend14) {
|
||||
if (!synth) return;
|
||||
// fluid_synth_pitch_bend takes the raw 14-bit value (center 8192).
|
||||
// fluid_synth_pitch_bend takes the raw 14-bit value (center 2097152).
|
||||
fluid_synth_pitch_bend(FS_SYNTH, channel, bend14);
|
||||
}
|
||||
|
||||
@@ -435,7 +438,10 @@ void InstrumentEngineManager::allNotesOff() {
|
||||
// audio buffers; plain std::vector is only 16B-aligned. Over-allocate and
|
||||
// align the pointer handed to plugins to 64B.
|
||||
static float* alignF(std::vector<float>& v, size_t n) {
|
||||
if (v.size() < n + 16) v.assign(n + 16, 0.0f);
|
||||
// 64B-aligned pointer can sit up to 63B into the allocation; TEMP diag:
|
||||
// huge tail so we can measure how far DUNE writes past n.
|
||||
const size_t kTail = 2097152 + 64;
|
||||
if (v.size() < n + kTail) v.assign(n + kTail, 0.0f);
|
||||
uintptr_t a = reinterpret_cast<uintptr_t>(v.data());
|
||||
return reinterpret_cast<float*>((a + 63) & ~(uintptr_t)63);
|
||||
}
|
||||
@@ -457,6 +463,16 @@ static bool SafeProcessChannel(INativeInstrument* inst, float* outL, float* outR
|
||||
return true;
|
||||
} __except (g_sehCode = GetExceptionCode(),
|
||||
g_sehAddr = GetExceptionInformation()->ExceptionRecord->ExceptionAddress,
|
||||
std::cerr << "[NativeBridge][G3.3][diag] SEH code=0x" << std::hex
|
||||
<< g_sehCode << " rip=0x" << (uintptr_t)g_sehAddr
|
||||
<< " fault=0x" << std::hex
|
||||
<< (GetExceptionInformation()->ExceptionRecord->NumberParameters > 1
|
||||
? GetExceptionInformation()->ExceptionRecord->ExceptionInformation[1]
|
||||
: 0)
|
||||
<< " isWrite=" << (GetExceptionInformation()->ExceptionRecord->NumberParameters > 0
|
||||
? GetExceptionInformation()->ExceptionRecord->ExceptionInformation[0]
|
||||
: 0)
|
||||
<< std::dec << std::endl,
|
||||
EXCEPTION_EXECUTE_HANDLER) {
|
||||
*outCode = g_sehCode;
|
||||
return false;
|
||||
@@ -546,8 +562,17 @@ void InstrumentEngineManager::renderAll(float* outputL, float* outputR, uint32_t
|
||||
if (channelQuiet(ch)) continue; // editor open / crashed: do not process
|
||||
float* spL = alignF(scratchL_, numSamples);
|
||||
float* spR = alignF(scratchR_, numSamples);
|
||||
std::memset(spL, 0, numSamples * sizeof(float));
|
||||
std::memset(spR, 0, numSamples * sizeof(float));
|
||||
std::cerr << "[NativeBridge][diag] renderAll ch=" << ch << " n=" << numSamples
|
||||
<< " spL=0x" << std::hex << (uintptr_t)spL
|
||||
<< " spR=0x" << (uintptr_t)spR
|
||||
<< " capL=" << std::dec << scratchL_.size()
|
||||
<< " capR=" << scratchR_.size() << std::endl;
|
||||
// TEMP diag: fill canary with a NaN pattern so writes of 0.0 (silence)
|
||||
// are still detected.
|
||||
for (uint32_t i = 0; i < numSamples + 2097152; ++i) {
|
||||
spL[i] = 0x7FC00000u; // quiet NaN
|
||||
spR[i] = 0x7FC00000u;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
DWORD sehCode = 0;
|
||||
#else
|
||||
@@ -592,6 +617,28 @@ void InstrumentEngineManager::renderAll(float* outputL, float* outputR, uint32_t
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// TEMP diag: plugin output-overrun canary + heap health.
|
||||
{
|
||||
static uint64_t diagBlock = 0; ++diagBlock;
|
||||
int farL = -1, farR = -1;
|
||||
for (uint32_t i = 0; i < 2097152; ++i) {
|
||||
uint32_t bL, bR;
|
||||
std::memcpy(&bL, &spL[numSamples + i], 4);
|
||||
std::memcpy(&bR, &spR[numSamples + i], 4);
|
||||
if (bL != 0x7FC00000u) farL = (int)i;
|
||||
if (bR != 0x7FC00000u) farR = (int)i;
|
||||
}
|
||||
if (farL >= 0 || farR >= 0)
|
||||
std::cerr << "[NativeBridge][diag] block " << diagBlock
|
||||
<< " OUTPUT OVERRUN past n: L=" << farL
|
||||
<< " R=" << farR << " (ch=" << ch << ")" << std::endl;
|
||||
#ifdef _WIN32
|
||||
int h = _heapchk();
|
||||
if (h != _HEAPOK)
|
||||
std::cerr << "[NativeBridge][diag] block " << diagBlock
|
||||
<< " heap NOT OK code=" << h << std::endl;
|
||||
#endif
|
||||
}
|
||||
// Auto-normalize: makeup calibrated (constant per-channel gain, no steps).
|
||||
auto mit = makeup_.find(ch);
|
||||
const float g = (mit != makeup_.end()) ? mit->second : 1.0f;
|
||||
@@ -620,3 +667,10 @@ void InstrumentEngineManager::renderAll(float* outputL, float* outputR, uint32_t
|
||||
outputR[i] *= limiterGain_;
|
||||
}
|
||||
}
|
||||
|
||||
void InstrumentEngineManager::guiIdleAll() {
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
for (auto& kv : channels_) {
|
||||
kv.second->guiIdle();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user