Skip to content

fix: apply max plugin delay compensation#1806

Merged
ChuxiJ merged 1 commit into
mainfrom
fix/issue-1783
Apr 30, 2026
Merged

fix: apply max plugin delay compensation#1806
ChuxiJ merged 1 commit into
mainfrom
fix/issue-1783

Conversation

@ChuxiJ
Copy link
Copy Markdown

@ChuxiJ ChuxiJ commented Apr 30, 2026

Summary

  • apply plugin delay compensation using the maximum active chain latency across tracks
  • exclude bypassed plugins from latency totals and sanitize live latency reports
  • preserve VST3 companion latency from instance creation and later latencyInfo updates

Verification

  • npx tsc --noEmit --pretty false
  • npx vitest run src/services/vst3bridge/tests/PluginEngineLatency.test.ts src/services/vst3bridge/tests/VST3LatencyCompensation.test.ts src/services/vst3bridge/tests/VST3PluginAdapter.test.ts src/hooks/tests/useEffectsSync.vst3.test.ts src/store/tests/vst3Store.test.ts
  • git diff --check

Closes #1783

Copilot AI review requested due to automatic review settings April 30, 2026 00:32
@ChuxiJ
Copy link
Copy Markdown
Author

ChuxiJ commented Apr 30, 2026

Codex review completed.

Result: PASS

No actionable regressions were found in the latency propagation and compensation changes. Local verification passed:

  • npx tsc --noEmit --pretty false
  • npx vitest run src/services/vst3bridge/tests/PluginEngineLatency.test.ts src/services/vst3bridge/tests/VST3LatencyCompensation.test.ts src/services/vst3bridge/tests/VST3PluginAdapter.test.ts src/hooks/tests/useEffectsSync.vst3.test.ts src/store/tests/vst3Store.test.ts
  • git diff --check

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates VST3 plugin delay compensation (PDC) to align tracks using the maximum active plugin-chain latency across tracks, while also improving how VST3 latency is tracked and updated live from the companion.

Changes:

  • Track and sanitize per-instance VST3 latency (latencySamples) from instantiation and subsequent latencyInfo updates.
  • Compute cross-track PDC using max chain latency and apply per-track compensation (instead of delaying each track by its own latency).
  • Exclude bypassed plugins from chain latency totals; add/extend unit tests around bypass and live latency updates.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/types/vst3.ts Adds optional latencySamples to the active instance model.
src/store/vst3Store.ts Persists initial latency on load and adds _updateLatency to apply/store live latency updates.
src/store/tests/vst3Store.test.ts Tests initial latency capture and live latency updates to store + PluginEngine.
src/services/vst3bridge/tests/PluginEngineLatency.test.ts Tests bypass exclusion from latency and live latency update behavior.
src/services/vst3bridge/VST3PluginAdapter.ts Stores latency internally and exposes setLatencySamples for live updates.
src/hooks/useVST3Connection.ts Subscribes to latencyInfo and forwards updates into the store.
src/hooks/useEffectsSync.ts Applies max-latency-based compensation across tracks via TrackNode.setLatencyCompensation.
src/hooks/tests/useEffectsSync.vst3.test.ts Adds coverage for cross-track max-latency compensation calculations.
src/engine/PluginEngine.ts Excludes bypassed nodes from chain latency; adds setPluginLatency API for live updates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/store/vst3Store.ts Outdated
Comment on lines 160 to 191
@@ -166,7 +172,10 @@ export const useVST3Store = create<VST3Store>()((set, get) => ({
client.off('instanceCreated', onCreated);
client.off('error', onError);
const params = (msg.parameters as VST3Parameter[]) ?? [];
resolve(params);
resolve({
parameters: params,
latencySamples: sanitizeLatencySamples(msg.latencySamples),
});
}
};

@@ -182,7 +191,7 @@ export const useVST3Store = create<VST3Store>()((set, get) => ({
});
Comment on lines 53 to 61
/**
* Derive a stable fingerprint of VST3 instances for effect chain syncing.
* Only includes fields that affect audio routing (instanceId, trackId, enabled).
*/
function selectVst3EffectChainKey(s: { instances: Record<string, VST3ActiveInstance> }): string {
const parts: string[] = [];
for (const [id, inst] of Object.entries(s.instances)) {
parts.push(`${id}:${inst.trackId ?? ''}:${inst.enabled ? '1' : '0'}`);
parts.push(`${id}:${inst.trackId ?? ''}:${inst.enabled ? '1' : '0'}:${inst.latencySamples ?? 0}`);
}
Comment thread src/engine/PluginEngine.ts Outdated
total += node.plugin.latencySamples ?? 0;
if (node.bypassed) continue;
const latencySamples = node.plugin.latencySamples ?? 0;
total += Number.isFinite(latencySamples) ? Math.max(0, latencySamples) : 0;
@ChuxiJ
Copy link
Copy Markdown
Author

ChuxiJ commented Apr 30, 2026

Addressed Copilot review feedback:

  • Replaced the event-name-dependent loadPlugin flow with client.instantiate() request/response handling.
  • Updated the VST3 sync fingerprint comment to include timing changes.
  • Normalized chain latency aggregation to integer samples and added a regression test for fractional/invalid latency values.

Re-verified locally:

  • npx tsc --noEmit --pretty false
  • npx vitest run src/services/vst3bridge/tests/PluginEngineLatency.test.ts src/services/vst3bridge/tests/VST3LatencyCompensation.test.ts src/services/vst3bridge/tests/VST3PluginAdapter.test.ts src/hooks/tests/useEffectsSync.vst3.test.ts src/store/tests/vst3Store.test.ts
  • git diff --check

@ChuxiJ
Copy link
Copy Markdown
Author

ChuxiJ commented Apr 30, 2026

Addressed second Codex review finding:

  • Excluded group/bus tracks from leaf-track plugin delay compensation so child audio routed through a group bus is not delayed twice.
  • Added regression coverage for an excluded group bus with plugin latency.

Re-verified locally:

  • npx tsc --noEmit --pretty false
  • npx vitest run src/services/vst3bridge/tests/PluginEngineLatency.test.ts src/services/vst3bridge/tests/VST3LatencyCompensation.test.ts src/services/vst3bridge/tests/VST3PluginAdapter.test.ts src/hooks/tests/useEffectsSync.vst3.test.ts src/store/tests/vst3Store.test.ts
  • git diff --check

@ChuxiJ
Copy link
Copy Markdown
Author

ChuxiJ commented Apr 30, 2026

Addressed third Codex review finding:

  • Plugin delay compensation now uses routed signal-path latency for leaf tracks.
  • Child tracks include parent group-bus plugin latency in their path total.
  • Group buses are still assigned 0 explicit compensation so grouped audio is not double-delayed.

Re-verified locally:

  • npx tsc --noEmit --pretty false
  • npx vitest run src/services/vst3bridge/tests/PluginEngineLatency.test.ts src/services/vst3bridge/tests/VST3LatencyCompensation.test.ts src/services/vst3bridge/tests/VST3PluginAdapter.test.ts src/hooks/tests/useEffectsSync.vst3.test.ts src/store/tests/vst3Store.test.ts
  • git diff --check

@ChuxiJ
Copy link
Copy Markdown
Author

ChuxiJ commented Apr 30, 2026

Final Codex review completed after the signal-path PDC fix.

Result: PASS

No discrete, actionable regressions were identified in the diff. Type checking and targeted changed tests pass.

@ChuxiJ ChuxiJ merged commit 88aa25c into main Apr 30, 2026
8 checks passed
@ChuxiJ ChuxiJ deleted the fix/issue-1783 branch April 30, 2026 01:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: Apply plugin delay compensation across tracks using max chain latency

2 participants