Classic Wave, Silk Ribbon, Kaleido Tunnel and Slow Orb all declared the `style` trait and honoured it with `col += sigGrain(uv)` and nothing else. A declared trait is a contract — the disqualification rule in Personality.js is the only thing keeping off-design scenes out of a track — so honouring it with dirt meant these four could not take the `texture: 0` opt-out the grain work introduced. Phase 9 measured their style response at exactly 0. They sat at texture: 0.35 as a stopgap, which kept speckle on the library's cleanest scenes purely to keep a gate green. Each already had the knob; it just was not wired to the track: - Classic Wave contrasts its wave through a bare smoothstep(0.2, 0.8). The transition width now comes from u_sigSoft and u_sigLine, centred on 0.5 so changing the hand does not change the exposure. Crest concentration is driven separately by u_sigLine, because a track is free to sample the scene's own u_softness at zero and the art direction must still show. - Silk Ribbon's strand width is u_sigLine and its falloff exponent u_sigSoft: a sharp track gets a filament with a defined edge, a soft one a haze. - Kaleido Tunnel drew its grid against a bare 0.42 — a line weight with no name. It is now a weight and a feather, both from the track. - Slow Orb's body edge multiplies the scene's softness by the video's, and gains a sigEdge rim so a sharp-handed track gets a defined limb. All four are now texture: 0. Style response measured against a maximally soft-handed versus maximally sharp-handed personality: Classic Wave 111, Silk Ribbon 216, Kaleido Tunnel 206, Slow Orb 102, out of 255 — previously 0. 104/104 checks pass including the slow set. See SIDE-QUESTS.md §1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
53 lines
2.0 KiB
HTML
53 lines
2.0 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head><title>audio probe</title></head>
|
|
<body>
|
|
<div id="out">running…</div>
|
|
<script type="module">
|
|
const out = document.getElementById('out');
|
|
const log = (m) => { out.textContent += m + '\n'; };
|
|
|
|
for (const sr of [44100, 48000]) {
|
|
try {
|
|
const s = await AudioEncoder.isConfigSupported({ codec: 'opus', sampleRate: sr, numberOfChannels: 2, bitrate: 160000 });
|
|
log(`opus @ ${sr}: supported=${s.supported}`);
|
|
} catch (e) { log(`opus @ ${sr}: threw ${e.message}`); }
|
|
}
|
|
for (const sr of [44100, 48000]) {
|
|
try {
|
|
const s = await AudioEncoder.isConfigSupported({ codec: 'mp4a.40.2', sampleRate: sr, numberOfChannels: 2, bitrate: 192000 });
|
|
log(`aac @ ${sr}: supported=${s.supported}`);
|
|
} catch (e) { log(`aac @ ${sr}: threw ${e.message}`); }
|
|
}
|
|
|
|
// Encode a 44100 stream with opus and inspect the output chunk metadata.
|
|
try {
|
|
const chunks = [];
|
|
const enc = new AudioEncoder({
|
|
output: (chunk, meta) => chunks.push({ ts: chunk.timestamp, dur: chunk.duration }),
|
|
error: (e) => log('enc error ' + e.message),
|
|
});
|
|
enc.configure({ codec: 'opus', sampleRate: 44100, numberOfChannels: 2, bitrate: 160000 });
|
|
const n = 44100; // 1 second
|
|
const data = new Float32Array(n * 2);
|
|
let td;
|
|
for (let i = 0; i < 10; i++) {
|
|
td = new AudioData({ format: 'f32', sampleRate: 44100, numberOfFrames: 4096, numberOfChannels: 2, timestamp: i * 4096 / 44100 * 1e6, data: data });
|
|
enc.encode(td); td.close();
|
|
}
|
|
await enc.flush();
|
|
log(`opus@44100 chunks: ${chunks.length}`);
|
|
if (chunks.length) {
|
|
const deltas = chunks.slice(1).map((c, i) => c.ts - chunks[i].ts);
|
|
log('first chunk ts/dur: ' + chunks[0].ts + '/' + chunks[0].dur);
|
|
log('deltas: ' + deltas.slice(0, 5).join(' '));
|
|
log('last ts: ' + chunks[chunks.length - 1].ts);
|
|
}
|
|
enc.close();
|
|
} catch (e) { log('opus@44100 encode threw: ' + e.message); }
|
|
log('DONE');
|
|
window.__AUDIO_PROBE__ = true;
|
|
</script>
|
|
</body>
|
|
</html>
|