@banou/ripple 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@banou/ripple",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
package/sw.js CHANGED
@@ -8,7 +8,7 @@ const live = new Map()
8
8
  /* Stamped at build time. These are the dev defaults and must never reach production: a worker whose
9
9
  BUILD never changes is never reinstalled, so the update this feature announces would never fire. */
10
10
  const MODE = "cache" // @stamp:mode
11
- const BUILD = "dc9663766143c273" // @stamp:build
11
+ const BUILD = "7abdce2fbfa281a1" // @stamp:build
12
12
  const MANIFEST = [["/assets/empty-BvRk9kiK.js","e3b0c44298fc1c14"],["/assets/libtorrent-DleyqKUt.js","27516279f85831f1"],["/assets/worker-kaROsro7.js","3f29b36a9bea36cc"],["/build-B7te3F-u.js","47b056c564f078c5"],["/remote-DvdN47iT.js","b0649250a9e3a079"]] // @stamp:manifest
13
13
 
14
14
  const CACHE = 'ripple-assets-' + BUILD
@@ -20,6 +20,13 @@
20
20
  const BINS_PER_SECOND = 1000
21
21
  // the analysis's unit of work and of what the worklet holds: 10 s of 1 ms bins
22
22
  const BLOCK_BINS = 10_000
23
+ /*
24
+ * The blocks the worklet keeps, those it was sent nearest the playhead, 4.8 MB of cut and fingerprint: as it plays,
25
+ * the 30 to 40 s sent ahead of it and 560 to 570 s behind. Under load Chrome plays a seek into audio it still has
26
+ * buffered before a block let go of is computed again: kept only 20 to 30 s behind and 30 to 40 s ahead, 3 to 32 ms of
27
+ * such a seek played on the live stage alone, in 51 of 75 seeks 24 to 44 s away on 4 loaded CPUs (HOR-681, 2026-10-25).
28
+ */
29
+ const KEPT_BLOCKS = 60
23
30
  /*
24
31
  * How far a cut reaches from the audio that asks for it, in bins. The slow stage reads 1.85 s ahead and 1.65 s
25
32
  * behind, and its exponential attack (0.3 s, backward) and release (0.5 s, forward) fall under 0.01 dB of a 20 dB cut
@@ -433,7 +440,8 @@ export const audioSamplesOf = (fragment, track) => {
433
440
  /**
434
441
  * The analysis: 1 ms bins of whatever audio it is given, the normal level learned from them, and the cut for the
435
442
  * blocks around the playhead. `toWorklet` takes `{ block, gain, finger }` (10 s of bins from `block * 10` s, NaN where
436
- * the cut or the audio is not known) and `{ drop }`; `toPage` takes the coverage reports the page schedules reads on.
443
+ * the cut or the audio is not known) and `{ drop }` for each block past the 60 sent nearest the playhead, which is all
444
+ * the worklet keeps; `toPage` takes the coverage reports the page schedules reads on.
437
445
  * Separate from the worker's messages so a test can drive it with decoded audio.
438
446
  */
439
447
  export const createAnalysis = ({ toWorklet, toPage = () => {} }) => {
@@ -557,13 +565,8 @@ export const createAnalysis = ({ toWorklet, toPage = () => {} }) => {
557
565
  const update = () => {
558
566
  timer = undefined
559
567
  const level = normal()
560
- const here = Math.floor(playhead * BINS_PER_SECOND / BLOCK_BINS)
561
- for (const block of [...sent.keys()]) {
562
- if (block >= here - 2 && block <= here + 4) continue
563
- sent.delete(block)
564
- toWorklet({ drop: block })
565
- }
566
568
  if (!Number.isFinite(level)) return
569
+ const here = Math.floor(playhead * BINS_PER_SECOND / BLOCK_BINS)
567
570
  // the playhead's own block first: under load each took 21 to 43 ms, and sent after the one before it, a seek's
568
571
  // cut over HTTP reached the worklet 64 to 75 ms after the seek, its audio 72 to 83 ms (HOR-888, 2026-10-23)
569
572
  for (const block of [here, here - 1, here + 1, here + 2, here + 3]) {
@@ -577,6 +580,11 @@ export const createAnalysis = ({ toWorklet, toPage = () => {} }) => {
577
580
  sent.set(block, { known, level })
578
581
  toWorklet({ block, gain, finger }, [gain.buffer, finger.buffer])
579
582
  }
583
+ const nearest = [...sent.keys()].sort((a, b) => Math.abs(a - here) - Math.abs(b - here))
584
+ for (const block of nearest.slice(KEPT_BLOCKS)) {
585
+ sent.delete(block)
586
+ toWorklet({ drop: block })
587
+ }
580
588
  }
581
589
  const schedule = () => { timer ??= setTimeout(update, 250) }
582
590