Reintroduce apps/arcade and the ten game crates that were ripped out of
the fork (assets, audio, blocks, coedit, gen, net, pkg, render, script,
session), from makepad-internal/dev. Reconcile against the fork's layout:
- makepad-game-sim/math come from the fork's existing libs/sim + sim/math;
the copied internal libs/game/{sim,math} are dropped and the kept game
crates plus arcade point at ../../sim and ../../sim/math.
- arcade AI is rewritten off the removed makepad-ai agent API onto the
makepad-ai-hub headless ChatProvider worker (example/cad pattern):
AiWorker{send,cancel,poll}, ai_worker_loop driving
ClaudeApiChatProvider(ClaudeCli), AiWorkerEvent availability/delta/
done/error mapped into the chat feed and authoring land_edit, with
main.rs send_message/cancel_request/event-drain rebuilt around it.
- the game-script sandbox is adapted to the fork's jailed splash storage:
every isolate gets mod.fs = splash_storage jail; splaes splash_storage
set_root_for_heap is now public so the ScriptHost (or Splash) can grant
a per-game jail root. ENT font: build.rs/dispatch.rs entities fill new
fork sim Entity/Part fields via ..Default::default(); world_raycast now
borrows mutably and returns the material id.
cargo check -p makepad-arcade and the game + arcade test suites pass.
77 lines
2.8 KiB
Rust
77 lines
2.8 KiB
Rust
//! Is a mismatch a TRIM bug or a CONTENT bug?
|
|
//!
|
|
//! Correlation cannot tell those apart: a transient decoded correctly but
|
|
//! offset scores badly, and a transient decoded wrongly can still score 0.8 on
|
|
//! envelope shape alone. This sweeps whole-frame lags looking for an EXACT
|
|
//! sample match instead. A lag where the overlap matches bit-for-bit means the
|
|
//! decode is right and only the trim is wrong; no such lag anywhere means the
|
|
//! samples themselves differ and the trim is a red herring.
|
|
//!
|
|
//! Usage: vorbis_exact <file.ogg> <reference.wav> [max_lag_frames]
|
|
use makepad_game_audio as audio;
|
|
|
|
fn main() {
|
|
let args: Vec<String> = std::env::args().collect();
|
|
let ogg = std::fs::read(&args[1]).expect("read ogg");
|
|
let refwav = std::fs::read(&args[2]).expect("read ref");
|
|
let max_lag: i64 = args.get(3).and_then(|s| s.parse().ok()).unwrap_or(2048);
|
|
|
|
let got = audio::decode(&ogg).expect("decode ogg");
|
|
let want = audio::wav::decode(&refwav).expect("decode ref");
|
|
let ch = got.channels as usize;
|
|
println!(
|
|
"got {}ch {} frames | ref {}ch {} frames | delta {}",
|
|
got.channels,
|
|
got.frames(),
|
|
want.channels,
|
|
want.frames(),
|
|
got.frames() as i64 - want.frames() as i64
|
|
);
|
|
|
|
let g = &got.samples;
|
|
let w = &want.samples;
|
|
|
|
// afconvert writes 16-bit, so our f32 can only ever match to quantisation.
|
|
// Compare at that resolution or every sample "differs" for no useful reason.
|
|
let q = |x: f32| (x * 32768.0).round() as i32;
|
|
|
|
let mut best = (0i64, 0usize, 0usize, f64::INFINITY);
|
|
for lag in -max_lag..=max_lag {
|
|
let off = lag * ch as i64;
|
|
let (gs, ws) = if off >= 0 {
|
|
(off as usize, 0usize)
|
|
} else {
|
|
(0usize, (-off) as usize)
|
|
};
|
|
if gs >= g.len() || ws >= w.len() {
|
|
continue;
|
|
}
|
|
let n = (g.len() - gs).min(w.len() - ws);
|
|
if n < ch * 256 {
|
|
continue;
|
|
}
|
|
let mut exact = 0usize;
|
|
let mut sad = 0f64;
|
|
for i in 0..n {
|
|
let (a, b) = (g[gs + i], w[ws + i]);
|
|
if q(a) == q(b) {
|
|
exact += 1;
|
|
}
|
|
sad += (a - b).abs() as f64;
|
|
}
|
|
let mean_abs = sad / n as f64;
|
|
if exact > best.1 || (exact == best.1 && mean_abs < best.3) {
|
|
best = (lag, exact, n, mean_abs);
|
|
}
|
|
}
|
|
let (lag, exact, n, mean_abs) = best;
|
|
println!(
|
|
"best lag {lag} frames: {exact}/{n} samples exact ({:.2}%), mean|diff| {mean_abs:.6}",
|
|
100.0 * exact as f64 / n as f64
|
|
);
|
|
if exact * 100 / n.max(1) >= 99 {
|
|
println!("VERDICT: decode is correct, trim is off by {lag} frames");
|
|
} else {
|
|
println!("VERDICT: content differs — trim alone cannot explain this");
|
|
}
|
|
}
|