@moq/watch 0.4.0 → 0.4.1

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.
@@ -1,26 +1,27 @@
1
- import { Path as e, Time as t } from "@moq/net";
2
- import { Effect as n, Signal as r, getter as i, readonlys as a } from "@moq/signals";
3
- import * as o from "@moq/hang/catalog";
4
- import { u53 as s } from "@moq/hang/catalog";
5
- import * as c from "@moq/hang/container";
6
- import * as l from "@moq/hang/util";
7
- import * as u from "@moq/json";
8
- import * as d from "@moq/msf";
1
+ import { n as e } from "./sync-zdwVEj9u.js";
2
+ import { Path as t, Time as n } from "@moq/net";
3
+ import { Effect as r, Signal as i, getter as a, readonlys as o } from "@moq/signals";
4
+ import * as s from "@moq/hang/catalog";
5
+ import { u53 as c } from "@moq/hang/catalog";
6
+ import * as l from "@moq/hang/container";
7
+ import * as u from "@moq/hang/util";
8
+ import * as d from "@moq/json";
9
+ import * as f from "@moq/msf";
9
10
  //#region src/base64.ts
10
- function f(e) {
11
+ function p(e) {
11
12
  let t = atob(e), n = new Uint8Array(t.length);
12
13
  for (let e = 0; e < t.length; e++) n[e] = t.charCodeAt(e);
13
14
  return n;
14
15
  }
15
16
  //#endregion
16
17
  //#region src/audio/shared-ring-buffer.ts
17
- var p = 0, m = 1, h = 2, g = 3, _ = 4;
18
- function v(e, t, n, r = !1) {
18
+ var m = 0, h = 1, g = 2, _ = 3, v = 4;
19
+ function y(e, t, n, r = !1) {
19
20
  if (e <= 0) throw Error("invalid channels");
20
21
  if (t <= 0) throw Error("invalid capacity");
21
22
  if (n <= 0) throw Error("invalid sample rate");
22
- let i = new SharedArrayBuffer(e * t * Float32Array.BYTES_PER_ELEMENT), a = new SharedArrayBuffer(_ * Int32Array.BYTES_PER_ELEMENT), o = new Int32Array(a);
23
- return Atomics.store(o, g, 1), {
23
+ let i = new SharedArrayBuffer(e * t * Float32Array.BYTES_PER_ELEMENT), a = new SharedArrayBuffer(v * Int32Array.BYTES_PER_ELEMENT), o = new Int32Array(a);
24
+ return Atomics.store(o, _, 1), {
24
25
  channels: e,
25
26
  capacity: t,
26
27
  rate: n,
@@ -29,20 +30,20 @@ function v(e, t, n, r = !1) {
29
30
  buffered: r
30
31
  };
31
32
  }
32
- function y(e, t) {
33
+ function b(e, t) {
33
34
  return (e - t | 0) > 0 ? e : t;
34
35
  }
35
- function b(e, t) {
36
+ function x(e, t) {
36
37
  return (e % t + t) % t;
37
38
  }
38
- function x(e, t, n) {
39
+ function S(e, t, n) {
39
40
  for (;;) {
40
41
  let r = Atomics.load(e, t);
41
42
  if ((n - r | 0) <= 0) return r;
42
43
  if (Atomics.compareExchange(e, t, r, n) === r) return n;
43
44
  }
44
45
  }
45
- var S = class e {
46
+ var C = class e {
46
47
  channels;
47
48
  capacity;
48
49
  rate;
@@ -55,80 +56,80 @@ var S = class e {
55
56
  this.channels = e.channels, this.capacity = e.capacity, this.rate = e.rate, this.buffered = e.buffered, this.init = e, this.#e = new Int32Array(e.control), this.#t = [];
56
57
  for (let t = 0; t < this.channels; t++) this.#t.push(new Float32Array(e.samples, t * this.capacity * Float32Array.BYTES_PER_ELEMENT, this.capacity));
57
58
  }
58
- insert(e, n) {
59
- if (n.length !== this.channels) throw Error("wrong number of channels");
60
- let r = Math.round(t.Second.fromMicro(e) * this.rate), i = n[0].length, a = 0;
61
- this.buffered && !this.#n && (Atomics.store(this.#e, m, r | 0), Atomics.store(this.#e, p, r | 0), this.#n = !0);
62
- let o = r + i | 0, s = Atomics.load(this.#e, m), c = s - r | 0;
59
+ insert(e, t) {
60
+ if (t.length !== this.channels) throw Error("wrong number of channels");
61
+ let r = Math.round(n.Second.fromMicro(e) * this.rate), i = t[0].length, a = 0;
62
+ this.buffered && !this.#n && (Atomics.store(this.#e, h, r | 0), Atomics.store(this.#e, m, r | 0), this.#n = !0);
63
+ let o = r + i | 0, s = Atomics.load(this.#e, h), c = s - r | 0;
63
64
  if (c > 0) {
64
65
  if (c >= i) return;
65
66
  a = c, r = r + c | 0;
66
67
  }
67
68
  let l = i - a;
68
- (o - s | 0) > this.capacity && x(this.#e, m, o - this.capacity | 0);
69
- let u = Atomics.load(this.#e, p), d = r - u | 0;
69
+ (o - s | 0) > this.capacity && S(this.#e, h, o - this.capacity | 0);
70
+ let u = Atomics.load(this.#e, m), d = r - u | 0;
70
71
  if (d > 0) {
71
72
  let e = Math.min(d, this.capacity);
72
73
  for (let t = 0; t < this.channels; t++) {
73
74
  let n = this.#t[t];
74
- for (let t = 0; t < e; t++) n[b(u + t | 0, this.capacity)] = 0;
75
+ for (let t = 0; t < e; t++) n[x(u + t | 0, this.capacity)] = 0;
75
76
  }
76
77
  }
77
78
  for (let e = 0; e < this.channels; e++) {
78
- let t = n[e], i = this.#t[e];
79
- for (let e = 0; e < l; e++) i[b(r + e | 0, this.capacity)] = t[a + e];
79
+ let n = t[e], i = this.#t[e];
80
+ for (let e = 0; e < l; e++) i[x(r + e | 0, this.capacity)] = n[a + e];
80
81
  }
81
- Atomics.store(this.#e, p, y(Atomics.load(this.#e, p), o));
82
- let f = Atomics.load(this.#e, m), _ = Atomics.load(this.#e, p), v = Atomics.load(this.#e, h);
83
- (_ - f | 0) >= v && v > 0 && Atomics.store(this.#e, g, 0);
82
+ Atomics.store(this.#e, m, b(Atomics.load(this.#e, m), o));
83
+ let f = Atomics.load(this.#e, h), p = Atomics.load(this.#e, m), v = Atomics.load(this.#e, g);
84
+ (p - f | 0) >= v && v > 0 && Atomics.store(this.#e, _, 0);
84
85
  }
85
86
  read(e) {
86
- if (Atomics.load(this.#e, g) === 1) return 0;
87
- let t = Atomics.load(this.#e, m), n = Atomics.load(this.#e, p), r = Atomics.load(this.#e, h), i = n - t | 0;
87
+ if (Atomics.load(this.#e, _) === 1) return 0;
88
+ let t = Atomics.load(this.#e, h), n = Atomics.load(this.#e, m), r = Atomics.load(this.#e, g), i = n - t | 0;
88
89
  if (!this.buffered && r > 0 && i > r) {
89
90
  let e = n - r | 0;
90
- t = x(this.#e, m, e);
91
+ t = S(this.#e, h, e);
91
92
  }
92
93
  let a = n - t | 0, o = Math.min(a, e[0].length);
93
94
  if (o <= 0) return 0;
94
95
  for (let n = 0; n < this.channels; n++) {
95
96
  let r = this.#t[n], i = e[n];
96
- for (let e = 0; e < o; e++) i[e] = r[b(t + e | 0, this.capacity)];
97
+ for (let e = 0; e < o; e++) i[e] = r[x(t + e | 0, this.capacity)];
97
98
  }
98
- return x(this.#e, m, t + o | 0), o;
99
+ return S(this.#e, h, t + o | 0), o;
99
100
  }
100
101
  setLatency(e) {
101
- Atomics.store(this.#e, h, e);
102
+ Atomics.store(this.#e, g, e);
102
103
  }
103
104
  reset() {
104
- this.#n = !1, Atomics.store(this.#e, g, 1);
105
- let e = Atomics.load(this.#e, p);
106
- Atomics.store(this.#e, m, e);
105
+ this.#n = !1, Atomics.store(this.#e, _, 1);
106
+ let e = Atomics.load(this.#e, m);
107
+ Atomics.store(this.#e, h, e);
107
108
  }
108
109
  resize(t) {
109
- let n = v(this.channels, t, this.rate, this.buffered), r = new e(n);
110
+ let n = y(this.channels, t, this.rate, this.buffered), r = new e(n);
110
111
  r.#n = this.#n;
111
- let i = Atomics.load(this.#e, m), a = Atomics.load(this.#e, p), o = Atomics.load(this.#e, h), s = Atomics.load(this.#e, g), c = a - i | 0, l = Math.max(0, Math.min(c, r.capacity)), u = a - l | 0;
112
+ let i = Atomics.load(this.#e, h), a = Atomics.load(this.#e, m), o = Atomics.load(this.#e, g), s = Atomics.load(this.#e, _), c = a - i | 0, l = Math.max(0, Math.min(c, r.capacity)), u = a - l | 0;
112
113
  for (let e = 0; e < this.channels; e++) {
113
114
  let t = this.#t[e], n = r.#t[e];
114
115
  for (let e = 0; e < l; e++) {
115
116
  let i = u + e | 0;
116
- n[b(i, r.capacity)] = t[b(i, this.capacity)];
117
+ n[x(i, r.capacity)] = t[x(i, this.capacity)];
117
118
  }
118
119
  }
119
- return Atomics.store(r.#e, m, u), Atomics.store(r.#e, p, a), Atomics.store(r.#e, h, o), Atomics.store(r.#e, g, s), r;
120
+ return Atomics.store(r.#e, h, u), Atomics.store(r.#e, m, a), Atomics.store(r.#e, g, o), Atomics.store(r.#e, _, s), r;
120
121
  }
121
122
  get timestamp() {
122
- let e = Atomics.load(this.#e, m);
123
- return t.Micro.fromSecond(e / this.rate);
123
+ let e = Atomics.load(this.#e, h);
124
+ return n.Micro.fromSecond(e / this.rate);
124
125
  }
125
126
  get stalled() {
126
- return Atomics.load(this.#e, g) === 1;
127
+ return Atomics.load(this.#e, _) === 1;
127
128
  }
128
129
  get length() {
129
- return Atomics.load(this.#e, p) - Atomics.load(this.#e, m) | 0;
130
+ return Atomics.load(this.#e, m) - Atomics.load(this.#e, h) | 0;
130
131
  }
131
- }, C = class {
132
+ }, w = class {
132
133
  #e;
133
134
  #t;
134
135
  #n = [];
@@ -152,32 +153,32 @@ var S = class e {
152
153
  this.#n = [];
153
154
  }
154
155
  };
155
- function w(e, n) {
156
- return t.Micro.fromSecond(e / n);
156
+ function T(e, t) {
157
+ return n.Micro.fromSecond(e / t);
157
158
  }
158
- function T() {
159
+ function E() {
159
160
  return !(typeof SharedArrayBuffer > "u" || typeof crossOriginIsolated < "u" && !crossOriginIsolated);
160
161
  }
161
- function E(e, t, n, r, i = !1) {
162
- return T() ? (console.log("[audio] using SharedArrayBuffer audio buffer"), new D(e, t, n, r, i)) : (console.log("[audio] using postMessage audio buffer (SharedArrayBuffer unavailable)"), new O(e, t, n, r, i));
162
+ function D(e, t, n, r, i = !1) {
163
+ return E() ? (console.log("[audio] using SharedArrayBuffer audio buffer"), new O(e, t, n, r, i)) : (console.log("[audio] using postMessage audio buffer (SharedArrayBuffer unavailable)"), new k(e, t, n, r, i));
163
164
  }
164
- var D = class {
165
+ var O = class {
165
166
  rate;
166
167
  channels;
167
168
  #e;
168
169
  #t;
169
- #n = new r(0);
170
+ #n = new i(0);
170
171
  timestamp = this.#n;
171
- #r = new r(!0);
172
+ #r = new i(!0);
172
173
  stalled = this.#r;
173
174
  #i;
174
- #a = new n();
175
+ #a = new r();
175
176
  constructor(e, t, n, r, i) {
176
177
  this.#e = e, this.channels = t, this.rate = n;
177
178
  let a = Math.max(n, r * 2);
178
- this.#i = new C(i, w(r, n));
179
- let o = v(t, a, n, i);
180
- this.#t = new S(o), this.#t.setLatency(r);
179
+ this.#i = new w(i, T(r, n));
180
+ let o = y(t, a, n, i);
181
+ this.#t = new C(o), this.#t.setLatency(r);
181
182
  let s = {
182
183
  type: "init-shared",
183
184
  ...o
@@ -191,7 +192,7 @@ var D = class {
191
192
  this.#t.insert(e, t);
192
193
  }
193
194
  setLatency(e) {
194
- if (this.#i.setHeadroom(w(e, this.rate)), this.#t.capacity < e * 1.5) {
195
+ if (this.#i.setHeadroom(T(e, this.rate)), this.#t.capacity < e * 1.5) {
195
196
  let t = Math.max(this.rate, e * 2);
196
197
  this.#t = this.#t.resize(t), this.#t.setLatency(e);
197
198
  let n = {
@@ -210,23 +211,23 @@ var D = class {
210
211
  close() {
211
212
  this.#i.flush(), this.#a.close();
212
213
  }
213
- }, O = class {
214
+ }, k = class {
214
215
  rate;
215
216
  channels;
216
217
  #e;
217
- #t = new r(0);
218
+ #t = new i(0);
218
219
  timestamp = this.#t;
219
- #n = new r(!0);
220
+ #n = new i(!0);
220
221
  stalled = this.#n;
221
222
  #r;
222
- #i = new n();
223
- constructor(e, n, r, i, a) {
224
- this.#e = e, this.channels = n, this.rate = r, this.#r = new C(a, w(i, r));
223
+ #i = new r();
224
+ constructor(e, t, r, i, a) {
225
+ this.#e = e, this.channels = t, this.rate = r, this.#r = new w(a, T(i, r));
225
226
  let o = {
226
227
  type: "init-post",
227
- channels: n,
228
+ channels: t,
228
229
  rate: r,
229
- latency: t.Milli.fromSecond(i / r),
230
+ latency: n.Milli.fromSecond(i / r),
230
231
  buffered: a
231
232
  };
232
233
  e.port.postMessage(o), this.#i.event(e.port, "message", (e) => {
@@ -243,12 +244,12 @@ var D = class {
243
244
  this.#e.port.postMessage(n, t.map((e) => e.buffer));
244
245
  }
245
246
  setLatency(e) {
246
- this.#r.setHeadroom(w(e, this.rate));
247
- let n = {
247
+ this.#r.setHeadroom(T(e, this.rate));
248
+ let t = {
248
249
  type: "latency",
249
- latency: t.Milli.fromSecond(e / this.rate)
250
+ latency: n.Milli.fromSecond(e / this.rate)
250
251
  };
251
- this.#e.port.postMessage(n);
252
+ this.#e.port.postMessage(t);
252
253
  }
253
254
  reset() {
254
255
  this.#e.port.postMessage({ type: "reset" }), this.#r.flush();
@@ -259,11 +260,11 @@ var D = class {
259
260
  close() {
260
261
  this.#r.flush(), this.#i.close();
261
262
  }
262
- }, k = new Blob(["var __defProp = Object.defineProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\n\n// ../net/src/time.ts\nvar time_exports = {};\n__export(time_exports, {\n Micro: () => Micro,\n Milli: () => Milli,\n Nano: () => Nano,\n Second: () => Second,\n Timescale: () => Timescale,\n Timestamp: () => Timestamp\n});\nvar Nano = Object.assign((value) => value, {\n zero: 0,\n fromMicro: (us) => us * 1e3,\n fromMilli: (ms) => ms * 1e6,\n fromSecond: (s) => s * 1e9,\n toMicro: (ns) => ns / 1e3,\n toMilli: (ns) => ns / 1e6,\n toSecond: (ns) => ns / 1e9,\n now: () => performance.now() * 1e6,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Micro = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e3,\n fromMilli: (ms) => ms * 1e3,\n fromSecond: (s) => s * 1e6,\n toNano: (us) => us * 1e3,\n toMilli: (us) => us / 1e3,\n toSecond: (us) => us / 1e6,\n now: () => performance.now() * 1e3,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Milli = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e6,\n fromMicro: (us) => us / 1e3,\n fromSecond: (s) => s * 1e3,\n toNano: (ms) => ms * 1e6,\n toMicro: (ms) => ms * 1e3,\n toSecond: (ms) => ms / 1e3,\n now: () => performance.now(),\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Timescale = Object.assign(\n (unitsPerSecond) => {\n if (!Number.isInteger(unitsPerSecond) || unitsPerSecond <= 0) {\n throw new Error(`invalid timescale: ${unitsPerSecond}`);\n }\n return unitsPerSecond;\n },\n {\n /** One unit per second. */\n SECOND: 1,\n /** 1,000 units per second. */\n MILLI: 1e3,\n /** 1,000,000 units per second. */\n MICRO: 1e6,\n /** 1,000,000,000 units per second. */\n NANO: 1e9\n }\n);\nvar Timestamp = class _Timestamp {\n /** The raw value, in `scale` units. */\n value;\n /** Units per second the {@link value} is measured in. */\n scale;\n /** Build a timestamp of `value` units at `scale`. */\n constructor(value, scale) {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`invalid timestamp: ${value}`);\n }\n this.value = value;\n this.scale = scale;\n }\n /** Monotonic now (`performance.now()`, milliseconds since page load), not wall-clock time. */\n static now() {\n return new _Timestamp(performance.now(), Timescale.MILLI);\n }\n /** A timestamp of `ms` milliseconds. */\n static fromMillis(ms) {\n return new _Timestamp(ms, Timescale.MILLI);\n }\n /** A timestamp of `us` microseconds. */\n static fromMicros(us) {\n return new _Timestamp(us, Timescale.MICRO);\n }\n /** This timestamp's value re-expressed at `scale` (a raw number, not a new Timestamp). */\n as(scale) {\n return scale === this.scale ? this.value : this.value * scale / this.scale;\n }\n /** The value in milliseconds. */\n asMillis() {\n return this.as(Timescale.MILLI);\n }\n /** The value in microseconds. */\n asMicros() {\n return this.as(Timescale.MICRO);\n }\n};\nvar Second = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e9,\n fromMicro: (us) => us / 1e6,\n fromMilli: (ms) => ms / 1e3,\n toNano: (s) => s * 1e9,\n toMicro: (s) => s * 1e6,\n toMilli: (s) => s * 1e3,\n now: () => performance.now() / 1e3,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\n\n// src/audio/ring-buffer.ts\nvar AudioRingBuffer = class {\n #buffer;\n #writeIndex = 0;\n #readIndex = 0;\n rate;\n channels;\n #stalled = true;\n // Buffered mode: anchor to the first sample, play through without skipping ahead.\n #buffered;\n // Un-stall threshold in samples (how much to buffer before playback starts).\n #latencySamples;\n // Whether the read/write indices have been anchored to the first inserted sample.\n #anchored = false;\n constructor(props) {\n if (props.channels <= 0) throw new Error(\"invalid channels\");\n if (props.rate <= 0) throw new Error(\"invalid sample rate\");\n if (props.latency <= 0) throw new Error(\"invalid latency\");\n this.#latencySamples = Math.ceil(props.rate * time_exports.Second.fromMilli(props.latency));\n if (this.#latencySamples === 0) throw new Error(\"empty buffer\");\n this.rate = props.rate;\n this.channels = props.channels;\n this.#buffered = props.buffered ?? false;\n const capacity = this.#capacityFor(this.#latencySamples);\n this.#buffer = [];\n for (let i = 0; i < this.channels; i++) {\n this.#buffer[i] = new Float32Array(capacity);\n }\n }\n #capacityFor(latencySamples) {\n return this.#buffered ? latencySamples * 2 : latencySamples;\n }\n get stalled() {\n return this.#stalled;\n }\n get timestamp() {\n return time_exports.Micro.fromSecond(this.#readIndex / this.rate);\n }\n get length() {\n return this.#writeIndex - this.#readIndex;\n }\n get capacity() {\n return this.#buffer[0]?.length;\n }\n resize(latency) {\n this.#latencySamples = Math.ceil(this.rate * time_exports.Second.fromMilli(latency));\n const newCapacity = this.#capacityFor(this.#latencySamples);\n if (newCapacity === this.capacity) return;\n if (newCapacity === 0) throw new Error(\"empty buffer\");\n const newBuffer = [];\n for (let i = 0; i < this.channels; i++) {\n newBuffer[i] = new Float32Array(newCapacity);\n }\n const samplesToKeep = Math.min(this.length, newCapacity);\n if (samplesToKeep > 0) {\n const copyStart = this.#writeIndex - samplesToKeep;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#buffer[channel];\n const dst = newBuffer[channel];\n for (let i = 0; i < samplesToKeep; i++) {\n const srcPos = (copyStart + i) % src.length;\n const dstPos = (copyStart + i) % dst.length;\n dst[dstPos] = src[srcPos];\n }\n }\n }\n this.#buffer = newBuffer;\n this.#readIndex = this.#writeIndex - samplesToKeep;\n if (samplesToKeep === 0) this.#stalled = true;\n }\n write(timestamp, data) {\n if (data.length !== this.channels) throw new Error(\"wrong number of channels\");\n let start = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate);\n let samples = data[0].length;\n if (this.#buffered && !this.#anchored) {\n this.#readIndex = start;\n this.#writeIndex = start;\n this.#anchored = true;\n }\n let offset = this.#readIndex - start;\n if (offset > samples) {\n return;\n } else if (offset > 0) {\n samples -= offset;\n start += offset;\n } else {\n offset = 0;\n }\n const end = start + samples;\n const overflow = end - this.#readIndex - this.#buffer[0].length;\n if (overflow >= 0) {\n this.#stalled = false;\n this.#readIndex += overflow;\n }\n if (start > this.#writeIndex) {\n const gapSize = Math.min(start - this.#writeIndex, this.#buffer[0].length);\n if (gapSize === 1) {\n console.warn(\"floating point inaccuracy detected\");\n }\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = this.#buffer[channel];\n for (let i = 0; i < gapSize; i++) {\n const writePos = (this.#writeIndex + i) % dst.length;\n dst[writePos] = 0;\n }\n }\n }\n for (let channel = 0; channel < this.channels; channel++) {\n let src = data[channel];\n src = src.subarray(src.length - samples);\n const dst = this.#buffer[channel];\n if (src.length !== samples) throw new Error(\"mismatching number of samples\");\n for (let i = 0; i < samples; i++) {\n const writePos = (start + i) % dst.length;\n dst[writePos] = src[i];\n }\n }\n if (end > this.#writeIndex) {\n this.#writeIndex = end;\n }\n if (this.#buffered && this.length >= this.#latencySamples) {\n this.#stalled = false;\n }\n }\n // Flush all buffered samples and re-stall, ready to anchor the next utterance.\n reset() {\n this.#readIndex = 0;\n this.#writeIndex = 0;\n this.#stalled = true;\n this.#anchored = false;\n }\n read(output) {\n if (output.length !== this.channels) throw new Error(\"wrong number of channels\");\n if (this.#stalled) return 0;\n const samples = Math.min(this.#writeIndex - this.#readIndex, output[0].length);\n if (samples === 0) return 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = output[channel];\n const src = this.#buffer[channel];\n if (dst.length !== output[0].length) throw new Error(\"mismatching number of samples\");\n for (let i = 0; i < samples; i++) {\n const readPos = (this.#readIndex + i) % src.length;\n dst[i] = src[readPos];\n }\n }\n this.#readIndex += samples;\n return samples;\n }\n};\n\n// src/audio/shared-ring-buffer.ts\nvar WRITE = 0;\nvar READ = 1;\nvar LATENCY = 2;\nvar STALLED = 3;\nvar CONTROL_SLOTS = 4;\nfunction allocSharedRingBuffer(channels, capacity, rate, buffered = false) {\n if (channels <= 0) throw new Error(\"invalid channels\");\n if (capacity <= 0) throw new Error(\"invalid capacity\");\n if (rate <= 0) throw new Error(\"invalid sample rate\");\n const samples = new SharedArrayBuffer(channels * capacity * Float32Array.BYTES_PER_ELEMENT);\n const control = new SharedArrayBuffer(CONTROL_SLOTS * Int32Array.BYTES_PER_ELEMENT);\n const ctrl = new Int32Array(control);\n Atomics.store(ctrl, STALLED, 1);\n return { channels, capacity, rate, samples, control, buffered };\n}\nfunction i32Max(a, b) {\n return (a - b | 0) > 0 ? a : b;\n}\nfunction slot(idx, capacity) {\n return (idx % capacity + capacity) % capacity;\n}\nfunction casAdvance(arr, idx, candidate) {\n for (; ; ) {\n const current = Atomics.load(arr, idx);\n if ((candidate - current | 0) <= 0) return current;\n const witnessed = Atomics.compareExchange(arr, idx, current, candidate);\n if (witnessed === current) return candidate;\n }\n}\nvar SharedRingBuffer = class _SharedRingBuffer {\n channels;\n capacity;\n rate;\n buffered;\n init;\n #control;\n #samples;\n // Whether READ/WRITE have been anchored to the first inserted sample (buffered mode).\n #anchored = false;\n constructor(init) {\n this.channels = init.channels;\n this.capacity = init.capacity;\n this.rate = init.rate;\n this.buffered = init.buffered;\n this.init = init;\n this.#control = new Int32Array(init.control);\n this.#samples = [];\n for (let i = 0; i < this.channels; i++) {\n this.#samples.push(\n new Float32Array(init.samples, i * this.capacity * Float32Array.BYTES_PER_ELEMENT, this.capacity)\n );\n }\n }\n /**\n * Insert audio samples at the given timestamp.\n * Main thread only. Handles out-of-order writes, gap filling, and overflow.\n */\n insert(timestamp, data) {\n if (data.length !== this.channels) throw new Error(\"wrong number of channels\");\n let start = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate);\n const originalLength = data[0].length;\n let offset = 0;\n if (this.buffered && !this.#anchored) {\n Atomics.store(this.#control, READ, start | 0);\n Atomics.store(this.#control, WRITE, start | 0);\n this.#anchored = true;\n }\n const end = start + originalLength | 0;\n const read = Atomics.load(this.#control, READ);\n const behind = read - start | 0;\n if (behind > 0) {\n if (behind >= originalLength) {\n return;\n }\n offset = behind;\n start = start + behind | 0;\n }\n const samples = originalLength - offset;\n if ((end - read | 0) > this.capacity) {\n casAdvance(this.#control, READ, end - this.capacity | 0);\n }\n const write = Atomics.load(this.#control, WRITE);\n const gap = start - write | 0;\n if (gap > 0) {\n const gapSize = Math.min(gap, this.capacity);\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = this.#samples[channel];\n for (let i = 0; i < gapSize; i++) {\n dst[slot(write + i | 0, this.capacity)] = 0;\n }\n }\n }\n for (let channel = 0; channel < this.channels; channel++) {\n const src = data[channel];\n const dst = this.#samples[channel];\n for (let i = 0; i < samples; i++) {\n dst[slot(start + i | 0, this.capacity)] = src[offset + i];\n }\n }\n Atomics.store(this.#control, WRITE, i32Max(Atomics.load(this.#control, WRITE), end));\n const currentRead = Atomics.load(this.#control, READ);\n const currentWrite = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n if ((currentWrite - currentRead | 0) >= latency && latency > 0) {\n Atomics.store(this.#control, STALLED, 0);\n }\n }\n /**\n * Read audio samples into the output buffers.\n * AudioWorklet only. Returns the number of samples read.\n */\n read(output) {\n if (Atomics.load(this.#control, STALLED) === 1) return 0;\n let read = Atomics.load(this.#control, READ);\n const write = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n const buffered = write - read | 0;\n if (!this.buffered && latency > 0 && buffered > latency) {\n const skipTo = write - latency | 0;\n read = casAdvance(this.#control, READ, skipTo);\n }\n const available = write - read | 0;\n const count = Math.min(available, output[0].length);\n if (count <= 0) return 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#samples[channel];\n const dst = output[channel];\n for (let i = 0; i < count; i++) {\n dst[i] = src[slot(read + i | 0, this.capacity)];\n }\n }\n casAdvance(this.#control, READ, read + count | 0);\n return count;\n }\n /** Update the target latency in samples. */\n setLatency(samples) {\n Atomics.store(this.#control, LATENCY, samples);\n }\n /**\n * Flush buffered samples and re-stall, ready to anchor the next utterance (buffered mode).\n * Main thread only. The worklet reader sees STALLED and stops until the next insert.\n */\n reset() {\n this.#anchored = false;\n Atomics.store(this.#control, STALLED, 1);\n const write = Atomics.load(this.#control, WRITE);\n Atomics.store(this.#control, READ, write);\n }\n /**\n * Allocate a new ring with `newCapacity` samples and copy the unread window\n * [READ, WRITE) plus control state into it. Used when growing capacity so\n * we don't drop buffered audio. If `newCapacity` is smaller than the unread\n * span, the oldest samples are truncated.\n *\n * Main thread only. `resize()` reads from the source `SharedRingBuffer` and\n * writes into a freshly allocated buffer from `allocSharedRingBuffer`, so it\n * relies on the same invariant as `insert()`: no concurrent main-thread\n * writers. The AudioWorklet reader is tolerated via the CAS discipline used\n * by READ/WRITE elsewhere.\n */\n resize(newCapacity) {\n const init = allocSharedRingBuffer(this.channels, newCapacity, this.rate, this.buffered);\n const dst = new _SharedRingBuffer(init);\n dst.#anchored = this.#anchored;\n const read = Atomics.load(this.#control, READ);\n const write = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n const stalled = Atomics.load(this.#control, STALLED);\n const available = write - read | 0;\n const copyCount = Math.max(0, Math.min(available, dst.capacity));\n const copyStart = write - copyCount | 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#samples[channel];\n const out = dst.#samples[channel];\n for (let i = 0; i < copyCount; i++) {\n const idx = copyStart + i | 0;\n out[slot(idx, dst.capacity)] = src[slot(idx, this.capacity)];\n }\n }\n Atomics.store(dst.#control, READ, copyStart);\n Atomics.store(dst.#control, WRITE, write);\n Atomics.store(dst.#control, LATENCY, latency);\n Atomics.store(dst.#control, STALLED, stalled);\n return dst;\n }\n /** Current playback timestamp derived from READ position. */\n get timestamp() {\n const read = Atomics.load(this.#control, READ);\n return time_exports.Micro.fromSecond(read / this.rate);\n }\n /** Whether the buffer is stalled (waiting to fill). */\n get stalled() {\n return Atomics.load(this.#control, STALLED) === 1;\n }\n /**\n * Number of buffered samples (WRITE - READ).\n *\n * Non-atomic: WRITE and READ are loaded separately, so a concurrent\n * writer/reader can make the two loads inconsistent. Intended for\n * tests and diagnostics, not control-flow decisions.\n */\n get length() {\n return Atomics.load(this.#control, WRITE) - Atomics.load(this.#control, READ) | 0;\n }\n};\n\n// src/audio/render-worklet.ts\nvar Render = class extends AudioWorkletProcessor {\n // Set after init, depending on which path the main thread chose.\n #backend;\n #underflow = 0;\n #stateCounter = 0;\n constructor() {\n super();\n this.port.onmessage = (event) => {\n const msg = event.data;\n if (msg.type === \"init-shared\") {\n console.log(\"[audio-worklet] init-shared: using SharedArrayBuffer path\");\n this.#backend = new SharedRingBuffer(msg);\n this.#underflow = 0;\n } else if (msg.type === \"init-post\") {\n console.log(\"[audio-worklet] init-post: using postMessage path\");\n this.#backend = new AudioRingBuffer(msg);\n this.#underflow = 0;\n } else if (msg.type === \"data\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.write(msg.timestamp, msg.data);\n } else if (msg.type === \"latency\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.resize(msg.latency);\n } else if (msg.type === \"reset\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.reset();\n }\n };\n }\n process(_inputs, outputs, _parameters) {\n const output = outputs[0];\n const backend = this.#backend;\n const samplesRead = backend?.read(output) ?? 0;\n if (samplesRead < output[0].length) {\n this.#underflow += output[0].length - samplesRead;\n } else if (this.#underflow > 0 && backend) {\n console.debug(`audio underflow: ${Math.round(1e3 * this.#underflow / backend.rate)}ms`);\n this.#underflow = 0;\n }\n if (backend instanceof AudioRingBuffer) {\n this.#stateCounter++;\n if (this.#stateCounter >= 5) {\n this.#stateCounter = 0;\n const state = {\n type: \"state\",\n timestamp: backend.timestamp,\n stalled: backend.stalled\n };\n this.port.postMessage(state);\n }\n }\n return true;\n }\n};\nregisterProcessor(\"render\", Render);\n"], { type: "application/javascript" }), ee = URL.createObjectURL(k);
263
+ }, A = new Blob(["var __defProp = Object.defineProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\n\n// ../net/src/time.ts\nvar time_exports = {};\n__export(time_exports, {\n Micro: () => Micro,\n Milli: () => Milli,\n Nano: () => Nano,\n Second: () => Second,\n Timescale: () => Timescale,\n Timestamp: () => Timestamp\n});\nvar Nano = Object.assign((value) => value, {\n zero: 0,\n fromMicro: (us) => us * 1e3,\n fromMilli: (ms) => ms * 1e6,\n fromSecond: (s) => s * 1e9,\n toMicro: (ns) => ns / 1e3,\n toMilli: (ns) => ns / 1e6,\n toSecond: (ns) => ns / 1e9,\n now: () => performance.now() * 1e6,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Micro = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e3,\n fromMilli: (ms) => ms * 1e3,\n fromSecond: (s) => s * 1e6,\n toNano: (us) => us * 1e3,\n toMilli: (us) => us / 1e3,\n toSecond: (us) => us / 1e6,\n now: () => performance.now() * 1e3,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Milli = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e6,\n fromMicro: (us) => us / 1e3,\n fromSecond: (s) => s * 1e3,\n toNano: (ms) => ms * 1e6,\n toMicro: (ms) => ms * 1e3,\n toSecond: (ms) => ms / 1e3,\n now: () => performance.now(),\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\nvar Timescale = Object.assign(\n (unitsPerSecond) => {\n if (!Number.isInteger(unitsPerSecond) || unitsPerSecond <= 0) {\n throw new Error(`invalid timescale: ${unitsPerSecond}`);\n }\n return unitsPerSecond;\n },\n {\n /** One unit per second. */\n SECOND: 1,\n /** 1,000 units per second. */\n MILLI: 1e3,\n /** 1,000,000 units per second. */\n MICRO: 1e6,\n /** 1,000,000,000 units per second. */\n NANO: 1e9\n }\n);\nvar Timestamp = class _Timestamp {\n /** The raw value, in `scale` units. */\n value;\n /** Units per second the {@link value} is measured in. */\n scale;\n /** Build a timestamp of `value` units at `scale`. */\n constructor(value, scale) {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`invalid timestamp: ${value}`);\n }\n this.value = value;\n this.scale = scale;\n }\n /** Monotonic now (`performance.now()`, milliseconds since page load), not wall-clock time. */\n static now() {\n return new _Timestamp(performance.now(), Timescale.MILLI);\n }\n /** A timestamp of `ms` milliseconds. */\n static fromMillis(ms) {\n return new _Timestamp(ms, Timescale.MILLI);\n }\n /** A timestamp of `us` microseconds. */\n static fromMicros(us) {\n return new _Timestamp(us, Timescale.MICRO);\n }\n /** This timestamp's value re-expressed at `scale` (a raw number, not a new Timestamp). */\n as(scale) {\n return scale === this.scale ? this.value : this.value * scale / this.scale;\n }\n /** The value in milliseconds. */\n asMillis() {\n return this.as(Timescale.MILLI);\n }\n /** The value in microseconds. */\n asMicros() {\n return this.as(Timescale.MICRO);\n }\n};\nvar Second = Object.assign((value) => value, {\n zero: 0,\n fromNano: (ns) => ns / 1e9,\n fromMicro: (us) => us / 1e6,\n fromMilli: (ms) => ms / 1e3,\n toNano: (s) => s * 1e9,\n toMicro: (s) => s * 1e6,\n toMilli: (s) => s * 1e3,\n now: () => performance.now() / 1e3,\n add: (a, b) => a + b,\n sub: (a, b) => a - b,\n mul: (a, b) => a * b,\n div: (a, b) => a / b,\n max: (a, b) => Math.max(a, b),\n min: (a, b) => Math.min(a, b)\n});\n\n// src/audio/ring-buffer.ts\nvar AudioRingBuffer = class {\n #buffer;\n #writeIndex = 0;\n #readIndex = 0;\n rate;\n channels;\n #stalled = true;\n // Buffered mode: anchor to the first sample, play through without skipping ahead.\n #buffered;\n // Un-stall threshold in samples (how much to buffer before playback starts).\n #latencySamples;\n // Whether the read/write indices have been anchored to the first inserted sample.\n #anchored = false;\n constructor(props) {\n if (props.channels <= 0) throw new Error(\"invalid channels\");\n if (props.rate <= 0) throw new Error(\"invalid sample rate\");\n if (props.latency <= 0) throw new Error(\"invalid latency\");\n this.#latencySamples = Math.ceil(props.rate * time_exports.Second.fromMilli(props.latency));\n if (this.#latencySamples === 0) throw new Error(\"empty buffer\");\n this.rate = props.rate;\n this.channels = props.channels;\n this.#buffered = props.buffered ?? false;\n const capacity = this.#capacityFor(this.#latencySamples);\n this.#buffer = [];\n for (let i = 0; i < this.channels; i++) {\n this.#buffer[i] = new Float32Array(capacity);\n }\n }\n #capacityFor(latencySamples) {\n return this.#buffered ? latencySamples * 2 : latencySamples;\n }\n get stalled() {\n return this.#stalled;\n }\n get timestamp() {\n return time_exports.Micro.fromSecond(this.#readIndex / this.rate);\n }\n get length() {\n return this.#writeIndex - this.#readIndex;\n }\n get capacity() {\n return this.#buffer[0]?.length;\n }\n resize(latency) {\n this.#latencySamples = Math.ceil(this.rate * time_exports.Second.fromMilli(latency));\n const newCapacity = this.#capacityFor(this.#latencySamples);\n if (newCapacity === this.capacity) return;\n if (newCapacity === 0) throw new Error(\"empty buffer\");\n const newBuffer = [];\n for (let i = 0; i < this.channels; i++) {\n newBuffer[i] = new Float32Array(newCapacity);\n }\n const samplesToKeep = Math.min(this.length, newCapacity);\n if (samplesToKeep > 0) {\n const copyStart = this.#writeIndex - samplesToKeep;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#buffer[channel];\n const dst = newBuffer[channel];\n for (let i = 0; i < samplesToKeep; i++) {\n const srcPos = (copyStart + i) % src.length;\n const dstPos = (copyStart + i) % dst.length;\n dst[dstPos] = src[srcPos];\n }\n }\n }\n this.#buffer = newBuffer;\n this.#readIndex = this.#writeIndex - samplesToKeep;\n if (samplesToKeep === 0) this.#stalled = true;\n }\n write(timestamp, data) {\n if (data.length !== this.channels) throw new Error(\"wrong number of channels\");\n let start = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate);\n let samples = data[0].length;\n if (this.#buffered && !this.#anchored) {\n this.#readIndex = start;\n this.#writeIndex = start;\n this.#anchored = true;\n }\n let offset = this.#readIndex - start;\n if (offset > samples) {\n return;\n } else if (offset > 0) {\n samples -= offset;\n start += offset;\n } else {\n offset = 0;\n }\n const end = start + samples;\n const overflow = end - this.#readIndex - this.#buffer[0].length;\n if (overflow >= 0) {\n this.#stalled = false;\n this.#readIndex += overflow;\n }\n if (start > this.#writeIndex) {\n const gapSize = Math.min(start - this.#writeIndex, this.#buffer[0].length);\n if (gapSize === 1) {\n console.warn(\"floating point inaccuracy detected\");\n }\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = this.#buffer[channel];\n for (let i = 0; i < gapSize; i++) {\n const writePos = (this.#writeIndex + i) % dst.length;\n dst[writePos] = 0;\n }\n }\n }\n for (let channel = 0; channel < this.channels; channel++) {\n let src = data[channel];\n src = src.subarray(src.length - samples);\n const dst = this.#buffer[channel];\n if (src.length !== samples) throw new Error(\"mismatching number of samples\");\n for (let i = 0; i < samples; i++) {\n const writePos = (start + i) % dst.length;\n dst[writePos] = src[i];\n }\n }\n if (end > this.#writeIndex) {\n this.#writeIndex = end;\n }\n if (this.#buffered && this.length >= this.#latencySamples) {\n this.#stalled = false;\n }\n }\n // Flush all buffered samples and re-stall, ready to anchor the next utterance.\n reset() {\n this.#readIndex = 0;\n this.#writeIndex = 0;\n this.#stalled = true;\n this.#anchored = false;\n }\n read(output) {\n if (output.length !== this.channels) throw new Error(\"wrong number of channels\");\n if (this.#stalled) return 0;\n const samples = Math.min(this.#writeIndex - this.#readIndex, output[0].length);\n if (samples === 0) return 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = output[channel];\n const src = this.#buffer[channel];\n if (dst.length !== output[0].length) throw new Error(\"mismatching number of samples\");\n for (let i = 0; i < samples; i++) {\n const readPos = (this.#readIndex + i) % src.length;\n dst[i] = src[readPos];\n }\n }\n this.#readIndex += samples;\n return samples;\n }\n};\n\n// src/audio/shared-ring-buffer.ts\nvar WRITE = 0;\nvar READ = 1;\nvar LATENCY = 2;\nvar STALLED = 3;\nvar CONTROL_SLOTS = 4;\nfunction allocSharedRingBuffer(channels, capacity, rate, buffered = false) {\n if (channels <= 0) throw new Error(\"invalid channels\");\n if (capacity <= 0) throw new Error(\"invalid capacity\");\n if (rate <= 0) throw new Error(\"invalid sample rate\");\n const samples = new SharedArrayBuffer(channels * capacity * Float32Array.BYTES_PER_ELEMENT);\n const control = new SharedArrayBuffer(CONTROL_SLOTS * Int32Array.BYTES_PER_ELEMENT);\n const ctrl = new Int32Array(control);\n Atomics.store(ctrl, STALLED, 1);\n return { channels, capacity, rate, samples, control, buffered };\n}\nfunction i32Max(a, b) {\n return (a - b | 0) > 0 ? a : b;\n}\nfunction slot(idx, capacity) {\n return (idx % capacity + capacity) % capacity;\n}\nfunction casAdvance(arr, idx, candidate) {\n for (; ; ) {\n const current = Atomics.load(arr, idx);\n if ((candidate - current | 0) <= 0) return current;\n const witnessed = Atomics.compareExchange(arr, idx, current, candidate);\n if (witnessed === current) return candidate;\n }\n}\nvar SharedRingBuffer = class _SharedRingBuffer {\n channels;\n capacity;\n rate;\n buffered;\n init;\n #control;\n #samples;\n // Whether READ/WRITE have been anchored to the first inserted sample (buffered mode).\n #anchored = false;\n constructor(init) {\n this.channels = init.channels;\n this.capacity = init.capacity;\n this.rate = init.rate;\n this.buffered = init.buffered;\n this.init = init;\n this.#control = new Int32Array(init.control);\n this.#samples = [];\n for (let i = 0; i < this.channels; i++) {\n this.#samples.push(\n new Float32Array(init.samples, i * this.capacity * Float32Array.BYTES_PER_ELEMENT, this.capacity)\n );\n }\n }\n /**\n * Insert audio samples at the given timestamp.\n * Main thread only. Handles out-of-order writes, gap filling, and overflow.\n */\n insert(timestamp, data) {\n if (data.length !== this.channels) throw new Error(\"wrong number of channels\");\n let start = Math.round(time_exports.Second.fromMicro(timestamp) * this.rate);\n const originalLength = data[0].length;\n let offset = 0;\n if (this.buffered && !this.#anchored) {\n Atomics.store(this.#control, READ, start | 0);\n Atomics.store(this.#control, WRITE, start | 0);\n this.#anchored = true;\n }\n const end = start + originalLength | 0;\n const read = Atomics.load(this.#control, READ);\n const behind = read - start | 0;\n if (behind > 0) {\n if (behind >= originalLength) {\n return;\n }\n offset = behind;\n start = start + behind | 0;\n }\n const samples = originalLength - offset;\n if ((end - read | 0) > this.capacity) {\n casAdvance(this.#control, READ, end - this.capacity | 0);\n }\n const write = Atomics.load(this.#control, WRITE);\n const gap = start - write | 0;\n if (gap > 0) {\n const gapSize = Math.min(gap, this.capacity);\n for (let channel = 0; channel < this.channels; channel++) {\n const dst = this.#samples[channel];\n for (let i = 0; i < gapSize; i++) {\n dst[slot(write + i | 0, this.capacity)] = 0;\n }\n }\n }\n for (let channel = 0; channel < this.channels; channel++) {\n const src = data[channel];\n const dst = this.#samples[channel];\n for (let i = 0; i < samples; i++) {\n dst[slot(start + i | 0, this.capacity)] = src[offset + i];\n }\n }\n Atomics.store(this.#control, WRITE, i32Max(Atomics.load(this.#control, WRITE), end));\n const currentRead = Atomics.load(this.#control, READ);\n const currentWrite = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n if ((currentWrite - currentRead | 0) >= latency && latency > 0) {\n Atomics.store(this.#control, STALLED, 0);\n }\n }\n /**\n * Read audio samples into the output buffers.\n * AudioWorklet only. Returns the number of samples read.\n */\n read(output) {\n if (Atomics.load(this.#control, STALLED) === 1) return 0;\n let read = Atomics.load(this.#control, READ);\n const write = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n const buffered = write - read | 0;\n if (!this.buffered && latency > 0 && buffered > latency) {\n const skipTo = write - latency | 0;\n read = casAdvance(this.#control, READ, skipTo);\n }\n const available = write - read | 0;\n const count = Math.min(available, output[0].length);\n if (count <= 0) return 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#samples[channel];\n const dst = output[channel];\n for (let i = 0; i < count; i++) {\n dst[i] = src[slot(read + i | 0, this.capacity)];\n }\n }\n casAdvance(this.#control, READ, read + count | 0);\n return count;\n }\n /** Update the target latency in samples. */\n setLatency(samples) {\n Atomics.store(this.#control, LATENCY, samples);\n }\n /**\n * Flush buffered samples and re-stall, ready to anchor the next utterance (buffered mode).\n * Main thread only. The worklet reader sees STALLED and stops until the next insert.\n */\n reset() {\n this.#anchored = false;\n Atomics.store(this.#control, STALLED, 1);\n const write = Atomics.load(this.#control, WRITE);\n Atomics.store(this.#control, READ, write);\n }\n /**\n * Allocate a new ring with `newCapacity` samples and copy the unread window\n * [READ, WRITE) plus control state into it. Used when growing capacity so\n * we don't drop buffered audio. If `newCapacity` is smaller than the unread\n * span, the oldest samples are truncated.\n *\n * Main thread only. `resize()` reads from the source `SharedRingBuffer` and\n * writes into a freshly allocated buffer from `allocSharedRingBuffer`, so it\n * relies on the same invariant as `insert()`: no concurrent main-thread\n * writers. The AudioWorklet reader is tolerated via the CAS discipline used\n * by READ/WRITE elsewhere.\n */\n resize(newCapacity) {\n const init = allocSharedRingBuffer(this.channels, newCapacity, this.rate, this.buffered);\n const dst = new _SharedRingBuffer(init);\n dst.#anchored = this.#anchored;\n const read = Atomics.load(this.#control, READ);\n const write = Atomics.load(this.#control, WRITE);\n const latency = Atomics.load(this.#control, LATENCY);\n const stalled = Atomics.load(this.#control, STALLED);\n const available = write - read | 0;\n const copyCount = Math.max(0, Math.min(available, dst.capacity));\n const copyStart = write - copyCount | 0;\n for (let channel = 0; channel < this.channels; channel++) {\n const src = this.#samples[channel];\n const out = dst.#samples[channel];\n for (let i = 0; i < copyCount; i++) {\n const idx = copyStart + i | 0;\n out[slot(idx, dst.capacity)] = src[slot(idx, this.capacity)];\n }\n }\n Atomics.store(dst.#control, READ, copyStart);\n Atomics.store(dst.#control, WRITE, write);\n Atomics.store(dst.#control, LATENCY, latency);\n Atomics.store(dst.#control, STALLED, stalled);\n return dst;\n }\n /** Current playback timestamp derived from READ position. */\n get timestamp() {\n const read = Atomics.load(this.#control, READ);\n return time_exports.Micro.fromSecond(read / this.rate);\n }\n /** Whether the buffer is stalled (waiting to fill). */\n get stalled() {\n return Atomics.load(this.#control, STALLED) === 1;\n }\n /**\n * Number of buffered samples (WRITE - READ).\n *\n * Non-atomic: WRITE and READ are loaded separately, so a concurrent\n * writer/reader can make the two loads inconsistent. Intended for\n * tests and diagnostics, not control-flow decisions.\n */\n get length() {\n return Atomics.load(this.#control, WRITE) - Atomics.load(this.#control, READ) | 0;\n }\n};\n\n// src/audio/render-worklet.ts\nvar Render = class extends AudioWorkletProcessor {\n // Set after init, depending on which path the main thread chose.\n #backend;\n #underflow = 0;\n #stateCounter = 0;\n constructor() {\n super();\n this.port.onmessage = (event) => {\n const msg = event.data;\n if (msg.type === \"init-shared\") {\n console.log(\"[audio-worklet] init-shared: using SharedArrayBuffer path\");\n this.#backend = new SharedRingBuffer(msg);\n this.#underflow = 0;\n } else if (msg.type === \"init-post\") {\n console.log(\"[audio-worklet] init-post: using postMessage path\");\n this.#backend = new AudioRingBuffer(msg);\n this.#underflow = 0;\n } else if (msg.type === \"data\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.write(msg.timestamp, msg.data);\n } else if (msg.type === \"latency\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.resize(msg.latency);\n } else if (msg.type === \"reset\") {\n if (this.#backend instanceof AudioRingBuffer) this.#backend.reset();\n }\n };\n }\n process(_inputs, outputs, _parameters) {\n const output = outputs[0];\n const backend = this.#backend;\n const samplesRead = backend?.read(output) ?? 0;\n if (samplesRead < output[0].length) {\n this.#underflow += output[0].length - samplesRead;\n } else if (this.#underflow > 0 && backend) {\n console.debug(`audio underflow: ${Math.round(1e3 * this.#underflow / backend.rate)}ms`);\n this.#underflow = 0;\n }\n if (backend instanceof AudioRingBuffer) {\n this.#stateCounter++;\n if (this.#stateCounter >= 5) {\n this.#stateCounter = 0;\n const state = {\n type: \"state\",\n timestamp: backend.timestamp,\n stalled: backend.stalled\n };\n this.port.postMessage(state);\n }\n }\n return true;\n }\n};\nregisterProcessor(\"render\", Render);\n"], { type: "application/javascript" }), j = URL.createObjectURL(A);
263
264
  //#endregion
264
265
  //#region src/audio/unlock.ts
265
- function te(e, t) {
266
- let n = new r(t.state === "running");
266
+ function ee(e, t) {
267
+ let n = new i(t.state === "running");
267
268
  e.event(t, "statechange", () => n.set(t.state === "running")), e.run((e) => {
268
269
  if (e.get(n)) return;
269
270
  let r = () => {
@@ -274,72 +275,85 @@ function te(e, t) {
274
275
  }
275
276
  //#endregion
276
277
  //#region src/audio/decoder.ts
277
- var A = class {
278
+ var te = 150, ne = class {
278
279
  in;
279
280
  source;
280
281
  sync;
281
282
  #e = {
282
- context: new r(void 0),
283
- root: new r(void 0),
284
- sampleRate: new r(void 0),
285
- stats: new r(void 0),
286
- timestamp: new r(void 0),
287
- stalled: new r(!0),
288
- buffered: new r([])
283
+ context: new i(void 0),
284
+ root: new i(void 0),
285
+ sampleRate: new i(void 0),
286
+ stats: new i(void 0),
287
+ timestamp: new i(void 0),
288
+ stalled: new i(!0),
289
+ buffered: new i([])
289
290
  };
290
- out = a(this.#e);
291
- #t = new r([]);
291
+ out = o(this.#e);
292
+ #t = new i([]);
292
293
  #n;
293
- #r = new r(void 0);
294
+ #r = new i(void 0);
294
295
  #i = 0;
295
- #a = new r(t.Milli.zero);
296
- #o = new n();
296
+ #a = new i(n.Milli.zero);
297
+ #o;
298
+ #s = new r();
297
299
  constructor(e, t, n) {
298
- this.in = { enabled: i(n?.enabled ?? !1) }, this.source = e, this.sync = t, this.#o.run((e) => {
300
+ this.in = { enabled: a(n?.enabled ?? !1) }, this.source = e, this.sync = t, this.#s.run((e) => {
299
301
  this.#a.set(e.get(this.sync.out.maxBuffer));
300
- }), this.#o.run(this.#s.bind(this)), this.#o.run(this.#c.bind(this)), this.#o.run(this.#l.bind(this)), this.#o.run(this.#u.bind(this));
302
+ }), this.#s.run(this.#c.bind(this)), this.#s.run(this.#l.bind(this)), this.#s.run(this.#u.bind(this)), this.#s.run(this.#d.bind(this)), this.#s.run(this.#f.bind(this));
301
303
  }
302
- #s(e) {
303
- let n = e.get(this.source.out.config);
304
- if (!n) return;
305
- let r = e.get(this.#r) ?? n.sampleRate, i = n.numberOfChannels;
304
+ #c(e) {
305
+ let t = e.get(this.source.out.config);
306
+ if (!t) return;
307
+ let r = e.get(this.#r) ?? t.sampleRate, i = t.numberOfChannels;
306
308
  e.set(this.#e.sampleRate, r);
307
309
  let a = new AudioContext({
308
310
  latencyHint: "interactive",
309
311
  sampleRate: r
310
312
  });
311
313
  e.set(this.#e.context, a), e.cleanup(() => a.close()), e.spawn(async () => {
312
- if (!await Promise.race([a.audioWorklet.addModule(ee).then(() => !0), e.cancel])) return;
313
- let n = new AudioWorkletNode(a, "render", {
314
+ if (!await Promise.race([a.audioWorklet.addModule(j).then(() => !0), e.cancel])) return;
315
+ let t = new AudioWorkletNode(a, "render", {
314
316
  channelCount: i,
315
317
  channelCountMode: "explicit",
316
318
  outputChannelCount: [i]
317
319
  });
318
- e.cleanup(() => n.disconnect());
319
- let o = this.sync.out.buffer.peek(), s = Math.ceil(r * t.Second.fromMilli(o)), c = this.sync.out.buffered.peek(), l = E(n, i, r, s, c);
320
+ e.cleanup(() => t.disconnect());
321
+ let o = this.sync.out.buffer.peek(), s = Math.ceil(r * n.Second.fromMilli(o)), c = this.sync.out.buffered.peek(), l = D(t, i, r, s, c);
320
322
  this.#n = l, e.cleanup(() => {
321
323
  l.close(), this.#n = void 0;
322
324
  }), e.run((e) => {
323
- let n = t.Milli.fromMicro(e.get(l.timestamp));
324
- this.#e.timestamp.set(n), this.#h(n);
325
+ let t = n.Milli.fromMicro(e.get(l.timestamp));
326
+ this.#e.timestamp.set(t), this.#_(t);
325
327
  }), e.run((e) => {
326
328
  this.#e.stalled.set(e.get(l.stalled));
327
- }), e.set(this.#e.root, n);
329
+ }), e.set(this.#e.root, t);
328
330
  });
329
331
  }
330
- #c(e) {
332
+ #l(e) {
331
333
  if (!e.get(this.in.enabled)) return;
332
334
  let t = e.get(this.#e.context);
333
- t && te(e, t);
335
+ t && ee(e, t);
334
336
  }
335
- #l(e) {
337
+ #u(e) {
336
338
  if (!e.get(this.#e.root)) return;
337
- let n = this.#n;
338
- if (!n) return;
339
- let r = e.get(this.sync.out.buffer), i = Math.ceil(n.rate * t.Second.fromMilli(r));
340
- n.setLatency(i);
339
+ let t = this.#n;
340
+ if (!t) return;
341
+ let r = e.get(this.sync.out.buffer), i = Math.ceil(t.rate * n.Second.fromMilli(r));
342
+ t.setLatency(i);
341
343
  }
342
- #u(e) {
344
+ #d(t) {
345
+ let n = e(t.get(this.sync.in.latency)).min;
346
+ if (this.#o === void 0) {
347
+ this.#o = n;
348
+ return;
349
+ }
350
+ let r = this.#o;
351
+ t.timer(() => {
352
+ let e = (e) => e === "real-time" ? 0 : e;
353
+ e(n) > e(r) && this.reset(), this.#o = n;
354
+ }, te);
355
+ }
356
+ #f(e) {
343
357
  if (!e.get(this.in.enabled)) return;
344
358
  let t = e.get(this.source.in.broadcast);
345
359
  if (!t) return;
@@ -349,72 +363,72 @@ var A = class {
349
363
  if (!r) return;
350
364
  let i = t.relativeBroadcast(e, r.broadcast);
351
365
  if (!i) return;
352
- let a = i.track(n).subscribe({ priority: o.PRIORITY.audio });
353
- e.cleanup(() => a.close()), r.container.kind === "cmaf" ? this.#f(e, a, r) : this.#d(e, a, r);
366
+ let a = i.track(n).subscribe({ priority: s.PRIORITY.audio });
367
+ e.cleanup(() => a.close()), r.container.kind === "cmaf" ? this.#m(e, a, r) : this.#p(e, a, r);
354
368
  }
355
- #d(e, n, r) {
356
- let i = r.container.kind === "loc" ? new c.Loc.Format() : new c.Legacy.Format(), a = new c.Consumer(n, {
369
+ #p(e, t, r) {
370
+ let i = r.container.kind === "loc" ? new l.Loc.Format() : new l.Legacy.Format(), a = new l.Consumer(t, {
357
371
  format: i,
358
372
  latency: this.#a
359
373
  });
360
374
  e.cleanup(() => a.close()), e.run((e) => {
361
375
  let t = e.get(a.buffered), n = e.get(this.#t);
362
- this.#e.buffered.update(() => c.mergeBufferedRanges(t, n));
376
+ this.#e.buffered.update(() => l.mergeBufferedRanges(t, n));
363
377
  }), e.spawn(async () => {
364
- if (!await l.Libav.polyfill()) return;
365
- let n = 0, i = new AudioDecoder({
378
+ if (!await u.Libav.polyfill()) return;
379
+ let t = 0, i = new AudioDecoder({
366
380
  output: (e) => {
367
- if (n++, n <= 3) {
381
+ if (t++, t <= 3) {
368
382
  e.close();
369
383
  return;
370
384
  }
371
- this.#p(e);
385
+ this.#h(e);
372
386
  },
373
387
  error: (e) => console.error("audio decoder error", e)
374
388
  });
375
389
  e.cleanup(() => {
376
390
  i.state !== "closed" && i.close();
377
391
  });
378
- let o = r.codec === "opus" ? void 0 : r.description ? l.Hex.toBytes(r.description) : void 0;
392
+ let o = r.codec === "opus" ? void 0 : r.description ? u.Hex.toBytes(r.description) : void 0;
379
393
  for (i.configure({
380
394
  ...r,
381
395
  description: o
382
396
  });;) {
383
397
  let e = await a.next();
384
398
  if (!e) break;
385
- this.#g(e.discontinuity);
386
- let { frame: n } = e;
387
- if (!n) continue;
388
- let r = t.Milli.fromMicro(n.timestamp);
389
- this.sync.received(r, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + n.payload.byteLength })), await this.#n?.wait(n.timestamp);
399
+ this.#v(e.discontinuity);
400
+ let { frame: t } = e;
401
+ if (!t) continue;
402
+ let r = n.Milli.fromMicro(t.timestamp);
403
+ this.sync.received(r, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength })), await this.#n?.wait(t.timestamp);
390
404
  let o = new EncodedAudioChunk({
391
- type: n.keyframe ? "key" : "delta",
392
- data: n.payload,
393
- timestamp: n.timestamp
405
+ type: t.keyframe ? "key" : "delta",
406
+ data: t.payload,
407
+ timestamp: t.timestamp
394
408
  });
395
409
  if (i.state === "closed") break;
396
410
  i.decode(o);
397
411
  }
398
412
  });
399
413
  }
400
- #f(e, n, r) {
414
+ #m(e, t, r) {
401
415
  if (r.container.kind !== "cmaf") return;
402
- let i = f(r.container.init), a = c.Cmaf.decodeInitSegment(i), o = r.codec === "opus" ? void 0 : r.description ? l.Hex.toBytes(r.description) : a.description, s = new c.Consumer(n, {
403
- format: new c.Cmaf.Format(a),
416
+ let i = p(r.container.init), a = l.Cmaf.decodeInitSegment(i), o = r.codec === "opus" ? void 0 : r.description ? u.Hex.toBytes(r.description) : a.description, s = new l.Consumer(t, {
417
+ format: new l.Cmaf.Format(a),
404
418
  latency: this.#a
405
419
  });
406
420
  e.cleanup(() => s.close()), e.run((e) => {
407
421
  let t = e.get(s.buffered), n = e.get(this.#t);
408
- this.#e.buffered.update(() => c.mergeBufferedRanges(t, n));
422
+ this.#e.buffered.update(() => l.mergeBufferedRanges(t, n));
409
423
  }), e.spawn(async () => {
410
- if (!await l.Libav.polyfill()) return;
411
- let n = new AudioDecoder({
412
- output: (e) => this.#p(e),
424
+ if (!await u.Libav.polyfill()) return;
425
+ let t = new AudioDecoder({
426
+ output: (e) => this.#h(e),
413
427
  error: (e) => console.error("audio decoder error", e)
414
428
  });
415
429
  for (e.cleanup(() => {
416
- n.state !== "closed" && n.close();
417
- }), n.configure({
430
+ t.state !== "closed" && t.close();
431
+ }), t.configure({
418
432
  codec: r.codec,
419
433
  sampleRate: r.sampleRate,
420
434
  numberOfChannels: r.numberOfChannels,
@@ -422,12 +436,12 @@ var A = class {
422
436
  });;) {
423
437
  let e = await s.next();
424
438
  if (!e) break;
425
- this.#g(e.discontinuity);
439
+ this.#v(e.discontinuity);
426
440
  let { frame: r } = e;
427
441
  if (!r) continue;
428
- let i = t.Milli.fromMicro(r.timestamp);
429
- if (this.sync.received(i, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + r.payload.byteLength })), await this.#n?.wait(r.timestamp), n.state === "closed") break;
430
- n.decode(new EncodedAudioChunk({
442
+ let i = n.Milli.fromMicro(r.timestamp);
443
+ if (this.sync.received(i, "audio"), this.#e.stats.update((e) => ({ bytesReceived: (e?.bytesReceived ?? 0) + r.payload.byteLength })), await this.#n?.wait(r.timestamp), t.state === "closed") break;
444
+ t.decode(new EncodedAudioChunk({
431
445
  type: r.keyframe ? "key" : "delta",
432
446
  data: r.payload,
433
447
  timestamp: r.timestamp
@@ -435,8 +449,8 @@ var A = class {
435
449
  }
436
450
  });
437
451
  }
438
- #p(e) {
439
- let n = e.timestamp, r = t.Milli.fromMicro(n), i = this.#n;
452
+ #h(e) {
453
+ let t = e.timestamp, r = n.Milli.fromMicro(t), i = this.#n;
440
454
  if (!i) {
441
455
  e.close();
442
456
  return;
@@ -445,8 +459,8 @@ var A = class {
445
459
  this.#r.set(e.sampleRate), e.close();
446
460
  return;
447
461
  }
448
- let a = e.numberOfFrames / e.sampleRate * 1e6, o = t.Milli.fromMicro(a), s = t.Milli.add(r, o);
449
- this.#m(r, s);
462
+ let a = e.numberOfFrames / e.sampleRate * 1e6, o = n.Milli.fromMicro(a), s = n.Milli.add(r, o);
463
+ this.#g(r, s);
450
464
  let c = Math.min(e.numberOfChannels, i.channels), l = [];
451
465
  for (let t = 0; t < c; t++) {
452
466
  let n = new Float32Array(e.numberOfFrames);
@@ -455,53 +469,53 @@ var A = class {
455
469
  planeIndex: t
456
470
  }), l.push(n);
457
471
  }
458
- i.insert(n, l), e.close();
472
+ i.insert(t, l), e.close();
459
473
  }
460
- #m(e, n) {
461
- e > n || this.#t.mutate((r) => {
462
- for (let i of r) if (e <= i.end + 1 && n >= i.start) {
463
- i.start = t.Milli.min(i.start, e), i.end = t.Milli.max(i.end, n);
474
+ #g(e, t) {
475
+ e > t || this.#t.mutate((r) => {
476
+ for (let i of r) if (e <= i.end + 1 && t >= i.start) {
477
+ i.start = n.Milli.min(i.start, e), i.end = n.Milli.max(i.end, t);
464
478
  return;
465
479
  }
466
480
  r.push({
467
481
  start: e,
468
- end: n
482
+ end: t
469
483
  }), r.sort((e, t) => e.start - t.start);
470
484
  });
471
485
  }
472
- #h(e) {
473
- this.#t.mutate((n) => {
474
- for (; n.length > 0;) {
475
- if (n[0].end >= e) {
476
- n[0].start = t.Milli.max(n[0].start, e);
486
+ #_(e) {
487
+ this.#t.mutate((t) => {
488
+ for (; t.length > 0;) {
489
+ if (t[0].end >= e) {
490
+ t[0].start = n.Milli.max(t[0].start, e);
477
491
  break;
478
492
  }
479
- n.shift();
493
+ t.shift();
480
494
  }
481
495
  });
482
496
  }
483
497
  reset() {
484
498
  this.#n?.reset();
485
499
  }
486
- #g(e) {
500
+ #v(e) {
487
501
  e !== this.#i && (this.#i = e, this.#n?.reset(), this.sync.reset());
488
502
  }
489
503
  close() {
490
- this.#o.close();
504
+ this.#s.close();
491
505
  }
492
- static supported = j;
506
+ static supported = re;
493
507
  };
494
- async function j(e) {
495
- if (!o.containerSupported(e.container)) {
508
+ async function re(e) {
509
+ if (!s.containerSupported(e.container)) {
496
510
  let t = e.container.kind === "unknown" ? e.container.raw.kind : e.container.kind;
497
511
  return console.warn(`audio: ignoring rendition with unknown container: ${t}`), !1;
498
512
  }
499
- e.codec === "opus" && !l.Opus.supportsRate(e.sampleRate) && console.warn(`audio: opus advertised at ${e.sampleRate}Hz, which some browsers cannot decode`);
513
+ e.codec === "opus" && !u.Opus.supportsRate(e.sampleRate) && console.warn(`audio: opus advertised at ${e.sampleRate}Hz, which some browsers cannot decode`);
500
514
  let t;
501
515
  if (e.codec !== "opus") {
502
- if (e.description) t = l.Hex.toBytes(e.description);
516
+ if (e.description) t = u.Hex.toBytes(e.description);
503
517
  else if (e.container.kind === "cmaf") try {
504
- t = c.Cmaf.decodeInitSegment(f(e.container.init)).description;
518
+ t = l.Cmaf.decodeInitSegment(p(e.container.init)).description;
505
519
  } catch (t) {
506
520
  return console.warn(`audio: malformed CMAF init segment for codec ${e.codec}`, t), !1;
507
521
  }
@@ -516,15 +530,15 @@ async function j(e) {
516
530
  var M = .001, N = .2, P = class {
517
531
  source;
518
532
  in;
519
- #e = { enabled: new r(!1) };
520
- out = a(this.#e);
521
- #t = new n();
522
- #n = new r(void 0);
533
+ #e = { enabled: new i(!1) };
534
+ out = o(this.#e);
535
+ #t = new r();
536
+ #n = new i(void 0);
523
537
  constructor(e, t) {
524
538
  this.source = e, this.in = {
525
- volume: i(t?.volume ?? .5),
526
- muted: i(t?.muted ?? !1),
527
- paused: i(t?.paused ?? !1)
539
+ volume: a(t?.volume ?? .5),
540
+ muted: a(t?.muted ?? !1),
541
+ paused: a(t?.paused ?? !1)
528
542
  }, this.#t.run((e) => {
529
543
  let t = !e.get(this.in.paused) && !e.get(this.in.muted);
530
544
  this.#e.enabled.set(t);
@@ -549,19 +563,19 @@ var M = .001, N = .2, P = class {
549
563
  }, F = 128, I = class {
550
564
  in;
551
565
  #e = {
552
- catalog: new r(void 0),
553
- available: new r({}),
554
- track: new r(void 0),
555
- config: new r(void 0),
556
- jitter: new r(void 0)
566
+ catalog: new i(void 0),
567
+ available: new i({}),
568
+ track: new i(void 0),
569
+ config: new i(void 0),
570
+ jitter: new i(void 0)
557
571
  };
558
- out = a(this.#e);
559
- #t = new n();
572
+ out = o(this.#e);
573
+ #t = new r();
560
574
  constructor(e) {
561
575
  this.in = {
562
- broadcast: i(e?.broadcast),
563
- target: i(e?.target),
564
- supported: i(e?.supported)
576
+ broadcast: a(e?.broadcast),
577
+ target: a(e?.target),
578
+ supported: a(e?.supported)
565
579
  }, this.#t.run(this.#n.bind(this)), this.#t.run(this.#r.bind(this)), this.#t.run(this.#i.bind(this));
566
580
  }
567
581
  #n(e) {
@@ -579,17 +593,17 @@ var M = .001, N = .2, P = class {
579
593
  });
580
594
  }
581
595
  #i(e) {
582
- let n = e.get(this.#e.available);
583
- if (Object.keys(n).length === 0) return;
596
+ let t = e.get(this.#e.available);
597
+ if (Object.keys(t).length === 0) return;
584
598
  let r = e.get(this.in.target), i;
585
- if (r?.name && r.name in n) i = {
599
+ if (r?.name && r.name in t) i = {
586
600
  track: r.name,
587
- config: n[r.name]
601
+ config: t[r.name]
588
602
  };
589
- else if (i = this.#a(n), !i) return;
603
+ else if (i = this.#a(t), !i) return;
590
604
  e.set(this.#e.track, i.track), e.set(this.#e.config, i.config);
591
605
  let a = (i.config.jitter ?? L(i.config) ?? 0) + Math.ceil(F / i.config.sampleRate * 1e3);
592
- e.set(this.#e.jitter, t.Milli(a));
606
+ e.set(this.#e.jitter, n.Milli(a));
593
607
  }
594
608
  #a(e) {
595
609
  let t = Object.entries(e);
@@ -631,7 +645,7 @@ function B(e) {
631
645
  function V(e) {
632
646
  let t;
633
647
  try {
634
- t = e.initData ? f(e.initData) : void 0;
648
+ t = e.initData ? p(e.initData) : void 0;
635
649
  } catch {
636
650
  t = void 0;
637
651
  }
@@ -653,11 +667,11 @@ function H(e) {
653
667
  codec: e.codec,
654
668
  container: t,
655
669
  description: n,
656
- codedWidth: e.width == null ? void 0 : s(e.width),
657
- codedHeight: e.height == null ? void 0 : s(e.height),
670
+ codedWidth: e.width == null ? void 0 : c(e.width),
671
+ codedHeight: e.height == null ? void 0 : c(e.height),
658
672
  framerate: e.framerate,
659
- bitrate: e.bitrate == null ? void 0 : s(e.bitrate),
660
- jitter: e.jitter == null ? void 0 : s(e.jitter)
673
+ bitrate: e.bitrate == null ? void 0 : c(e.bitrate),
674
+ jitter: e.jitter == null ? void 0 : c(e.jitter)
661
675
  };
662
676
  }
663
677
  function U(e) {
@@ -671,10 +685,10 @@ function U(e) {
671
685
  codec: e.codec,
672
686
  container: n,
673
687
  description: r,
674
- sampleRate: s(e.samplerate ?? R),
675
- numberOfChannels: s(t),
676
- bitrate: e.bitrate == null ? void 0 : s(e.bitrate),
677
- jitter: e.jitter == null ? void 0 : s(e.jitter)
688
+ sampleRate: c(e.samplerate ?? R),
689
+ numberOfChannels: c(t),
690
+ bitrate: e.bitrate == null ? void 0 : c(e.bitrate),
691
+ jitter: e.jitter == null ? void 0 : c(e.jitter)
678
692
  };
679
693
  }
680
694
  function W(e) {
@@ -696,45 +710,45 @@ function K(e) {
696
710
  return e.discovery ? !1 : (G.has(e) || (G.add(e), console.warn("relay does not support broadcast discovery; ignoring reload signal.")), !0);
697
711
  }
698
712
  var q = [
699
- ...o.FORMATS,
713
+ ...s.FORMATS,
700
714
  "hangz",
701
715
  "manual"
702
716
  ];
703
- function J(e) {
717
+ function ie(e) {
704
718
  if (e !== null) return q.find((t) => t === e);
705
719
  }
706
- var Y = class {
720
+ var J = class {
707
721
  in;
708
722
  #e = {
709
- status: new r("offline"),
710
- active: new r(void 0),
711
- catalog: new r(void 0)
723
+ status: new i("offline"),
724
+ active: new i(void 0),
725
+ catalog: new i(void 0)
712
726
  };
713
- out = a(this.#e);
714
- #t = new r(void 0);
715
- #n = new r(!1);
716
- #r = new n();
717
- constructor(t) {
727
+ out = o(this.#e);
728
+ #t = new i(void 0);
729
+ #n = new i(!1);
730
+ #r = new r();
731
+ constructor(e) {
718
732
  this.in = {
719
- connection: i(t?.connection),
720
- name: i(t?.name ?? e.empty()),
721
- enabled: i(t?.enabled ?? !1),
722
- reload: i(t?.reload ?? !0),
723
- catalogFormat: i(t?.catalogFormat),
724
- catalog: i(t?.catalog)
733
+ connection: a(e?.connection),
734
+ name: a(e?.name ?? t.empty()),
735
+ enabled: a(e?.enabled ?? !1),
736
+ reload: a(e?.reload ?? !0),
737
+ catalogFormat: a(e?.catalogFormat),
738
+ catalog: a(e?.catalog)
725
739
  }, this.#r.run(this.#i.bind(this)), this.#r.run(this.#o.bind(this)), this.#r.run(this.#s.bind(this));
726
740
  }
727
- #i(t) {
728
- if (this.#t.set(void 0), !t.get(this.#n) || !t.get(this.in.reload)) return;
729
- let n = t.get(this.in.connection);
741
+ #i(e) {
742
+ if (this.#t.set(void 0), !e.get(this.#n) || !e.get(this.in.reload)) return;
743
+ let n = e.get(this.in.connection);
730
744
  if (!n || K(n)) return;
731
- let r = n.announced(e.empty());
732
- t.cleanup(() => r.close()), this.#t.set(/* @__PURE__ */ new Set()), t.spawn(async () => {
745
+ let r = n.announced(t.empty());
746
+ e.cleanup(() => r.close()), this.#t.set(/* @__PURE__ */ new Set()), e.spawn(async () => {
733
747
  for (;;) {
734
- let e = await Promise.race([t.cancel, r.next()]);
735
- if (!e) break;
736
- this.#t.mutate((t) => {
737
- t && (e.active ? t.add(e.path) : t.delete(e.path));
748
+ let t = await Promise.race([e.cancel, r.next()]);
749
+ if (!t) break;
750
+ this.#t.mutate((e) => {
751
+ e && (t.active ? e.add(t.path) : e.delete(t.path));
738
752
  });
739
753
  }
740
754
  });
@@ -747,26 +761,26 @@ var Y = class {
747
761
  let r = e.get(this.#t);
748
762
  return r ? r.has(t) : !1;
749
763
  }
750
- #o(t) {
751
- if (!t.get(this.in.enabled)) return;
752
- let n = t.get(this.in.connection);
764
+ #o(e) {
765
+ if (!e.get(this.in.enabled)) return;
766
+ let n = e.get(this.in.connection);
753
767
  if (!n) return;
754
- let r = t.get(this.in.name);
755
- if (!t.get(this.in.reload) || K(n)) {
756
- let e = n.consume(r);
757
- t.cleanup(() => e.close()), t.set(this.#e.active, e, void 0);
768
+ let r = e.get(this.in.name);
769
+ if (!e.get(this.in.reload) || K(n)) {
770
+ let t = n.consume(r);
771
+ e.cleanup(() => t.close()), e.set(this.#e.active, t, void 0);
758
772
  return;
759
773
  }
760
774
  let i = n.announced(r);
761
- t.cleanup(() => i.close());
775
+ e.cleanup(() => i.close());
762
776
  let a;
763
- t.cleanup(() => {
777
+ e.cleanup(() => {
764
778
  a?.close(), a = void 0, this.#e.active.set(void 0);
765
- }), t.spawn(async () => {
779
+ }), e.spawn(async () => {
766
780
  for (;;) {
767
- let o = await Promise.race([t.cancel, i.next()]);
781
+ let o = await Promise.race([e.cancel, i.next()]);
768
782
  if (!o) break;
769
- if (o.path === e.empty()) if (o.active) {
783
+ if (o.path === t.empty()) if (o.active) {
770
784
  if (a && a.closed.peek() === void 0) continue;
771
785
  a?.close(), a = n.consume(r), this.#e.active.set(a);
772
786
  } else a?.close(), a = void 0, this.#e.active.set(void 0);
@@ -775,7 +789,7 @@ var Y = class {
775
789
  }
776
790
  #s(e) {
777
791
  if (!e.get(this.in.enabled)) return;
778
- let t = e.get(this.in.catalogFormat), n = e.get(this.in.name), r = t ?? o.detectFormat(n) ?? o.DEFAULT_FORMAT;
792
+ let t = e.get(this.in.catalogFormat), n = e.get(this.in.name), r = t ?? s.detectFormat(n) ?? s.DEFAULT_FORMAT;
779
793
  if (r === "manual") {
780
794
  let t = e.get(this.in.catalog);
781
795
  e.set(this.#e.catalog, t, void 0), this.#e.status.set(t ? "live" : "loading");
@@ -784,17 +798,17 @@ var Y = class {
784
798
  let i = e.get(this.out.active);
785
799
  if (!i) return;
786
800
  this.#e.status.set("loading");
787
- let a = r === "hang" ? o.TRACK : r === "hangz" ? o.TRACK_COMPRESSED : "catalog", s = i.track(a).subscribe({ priority: o.PRIORITY.catalog });
788
- e.cleanup(() => s.close());
801
+ let a = r === "hang" ? s.TRACK : r === "hangz" ? s.TRACK_COMPRESSED : "catalog", o = i.track(a).subscribe({ priority: s.PRIORITY.catalog });
802
+ e.cleanup(() => o.close());
789
803
  let c;
790
804
  if (r === "hang" || r === "hangz") {
791
- let e = new u.Snapshot.Consumer(s, {
792
- schema: o.RootSchema,
805
+ let e = new d.Snapshot.Consumer(o, {
806
+ schema: s.RootSchema,
793
807
  compression: r === "hangz"
794
808
  });
795
809
  c = () => e.next();
796
810
  } else c = async () => {
797
- let e = await d.fetch(s);
811
+ let e = await f.fetch(o);
798
812
  return e ? W(e) : void 0;
799
813
  };
800
814
  e.spawn(async () => {
@@ -811,41 +825,123 @@ var Y = class {
811
825
  }
812
826
  });
813
827
  }
814
- relativeBroadcast(t, n) {
815
- if (!n) return t.get(this.out.active);
816
- let r = t.get(this.in.name), i = e.resolve(r, n);
817
- if (i === r || i === e.empty()) return t.get(this.out.active);
818
- if (!t.get(this.in.enabled)) return;
819
- let a = t.get(this.in.connection);
820
- if (!a || !this.#a(t, i)) return;
828
+ relativeBroadcast(e, n) {
829
+ if (!n) return e.get(this.out.active);
830
+ let r = e.get(this.in.name), i = t.resolve(r, n);
831
+ if (i === r || i === t.empty()) return e.get(this.out.active);
832
+ if (!e.get(this.in.enabled)) return;
833
+ let a = e.get(this.in.connection);
834
+ if (!a || !this.#a(e, i)) return;
821
835
  let o = a.consume(i);
822
- return t.cleanup(() => o.close()), o;
836
+ return e.cleanup(() => o.close()), o;
823
837
  }
824
838
  close() {
825
839
  this.#r.close();
826
840
  }
827
- }, X = t.Milli(500), Z = t.Milli(100), ne = class {
841
+ };
842
+ //#endregion
843
+ //#region src/video/presentation.ts
844
+ function Y(e = 0) {
845
+ let t = (e % 360 + 360) % 360;
846
+ return Math.round(t / 90) % 4 * 90;
847
+ }
848
+ function X(e, t = 0) {
849
+ let n = Y(t);
850
+ return n === 90 || n === 270 ? {
851
+ width: e.height,
852
+ height: e.width
853
+ } : {
854
+ width: e.width,
855
+ height: e.height
856
+ };
857
+ }
858
+ function Z(e) {
859
+ return Object.is(e, -0) ? 0 : e;
860
+ }
861
+ function ae(e, t) {
862
+ let [n, r, i, a, o, s] = e;
863
+ return [
864
+ Z(-n),
865
+ Z(r),
866
+ Z(-i),
867
+ Z(a),
868
+ Z(t - o),
869
+ Z(s)
870
+ ];
871
+ }
872
+ function oe(e, t) {
873
+ let n = Y(t?.rotation), r = X(e, n), i;
874
+ switch (n) {
875
+ case 90:
876
+ i = [
877
+ 0,
878
+ 1,
879
+ -1,
880
+ 0,
881
+ e.width,
882
+ 0
883
+ ];
884
+ break;
885
+ case 180:
886
+ i = [
887
+ -1,
888
+ 0,
889
+ 0,
890
+ -1,
891
+ e.width,
892
+ e.height
893
+ ];
894
+ break;
895
+ case 270:
896
+ i = [
897
+ 0,
898
+ -1,
899
+ 1,
900
+ 0,
901
+ 0,
902
+ e.height
903
+ ];
904
+ break;
905
+ default:
906
+ i = [
907
+ 1,
908
+ 0,
909
+ 0,
910
+ 1,
911
+ 0,
912
+ 0
913
+ ];
914
+ break;
915
+ }
916
+ return t?.flip && (i = ae(i, e.width)), {
917
+ matrix: i,
918
+ source: r
919
+ };
920
+ }
921
+ //#endregion
922
+ //#region src/video/decoder.ts
923
+ var se = n.Milli(500), ce = n.Milli(100), le = class {
828
924
  in;
829
925
  source;
830
926
  sync;
831
927
  #e = {
832
- frame: new r(void 0),
833
- timestamp: new r(void 0),
834
- display: new r(void 0),
835
- stalled: new r(!1),
836
- stats: new r(void 0),
837
- buffered: new r([])
928
+ frame: new i(void 0),
929
+ timestamp: new i(void 0),
930
+ display: new i(void 0),
931
+ stalled: new i(!1),
932
+ stats: new i(void 0),
933
+ buffered: new i([])
838
934
  };
839
- out = a(this.#e);
840
- #t = new r(void 0);
841
- #n = new n();
935
+ out = o(this.#e);
936
+ #t = new i(void 0);
937
+ #n = new r();
842
938
  #r() {
843
939
  this.#e.frame.update((e) => {
844
940
  e?.close();
845
941
  }), this.#e.timestamp.set(void 0);
846
942
  }
847
943
  constructor(e, t, n) {
848
- this.in = { enabled: i(n?.enabled ?? !1) }, this.source = e, this.sync = t, this.#n.run(this.#i.bind(this)), this.#n.run(this.#a.bind(this)), this.#n.run(this.#o.bind(this)), this.#n.run(this.#s.bind(this));
944
+ this.in = { enabled: a(n?.enabled ?? !1) }, this.source = e, this.sync = t, this.#n.run(this.#i.bind(this)), this.#n.run(this.#a.bind(this)), this.#n.run(this.#o.bind(this)), this.#n.run(this.#s.bind(this));
849
945
  }
850
946
  #i(e) {
851
947
  let t = e.getAll([
@@ -863,7 +959,7 @@ var Y = class {
863
959
  this.#t.set(void 0), this.#r(), this.#e.buffered.set([]);
864
960
  return;
865
961
  }
866
- let s = new re({
962
+ let s = new ue({
867
963
  sync: this.sync,
868
964
  broadcast: o,
869
965
  track: i,
@@ -875,7 +971,7 @@ var Y = class {
875
971
  let t = e.get(this.#t);
876
972
  if (t) {
877
973
  let n = e.get(s.timestamp), r = e.get(t.timestamp);
878
- if (!n || r && r > n + Z) return;
974
+ if (!n || r && r > n + ce) return;
879
975
  }
880
976
  this.#t.set(s), s = void 0, e.close();
881
977
  });
@@ -903,10 +999,10 @@ var Y = class {
903
999
  return;
904
1000
  }
905
1001
  let r = e.get(this.#e.frame);
906
- r && e.set(this.#e.display, {
1002
+ r && e.set(this.#e.display, X({
907
1003
  width: r.displayWidth,
908
1004
  height: r.displayHeight
909
- });
1005
+ }, t.rotation));
910
1006
  }
911
1007
  #s(e) {
912
1008
  if (e.get(this.in.enabled)) {
@@ -916,43 +1012,43 @@ var Y = class {
916
1012
  }
917
1013
  this.#e.stalled.set(!1), e.timer(() => {
918
1014
  this.#e.stalled.set(!0);
919
- }, X);
1015
+ }, se);
920
1016
  }
921
1017
  }
922
1018
  close() {
923
1019
  this.#r(), this.#n.close();
924
1020
  }
925
- static supported = ie;
926
- }, re = class {
1021
+ static supported = Q;
1022
+ }, ue = class {
927
1023
  sync;
928
1024
  broadcast;
929
1025
  track;
930
1026
  config;
931
1027
  stats;
932
- timestamp = new r(void 0);
933
- frame = new r(void 0);
934
- buffered = new r([]);
935
- #e = new r([]);
1028
+ timestamp = new i(void 0);
1029
+ frame = new i(void 0);
1030
+ buffered = new i([]);
1031
+ #e = new i([]);
936
1032
  #t = 0;
937
- #n = new n();
1033
+ #n = new r();
938
1034
  constructor(e) {
939
1035
  let { codedWidth: t, codedHeight: n, ...r } = e.config;
940
1036
  this.sync = e.sync, this.broadcast = e.broadcast, this.track = e.track, this.config = r, this.stats = e.stats, this.#n.run(this.#r.bind(this));
941
1037
  }
942
1038
  #r(e) {
943
- let n = this.broadcast.track(this.track).subscribe({ priority: o.PRIORITY.video });
944
- e.cleanup(() => n.close());
1039
+ let t = this.broadcast.track(this.track).subscribe({ priority: s.PRIORITY.video });
1040
+ e.cleanup(() => t.close());
945
1041
  let r = new VideoDecoder({
946
- output: async (n) => {
1042
+ output: async (t) => {
947
1043
  try {
948
- let r = this.#t, i = t.Milli.fromMicro(n.timestamp);
1044
+ let r = this.#t, i = n.Milli.fromMicro(t.timestamp);
949
1045
  if (i < (this.timestamp.peek() ?? 0)) return;
950
- this.frame.peek() === void 0 && this.frame.set(n.clone());
1046
+ this.frame.peek() === void 0 && this.frame.set(t.clone());
951
1047
  let a = this.sync.wait(i).then(() => !0);
952
1048
  if (!await Promise.race([a, e.cancel]) || r !== this.#t || i < (this.timestamp.peek() ?? 0)) return;
953
- this.timestamp.set(i), this.#c(i), this.frame.update((e) => (e?.close(), n.clone()));
1049
+ this.timestamp.set(i), this.#c(i), this.frame.update((e) => (e?.close(), t.clone()));
954
1050
  } finally {
955
- n.close();
1051
+ t.close();
956
1052
  }
957
1053
  },
958
1054
  error: (t) => {
@@ -961,19 +1057,19 @@ var Y = class {
961
1057
  });
962
1058
  e.cleanup(() => {
963
1059
  r.state !== "closed" && r.close();
964
- }), this.config.container.kind === "cmaf" ? this.#a(e, n, r) : this.#i(e, n, r);
1060
+ }), this.config.container.kind === "cmaf" ? this.#a(e, t, r) : this.#i(e, t, r);
965
1061
  }
966
- #i(e, n, r) {
967
- let i = this.config.container.kind === "loc" ? new c.Loc.Format() : new c.Legacy.Format(), a = new c.Consumer(n, {
1062
+ #i(e, t, r) {
1063
+ let i = this.config.container.kind === "loc" ? new l.Loc.Format() : new l.Legacy.Format(), a = new l.Consumer(t, {
968
1064
  format: i,
969
1065
  latency: this.sync.out.buffer
970
1066
  });
971
1067
  e.cleanup(() => a.close()), e.run((e) => {
972
1068
  let t = e.get(a.buffered), n = e.get(this.#e);
973
- this.buffered.update(() => c.mergeBufferedRanges(t, n));
1069
+ this.buffered.update(() => l.mergeBufferedRanges(t, n));
974
1070
  }), r.configure({
975
1071
  ...this.config,
976
- description: this.config.description ? l.Hex.toBytes(this.config.description) : void 0,
1072
+ description: this.config.description ? u.Hex.toBytes(this.config.description) : void 0,
977
1073
  optimizeForLatency: this.config.optimizeForLatency ?? !0,
978
1074
  flip: !1
979
1075
  });
@@ -983,45 +1079,45 @@ var Y = class {
983
1079
  let e = await a.next();
984
1080
  if (!e) break;
985
1081
  this.#o(e.discontinuity) && (o = void 0);
986
- let { frame: n, group: i } = e;
987
- if (!n) {
1082
+ let { frame: t, group: i } = e;
1083
+ if (!t) {
988
1084
  o && (o.final = !0);
989
1085
  continue;
990
1086
  }
991
- let s = t.Milli.fromMicro(n.timestamp);
1087
+ let s = n.Milli.fromMicro(t.timestamp);
992
1088
  this.sync.received(s, "video");
993
1089
  let c = new EncodedVideoChunk({
994
- type: n.keyframe ? "key" : "delta",
995
- data: n.payload,
996
- timestamp: n.timestamp
1090
+ type: t.keyframe ? "key" : "delta",
1091
+ data: t.payload,
1092
+ timestamp: t.timestamp
997
1093
  });
998
1094
  this.stats.update((e) => ({
999
1095
  frameCount: (e?.frameCount ?? 0) + 1,
1000
- bytesReceived: (e?.bytesReceived ?? 0) + n.payload.byteLength
1096
+ bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength
1001
1097
  }));
1002
1098
  let l = o;
1003
1099
  if (l && (l.group === i || l.final && l.group + 1 === i)) {
1004
- let e = t.Milli.fromMicro(l.timestamp), r = t.Milli.fromMicro(n.timestamp);
1100
+ let e = n.Milli.fromMicro(l.timestamp), r = n.Milli.fromMicro(t.timestamp);
1005
1101
  this.#s(e, r);
1006
1102
  }
1007
1103
  o = {
1008
- timestamp: n.timestamp,
1104
+ timestamp: t.timestamp,
1009
1105
  group: i,
1010
1106
  final: !1
1011
1107
  }, r.decode(c);
1012
1108
  }
1013
1109
  });
1014
1110
  }
1015
- #a(e, n, r) {
1111
+ #a(e, t, r) {
1016
1112
  let i = this.config.container;
1017
1113
  if (i.kind !== "cmaf") return;
1018
- let a = f(i.init), o = c.Cmaf.decodeInitSegment(a), s = this.config.description ? l.Hex.toBytes(this.config.description) : o.description, u = new c.Consumer(n, {
1019
- format: new c.Cmaf.Format(o),
1114
+ let a = p(i.init), o = l.Cmaf.decodeInitSegment(a), s = this.config.description ? u.Hex.toBytes(this.config.description) : o.description, c = new l.Consumer(t, {
1115
+ format: new l.Cmaf.Format(o),
1020
1116
  latency: this.sync.out.buffer
1021
1117
  });
1022
- e.cleanup(() => u.close()), e.run((e) => {
1023
- let t = e.get(u.buffered), n = e.get(this.#e);
1024
- this.buffered.update(() => c.mergeBufferedRanges(t, n));
1118
+ e.cleanup(() => c.close()), e.run((e) => {
1119
+ let t = e.get(c.buffered), n = e.get(this.#e);
1120
+ this.buffered.update(() => l.mergeBufferedRanges(t, n));
1025
1121
  }), r.configure({
1026
1122
  codec: this.config.codec,
1027
1123
  description: s,
@@ -1031,33 +1127,33 @@ var Y = class {
1031
1127
  let d;
1032
1128
  e.spawn(async () => {
1033
1129
  for (;;) {
1034
- let e = await u.next();
1130
+ let e = await c.next();
1035
1131
  if (!e) break;
1036
1132
  this.#o(e.discontinuity) && (d = void 0);
1037
- let { frame: n, group: i } = e;
1038
- if (!n) {
1133
+ let { frame: t, group: i } = e;
1134
+ if (!t) {
1039
1135
  d && (d.final = !0);
1040
1136
  continue;
1041
1137
  }
1042
- let a = t.Milli.fromMicro(n.timestamp);
1138
+ let a = n.Milli.fromMicro(t.timestamp);
1043
1139
  this.sync.received(a, "video"), this.stats.update((e) => ({
1044
1140
  frameCount: (e?.frameCount ?? 0) + 1,
1045
- bytesReceived: (e?.bytesReceived ?? 0) + n.payload.byteLength
1141
+ bytesReceived: (e?.bytesReceived ?? 0) + t.payload.byteLength
1046
1142
  }));
1047
1143
  let o = d;
1048
1144
  if (o && (o.group === i || o.final && o.group + 1 === i)) {
1049
- let e = t.Milli.fromMicro(o.timestamp), r = t.Milli.fromMicro(n.timestamp);
1145
+ let e = n.Milli.fromMicro(o.timestamp), r = n.Milli.fromMicro(t.timestamp);
1050
1146
  this.#s(e, r);
1051
1147
  }
1052
1148
  if (d = {
1053
- timestamp: n.timestamp,
1149
+ timestamp: t.timestamp,
1054
1150
  group: i,
1055
1151
  final: !1
1056
1152
  }, r.state === "closed") break;
1057
1153
  r.decode(new EncodedVideoChunk({
1058
- type: n.keyframe ? "key" : "delta",
1059
- data: n.payload,
1060
- timestamp: n.timestamp
1154
+ type: t.keyframe ? "key" : "delta",
1155
+ data: t.payload,
1156
+ timestamp: t.timestamp
1061
1157
  }));
1062
1158
  }
1063
1159
  });
@@ -1065,26 +1161,26 @@ var Y = class {
1065
1161
  #o(e) {
1066
1162
  return e === this.#t ? !1 : (this.#t = e, this.timestamp.set(void 0), this.#e.set([]), this.sync.reset(), !0);
1067
1163
  }
1068
- #s(e, n) {
1069
- e > n || this.#e.mutate((r) => {
1070
- for (let i of r) if (i.start <= n && i.end >= e) {
1071
- i.start = t.Milli.min(i.start, e), i.end = t.Milli.max(i.end, n);
1164
+ #s(e, t) {
1165
+ e > t || this.#e.mutate((r) => {
1166
+ for (let i of r) if (i.start <= t && i.end >= e) {
1167
+ i.start = n.Milli.min(i.start, e), i.end = n.Milli.max(i.end, t);
1072
1168
  return;
1073
1169
  }
1074
1170
  r.push({
1075
1171
  start: e,
1076
- end: n
1172
+ end: t
1077
1173
  }), r.sort((e, t) => e.start - t.start);
1078
1174
  });
1079
1175
  }
1080
1176
  #c(e) {
1081
- this.#e.mutate((n) => {
1082
- for (; n.length > 0;) {
1083
- if (n[0].end >= e) {
1084
- n[0].start = t.Milli.max(n[0].start, e);
1177
+ this.#e.mutate((t) => {
1178
+ for (; t.length > 0;) {
1179
+ if (t[0].end >= e) {
1180
+ t[0].start = n.Milli.max(t[0].start, e);
1085
1181
  break;
1086
1182
  }
1087
- n.shift();
1183
+ t.shift();
1088
1184
  }
1089
1185
  });
1090
1186
  }
@@ -1094,15 +1190,15 @@ var Y = class {
1094
1190
  });
1095
1191
  }
1096
1192
  };
1097
- async function ie(e) {
1098
- if (!o.containerSupported(e.container)) {
1193
+ async function Q(e) {
1194
+ if (!s.containerSupported(e.container)) {
1099
1195
  let t = e.container.kind === "unknown" ? e.container.raw.kind : e.container.kind;
1100
1196
  return console.warn(`video: ignoring rendition with unknown container: ${t}`), !1;
1101
1197
  }
1102
1198
  let t;
1103
- if (e.description) t = l.Hex.toBytes(e.description);
1199
+ if (e.description) t = u.Hex.toBytes(e.description);
1104
1200
  else if (e.container.kind === "cmaf") try {
1105
- t = c.Cmaf.decodeInitSegment(f(e.container.init)).description;
1201
+ t = l.Cmaf.decodeInitSegment(p(e.container.init)).description;
1106
1202
  } catch (t) {
1107
1203
  return console.warn(`video: malformed CMAF init segment for codec ${e.codec}`, t), !1;
1108
1204
  }
@@ -1124,21 +1220,21 @@ async function ie(e) {
1124
1220
  }
1125
1221
  //#endregion
1126
1222
  //#region src/video/renderer.ts
1127
- var Q = .01, ae = class {
1223
+ var $ = .01, de = class {
1128
1224
  decoder;
1129
1225
  in;
1130
1226
  #e = {
1131
- frame: new r(void 0),
1132
- timestamp: new r(void 0),
1133
- visible: new r(!1)
1227
+ frame: new i(void 0),
1228
+ timestamp: new i(void 0),
1229
+ visible: new i(!1)
1134
1230
  };
1135
- out = a(this.#e);
1136
- #t = new r(void 0);
1137
- #n = new n();
1231
+ out = o(this.#e);
1232
+ #t = new i(void 0);
1233
+ #n = new r();
1138
1234
  constructor(e, t) {
1139
1235
  this.decoder = e, this.in = {
1140
- canvas: i(t?.canvas),
1141
- visible: i(t?.visible ?? "20%")
1236
+ canvas: a(t?.canvas),
1237
+ visible: a(t?.visible ?? "20%")
1142
1238
  }, this.#n.run((e) => {
1143
1239
  let t = e.get(this.in.canvas);
1144
1240
  this.#t.set(t?.getContext("2d") ?? void 0);
@@ -1172,32 +1268,37 @@ var Q = .01, ae = class {
1172
1268
  }, o;
1173
1269
  try {
1174
1270
  o = new IntersectionObserver(a, {
1175
- threshold: Q,
1271
+ threshold: $,
1176
1272
  rootMargin: t
1177
1273
  });
1178
1274
  } catch {
1179
- console.warn(`moq-watch: invalid visible margin "${t}", using "0px"`), o = new IntersectionObserver(a, { threshold: Q });
1275
+ console.warn(`moq-watch: invalid visible margin "${t}", using "0px"`), o = new IntersectionObserver(a, { threshold: $ });
1180
1276
  }
1181
1277
  i(), e.event(document, "visibilitychange", i), o.observe(n), e.cleanup(() => o.disconnect()), e.cleanup(() => this.#e.visible.set(!1));
1182
1278
  }
1183
1279
  #a(e) {
1184
- let n = e.get(this.#t);
1185
- if (!n) return;
1186
- let r = e.get(this.decoder.out.frame), i = requestAnimationFrame(() => {
1187
- this.#o(n, r), r ? (this.#e.frame.update((e) => (e?.close(), r.clone())), this.#e.timestamp.set(t.Milli.fromMicro(r.timestamp))) : (this.#e.frame.update((e) => {
1280
+ let t = e.get(this.#t);
1281
+ if (!t) return;
1282
+ let r = e.get(this.decoder.out.frame), i = e.get(this.decoder.source.out.catalog), a = requestAnimationFrame(() => {
1283
+ this.#o(t, r, i), r ? (this.#e.frame.update((e) => (e?.close(), r.clone())), this.#e.timestamp.set(n.Milli.fromMicro(r.timestamp))) : (this.#e.frame.update((e) => {
1188
1284
  e?.close();
1189
- }), this.#e.timestamp.set(void 0)), i = void 0;
1285
+ }), this.#e.timestamp.set(void 0)), a = void 0;
1190
1286
  });
1191
1287
  e.cleanup(() => {
1192
- i && cancelAnimationFrame(i);
1288
+ a && cancelAnimationFrame(a);
1193
1289
  });
1194
1290
  }
1195
- #o(e, t) {
1291
+ #o(e, t, n) {
1196
1292
  if (!t) {
1197
1293
  e.fillStyle = "#000", e.fillRect(0, 0, e.canvas.width, e.canvas.height);
1198
1294
  return;
1199
1295
  }
1200
- e.save(), e.fillStyle = "#000", e.fillRect(0, 0, e.canvas.width, e.canvas.height), this.decoder.source.out.catalog.peek()?.flip && (e.scale(-1, 1), e.translate(-e.canvas.width, 0)), e.drawImage(t, 0, 0, e.canvas.width, e.canvas.height), e.restore();
1296
+ if (e.save(), e.fillStyle = "#000", e.fillRect(0, 0, e.canvas.width, e.canvas.height), !n?.rotation) n?.flip && (e.scale(-1, 1), e.translate(-e.canvas.width, 0)), e.drawImage(t, 0, 0, e.canvas.width, e.canvas.height);
1297
+ else {
1298
+ let r = oe(e.canvas, n);
1299
+ e.setTransform(...r.matrix), e.drawImage(t, 0, 0, r.source.width, r.source.height);
1300
+ }
1301
+ e.restore();
1201
1302
  }
1202
1303
  close() {
1203
1304
  this.#e.frame.update((e) => {
@@ -1207,7 +1308,7 @@ var Q = .01, ae = class {
1207
1308
  };
1208
1309
  //#endregion
1209
1310
  //#region src/video/source.ts
1210
- function oe(e) {
1311
+ function fe(e) {
1211
1312
  return (t) => {
1212
1313
  let n = [], r = [];
1213
1314
  for (let [i, a] of t) if (a.codedWidth && a.codedHeight) {
@@ -1223,7 +1324,7 @@ function oe(e) {
1223
1324
  return n.sort((e, t) => t.size - e.size), n.length > 0 ? n.map((e) => e.name) : r.length > 0 ? (r.sort((e, t) => e.size - t.size), [r[0].name]) : t.map(([e]) => e);
1224
1325
  };
1225
1326
  }
1226
- function $(e, t) {
1327
+ function pe(e, t) {
1227
1328
  return (n) => {
1228
1329
  let r = [], i = [];
1229
1330
  for (let [a, o] of n) {
@@ -1240,7 +1341,7 @@ function $(e, t) {
1240
1341
  return r.sort((e, t) => t.size - e.size), r.length > 0 ? r.map((e) => e.name) : i.length > 0 ? (i.sort((e, t) => e.size - t.size), [i[0].name]) : n.map(([e]) => e);
1241
1342
  };
1242
1343
  }
1243
- function se(e) {
1344
+ function me(e) {
1244
1345
  return (t) => {
1245
1346
  let n = [], r = [];
1246
1347
  for (let [i, a] of t) a.bitrate != null && a.bitrate <= e ? n.push({
@@ -1253,7 +1354,7 @@ function se(e) {
1253
1354
  return n.sort((e, t) => t.bitrate - e.bitrate), n.length > 0 ? n.map((e) => e.name) : r.length > 0 ? (r.sort((e, t) => e.bitrate - t.bitrate), [r[0].name]) : t.map(([e]) => e);
1254
1355
  };
1255
1356
  }
1256
- function ce(e) {
1357
+ function he(e) {
1257
1358
  let t = e[0];
1258
1359
  for (let n of e) {
1259
1360
  let [, e] = n, [, r] = t, i = (e.codedWidth ?? 0) * (e.codedHeight ?? 0), a = (r.codedWidth ?? 0) * (r.codedHeight ?? 0);
@@ -1265,23 +1366,23 @@ function ce(e) {
1265
1366
  }
1266
1367
  return t[0];
1267
1368
  }
1268
- var le = class {
1369
+ var ge = class {
1269
1370
  in;
1270
1371
  #e = {
1271
- catalog: new r(void 0),
1272
- available: new r({}),
1273
- error: new r(void 0),
1274
- track: new r(void 0),
1275
- config: new r(void 0),
1276
- jitter: new r(void 0)
1372
+ catalog: new i(void 0),
1373
+ available: new i({}),
1374
+ error: new i(void 0),
1375
+ track: new i(void 0),
1376
+ config: new i(void 0),
1377
+ jitter: new i(void 0)
1277
1378
  };
1278
- out = a(this.#e);
1279
- #t = new n();
1379
+ out = o(this.#e);
1380
+ #t = new r();
1280
1381
  constructor(e) {
1281
1382
  this.in = {
1282
- broadcast: i(e?.broadcast),
1283
- target: i(e?.target),
1284
- supported: i(e?.supported)
1383
+ broadcast: a(e?.broadcast),
1384
+ target: a(e?.target),
1385
+ supported: a(e?.supported)
1285
1386
  }, this.#t.run(this.#n.bind(this)), this.#t.run(this.#r.bind(this)), this.#t.run(this.#i.bind(this));
1286
1387
  }
1287
1388
  #n(e) {
@@ -1313,12 +1414,12 @@ var le = class {
1313
1414
  });
1314
1415
  }
1315
1416
  #i(e) {
1316
- let n = e.get(this.#e.available);
1317
- if (Object.keys(n).length === 0) return;
1417
+ let t = e.get(this.#e.available);
1418
+ if (Object.keys(t).length === 0) return;
1318
1419
  let r = e.get(this.in.target);
1319
- if (r?.name && r.name in n) {
1320
- let i = n[r.name];
1321
- e.set(this.#e.track, r.name), e.set(this.#e.config, i), e.set(this.#e.jitter, i.jitter === void 0 ? void 0 : t.Milli(i.jitter));
1420
+ if (r?.name && r.name in t) {
1421
+ let i = t[r.name];
1422
+ e.set(this.#e.track, r.name), e.set(this.#e.config, i), e.set(this.#e.jitter, i.jitter === void 0 ? void 0 : n.Milli(i.jitter));
1322
1423
  return;
1323
1424
  }
1324
1425
  let i = r;
@@ -1332,19 +1433,19 @@ var le = class {
1332
1433
  };
1333
1434
  }
1334
1435
  }
1335
- let a = this.#a(n, i);
1436
+ let a = this.#a(t, i);
1336
1437
  if (!a) return;
1337
- let o = n[a];
1438
+ let o = t[a];
1338
1439
  e.set(this.#e.track, a), e.set(this.#e.config, o);
1339
1440
  let s = o.jitter ?? (o.framerate ? Math.ceil(1e3 / o.framerate) : void 0);
1340
- e.set(this.#e.jitter, s === void 0 ? void 0 : t.Milli(s));
1441
+ e.set(this.#e.jitter, s === void 0 ? void 0 : n.Milli(s));
1341
1442
  }
1342
1443
  #a(e, t) {
1343
1444
  let n = Object.entries(e);
1344
1445
  if (n.length === 0) return;
1345
1446
  if (n.length === 1) return n[0][0];
1346
1447
  let r = [];
1347
- if (t?.pixels != null && r.push(oe(t.pixels)), (t?.width != null || t?.height != null) && r.push($(t.width, t.height)), t?.bitrate != null && r.push(se(t.bitrate)), r.length === 0) return ce(n);
1448
+ if (t?.pixels != null && r.push(fe(t.pixels)), (t?.width != null || t?.height != null) && r.push(pe(t.width, t.height)), t?.bitrate != null && r.push(me(t.bitrate)), r.length === 0) return he(n);
1348
1449
  let i = r.map((e) => e(n)), a = i.map((e) => new Set(e));
1349
1450
  for (let e of i[0]) if (a.every((t) => t.has(e))) return e;
1350
1451
  console.warn("conflicting rendition filters, no rendition satisfies all criteria");
@@ -1354,6 +1455,6 @@ var le = class {
1354
1455
  }
1355
1456
  };
1356
1457
  //#endregion
1357
- export { q as a, P as c, Y as i, A as l, ae as n, J as o, ne as r, I as s, le as t };
1458
+ export { q as a, P as c, J as i, ne as l, de as n, ie as o, le as r, I as s, ge as t };
1358
1459
 
1359
- //# sourceMappingURL=source-CWtgjSC_.js.map
1460
+ //# sourceMappingURL=source-CPHBHrLc.js.map