Split audio host contract

This commit is contained in:
gamer147
2026-08-03 10:16:15 -04:00
parent 2bdd2b562d
commit e770aa0094
4 changed files with 56 additions and 34 deletions

View File

@@ -163,8 +163,9 @@ of that state through the sealed partial class.
`engine/Age.Engine/Hosting/IHost.cs` remains the aggregate runtime host accepted by the VM and existing host `engine/Age.Engine/Hosting/IHost.cs` remains the aggregate runtime host accepted by the VM and existing host
implementations. `engine/Age.Engine/Hosting/IDiagnosticHost.cs` owns recoverable-warning and modal-diagnostic implementations. `engine/Age.Engine/Hosting/IDiagnosticHost.cs` owns recoverable-warning and modal-diagnostic
reporting contracts, while `engine/Age.Engine/Hosting/ILifecycleHost.cs` owns script-context entry/exit, sleep and reporting contracts, while `engine/Age.Engine/Hosting/ILifecycleHost.cs` owns script-context entry/exit, sleep and
timed-deadline waiting, frame yield, and scene reset. `IHost` inherits both focused contracts; their required and timed-deadline waiting, frame yield, and scene reset. `engine/Age.Engine/Hosting/IAudioHost.cs` owns BGM, voice,
default behavior is unchanged. SFX, fade, volume, and route-control contracts, including the compatibility overload/default chains used by
simple hosts. `IHost` inherits all three focused contracts; their required and default behavior is unchanged.
`engine/Age.Engine/Model/GfxState.cs` retains cross-domain retained-graphics coordination. `engine/Age.Engine/Model/GfxState.cs` retains cross-domain retained-graphics coordination.
`engine/Age.Engine/Model/GfxState.Contracts.cs` owns its public render, transition, diagnostic, persistence, `engine/Age.Engine/Model/GfxState.Contracts.cs` owns its public render, transition, diagnostic, persistence,

View File

@@ -765,6 +765,11 @@ do not mix mechanical moves with semantic changes.
entry point; all required members, default implementations, existing hosts, and transport-record locations entry point; all required members, default implementations, existing hosts, and transport-record locations
are unchanged. Runtime validation remains green. are unchanged. Runtime validation remains green.
The second bounded contract slice introduced `IAudioHost` for BGM, voice, sound-effect, fade, volume, and
route-control operations. `IHost` inherits the focused contract; all fifteen members, required implementations,
compatibility overloads/default chains, and existing host classes remain behaviorally unchanged. Runtime
validation remains green.
4. **Make the build graph express source ownership.** Stop linking production `.cs` files from `godot/` and 4. **Make the build graph express source ownership.** Stop linking production `.cs` files from `godot/` and
`tools/movie-corpus-gate/` into `Age.Engine.Tests`. Extract the platform-neutral frontend/movie/diagnostic `tools/movie-corpus-gate/` into `Age.Engine.Tests`. Extract the platform-neutral frontend/movie/diagnostic
code into a small production project referenced by Godot, tests, and the corpus gate. Retain both existing code into a small production project referenced by Godot, tests, and the corpus gate. Retain both existing
@@ -1124,9 +1129,9 @@ layer's rendering diverges from ADV; save layout.
## 8. Immediate next step ## 8. Immediate next step
Continue step 3 of the **codebase consolidation** maintenance slice: clarify runtime contracts without changing Continue step 3 of the **codebase consolidation** maintenance slice: clarify runtime contracts without changing
behavior or the aggregate host accepted by the VM. With diagnostic and lifecycle contracts established beneath behavior or the aggregate host accepted by the VM. With diagnostic, lifecycle, and audio contracts established
`IHost`, introduce the audio host contract next as the smallest remaining self-contained domain, preserving every beneath `IHost`, introduce the movie host contract next while leaving movie request/graphics transport records in
required/default member and all existing host implementations before tackling interdependent ADV/input/graphics their current locations for a separate dependency-cleanup slice; preserve every required/default member and all
surfaces. existing host implementations.
Concrete playthrough blockers may still preempt this bounded maintenance work; the consolidation effort does Concrete playthrough blockers may still preempt this bounded maintenance work; the consolidation effort does
not replace Phase B gameplay validation or the open cross-platform gates. not replace Phase B gameplay validation or the open cross-platform gates.

View File

@@ -0,0 +1,43 @@
namespace Age.Engine.Hosting;
public interface IAudioHost
{
void PlayBgm(long id);
// Ordinary op 0xbf is VM-filtered so reasserting the current track is idempotent. Ops
// 0xb7/0xb9 deliberately bypass that guard and restart with logical loop/one-shot mode.
void RestartBgm(long id, int startMode) => PlayBgm(id);
// Op 0xb8 releases the current source rather than merely applying a zero-volume envelope.
void StopBgm() => FadeBgm(0, 0);
void PlayVoice(long id);
// Native voice playback retains a second start argument: ordinary dialogue passes 0,
// while History replay (0x1bd) passes 1. Existing non-audio hosts may ignore it.
void PlayVoice(long id, int playbackVariant) => PlayVoice(id);
void ScheduleVoicePlayback(long id, int playbackVariant, long delayMs) { }
// Native op 0x1cf stores a transient control mask. Bit 0 suppresses the automatic
// BGM attenuation normally applied when a voice starts.
void SetVoiceBgmDuckControl(long flags) { }
void LoadSoundEffect(long resourceId, int channel) { }
void StartSoundEffect(int channel) { }
// Ops 0xb5/0xba share the native channel-start worker. Mode 0 plays once; mode 1
// rewinds the decoder at EOF. The one-argument seam remains for simple hosts.
void StartSoundEffect(int channel, int startMode) => StartSoundEffect(channel);
// Native SetDelay (op 0x2bf) starts an already-loaded channel after delayMs.
// startMode is forwarded to the same worker used by immediate SFX starts.
void ScheduleSoundEffectStart(int channel, int startMode, long delayMs) { }
void ReleaseSoundEffect(int channel) { }
void FadeBgm(int targetPercent, long durationMs) { }
// AGE's sound:* settings registry is VM-owned; the host applies changes to active playback.
void ApplyAudioVolume(int category, int basisPoints) { }
void ApplyAudioRouteEnabled(int category, bool enabled) { }
}

View File

@@ -48,7 +48,7 @@ public enum SurfaceBlackFadeDirection
ToBlack, ToBlack,
} }
public interface IHost : IDiagnosticHost, ILifecycleHost public interface IHost : IDiagnosticHost, ILifecycleHost, IAudioHost
{ {
/// <summary>Present AGERc's modal full-width editor. Cancel preserves CurrentText.</summary> /// <summary>Present AGERc's modal full-width editor. Cancel preserves CurrentText.</summary>
FullwidthTextEditResult EditFullwidthString(FullwidthTextEditRequest request) FullwidthTextEditResult EditFullwidthString(FullwidthTextEditRequest request)
@@ -171,33 +171,6 @@ public interface IHost : IDiagnosticHost, ILifecycleHost
} }
void DrawTexture(int slot, int srcX, int srcY, int width, int height, int dstX, int dstY); void DrawTexture(int slot, int srcX, int srcY, int width, int height, int dstX, int dstY);
(int Width, int Height) GetTextureSize(int slot); (int Width, int Height) GetTextureSize(int slot);
void PlayBgm(long id);
// Ordinary op 0xbf is VM-filtered so reasserting the current track is idempotent. Ops
// 0xb7/0xb9 deliberately bypass that guard and restart with logical loop/one-shot mode.
void RestartBgm(long id, int startMode) => PlayBgm(id);
// Op 0xb8 releases the current source rather than merely applying a zero-volume envelope.
void StopBgm() => FadeBgm(0, 0);
void PlayVoice(long id);
// Native voice playback retains a second start argument: ordinary dialogue passes 0,
// while History replay (0x1bd) passes 1. Existing non-audio hosts may ignore it.
void PlayVoice(long id, int playbackVariant) => PlayVoice(id);
void ScheduleVoicePlayback(long id, int playbackVariant, long delayMs) { }
// Native op 0x1cf stores a transient control mask. Bit 0 suppresses the automatic
// BGM attenuation normally applied when a voice starts.
void SetVoiceBgmDuckControl(long flags) { }
void LoadSoundEffect(long resourceId, int channel) { }
void StartSoundEffect(int channel) { }
// Ops 0xb5/0xba share the native channel-start worker. Mode 0 plays once; mode 1
// rewinds the decoder at EOF. The one-argument seam remains for simple hosts.
void StartSoundEffect(int channel, int startMode) => StartSoundEffect(channel);
// Native SetDelay (op 0x2bf) starts an already-loaded channel after delayMs.
// startMode is forwarded to the same worker used by immediate SFX starts.
void ScheduleSoundEffectStart(int channel, int startMode, long delayMs) { }
void ReleaseSoundEffect(int channel) { }
void FadeBgm(int targetPercent, long durationMs) { }
// AGE's sound:* settings registry is VM-owned; the host applies changes to active playback.
void ApplyAudioVolume(int category, int basisPoints) { }
void ApplyAudioRouteEnabled(int category, bool enabled) { }
// Native op 0x236 binds a movie decoder to an existing retained texture surface. // Native op 0x236 binds a movie decoder to an existing retained texture surface.
// Playback is non-modal: the VM advances to the following instruction while the host publishes frames. // Playback is non-modal: the VM advances to the following instruction while the host publishes frames.
/// <returns>The initialized movie graph's stop position in truncated integer milliseconds, or null /// <returns>The initialized movie graph's stop position in truncated integer milliseconds, or null