G4.3 idle-skip + no fixed-tick render: idle CPU ~0, latency 9.8ms
This commit is contained in:
@@ -128,4 +128,12 @@ G4.1 → G4.2 → G4.3.
|
||||
- Build Release PASS (daw_vst_bridge.exe + plugin_host.exe). Deploy shutil.copy2 (kill proc giu file truoc).
|
||||
- Verify (probe_g43.py, bridge standalone env `SF_SANDBOX_VST3=1` + state file rong): LOAD Nexus ch0+ch1 -> 2 plugin_host [con song song]; heartbeat ca 2 OK; note-on ch0 C4 + ch1 E4 -> main audio peak 0.71835 (tong 2 channel); writeSlot flip 64 blocks/s = latency 15.6ms < 20ms (khong yeu cau 172/s thuc - Nexus render ~10ms/block that, CPU-bound); kill child0 -> child1 van phat 0.36972, bridge song + heartbeat + child0 respawn - PASS.
|
||||
- Regression: G1.5 stress 3 iter PASS (writeIndex delta 286); G2.5 stress 2 iter PASS (kill bridge -> respawn -> preset exact + LOAD-skip OK). App deploy (install/sonicforge-daw.exe) dang chay, bridge pid moi.
|
||||
- ponytail: child render lien tuc ke ca im lang (CPU cao khi idle) - toi uu idle-skip khi can.
|
||||
- FIX idle-skip (G4.3.1): plugin_host_main.cpp them `activeNotes` dem (note-on ++, note-off --, clamp >= 0)
|
||||
+ `idle` flag. Khi khong con note dang giu va peak block < 0.0005f -> idle = true,
|
||||
loop Sleep(15) bo qua render (van PeekMessage + parent-alive check). Bo `Sleep(1)`
|
||||
hot loop -> `Sleep(0)` yield. KET QUA: writeSlot flip 0 blocks/s khi im lang (truoc day
|
||||
render lien tuc ~100/s, CPU cao); khi dang giu note flip 101.6 blocks/s = latency 9.8ms
|
||||
(truoc 64/s = 15.6ms) - ca 2 loi G4.3 xac nhan da het.
|
||||
- Verify lai: probe_g43.py PASS (2 children song song, peak 0.67273, kill child0 -> child1
|
||||
0.36972, isolation OK); dbg_rate.py idle 0 flips/3s; G1.5 3 iter PASS (delta 287);
|
||||
G2.5 2 iter PASS. Deploy install/plugin_host.exe moi. App dang chay pid 21396.
|
||||
|
||||
@@ -98,6 +98,8 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}).detach();
|
||||
|
||||
int activeNotes = 0;
|
||||
bool idle = false;
|
||||
for (;;) {
|
||||
MSG msg;
|
||||
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
@@ -105,14 +107,15 @@ int main(int argc, char* argv[]) {
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
uint32_t n = ipc->base.midiQueueCount > 64 ? 64 : ipc->base.midiQueueCount;
|
||||
bool midiActivity = n > 0;
|
||||
for (uint32_t i = 0; i < n; ++i) {
|
||||
const SharedAudioBufferIPC::MidiEventIPC& e = ipc->base.midiQueue[i];
|
||||
switch (e.command) {
|
||||
case 0x9:
|
||||
if (e.velocity > 0) inst.noteOn(e.channel, e.pitch, e.velocity / 127.0f, 0);
|
||||
else inst.noteOff(e.channel, e.pitch, 0);
|
||||
if (e.velocity > 0) { inst.noteOn(e.channel, e.pitch, e.velocity / 127.0f, 0); ++activeNotes; }
|
||||
else { inst.noteOff(e.channel, e.pitch, 0); if (activeNotes > 0) --activeNotes; }
|
||||
break;
|
||||
case 0x8: inst.noteOff(e.channel, e.pitch, 0); break;
|
||||
case 0x8: inst.noteOff(e.channel, e.pitch, 0); if (activeNotes > 0) --activeNotes; break;
|
||||
case 0xB: inst.controlChange(e.channel, e.pitch, e.data2); break;
|
||||
case 0xC: inst.programChange(e.channel, e.data2); break;
|
||||
case 0xE: inst.pitchBend(e.channel, e.data2 | (uint32_t(e.data3) << 7)); break;
|
||||
@@ -120,6 +123,15 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
ipc->base.midiQueueCount = 0;
|
||||
if (midiActivity) idle = false;
|
||||
if (parentPid && !parent_alive(parentPid)) {
|
||||
printf("[plugin_host] parent gone - exiting\n");
|
||||
break;
|
||||
}
|
||||
if (idle) {
|
||||
Sleep(15);
|
||||
continue;
|
||||
}
|
||||
// G4.3 double buffer: render into the slot we are NOT publishing, then
|
||||
// publish. The bridge keeps the last published block, so a slow child
|
||||
// never tears audio (it just repeats the previous block).
|
||||
@@ -127,11 +139,19 @@ int main(int argc, char* argv[]) {
|
||||
inst.processAudioBlock(ipc->audioLeft[slot], ipc->audioRight[slot], block);
|
||||
ipc->writeSlot = slot;
|
||||
ipc->base.bridgeWriteIndex++;
|
||||
if (parentPid && !parent_alive(parentPid)) {
|
||||
printf("[plugin_host] parent gone - exiting\n");
|
||||
break;
|
||||
if (activeNotes == 0) {
|
||||
float peak = 0.0f;
|
||||
for (uint32_t i = 0; i < block; ++i) {
|
||||
float l = ipc->audioLeft[slot][i];
|
||||
if (l < 0.0f) l = -l;
|
||||
float r = ipc->audioRight[slot][i];
|
||||
if (r < 0.0f) r = -r;
|
||||
if (l > peak) peak = l;
|
||||
if (r > peak) peak = r;
|
||||
}
|
||||
if (peak < 0.0005f) idle = true;
|
||||
}
|
||||
Sleep(1);
|
||||
Sleep(0);
|
||||
}
|
||||
inst.closeGUI();
|
||||
#ifdef _WIN32
|
||||
|
||||
Reference in New Issue
Block a user