@blockcast/mmt-render 0.1.0-main.dd5ce397d768 → 0.1.0-main.e6500013301e

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,30 +1,12 @@
1
- var __typeError = (msg) => {
2
- throw TypeError(msg);
3
- };
4
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
7
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
- var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
9
- var __privateWrapper = (obj, member, setter, getter) => ({
10
- set _(value) {
11
- __privateSet(obj, member, value, setter);
12
- },
13
- get _() {
14
- return __privateGet(obj, member, getter);
15
- }
16
- });
17
-
18
1
  // src/audio/audio-render-pipeline.ts
19
2
  import { MmtpDecodePipeline } from "@blockcast/mmt-container/mmtp-decode-pipeline";
20
3
 
21
4
  // src/pacing/frame-pacer.ts
22
- var _frameCount, _anchorWallMs, _anchored;
23
5
  var FrameCountPacer = class {
6
+ #frameCount = 0;
7
+ #anchorWallMs = 0;
8
+ #anchored = false;
24
9
  constructor(opts) {
25
- __privateAdd(this, _frameCount, 0);
26
- __privateAdd(this, _anchorWallMs, 0);
27
- __privateAdd(this, _anchored, false);
28
10
  if (!(opts.frameDurationMs > 0)) {
29
11
  throw new Error("frameDurationMs must be > 0");
30
12
  }
@@ -34,11 +16,11 @@ var FrameCountPacer = class {
34
16
  }
35
17
  /** Call on every emitted decoded frame (AU or picture). Anchors on first call. */
36
18
  notifyFrame() {
37
- if (!__privateGet(this, _anchored)) {
38
- __privateSet(this, _anchorWallMs, now());
39
- __privateSet(this, _anchored, true);
19
+ if (!this.#anchored) {
20
+ this.#anchorWallMs = now();
21
+ this.#anchored = true;
40
22
  }
41
- __privateWrapper(this, _frameCount)._++;
23
+ this.#frameCount++;
42
24
  }
43
25
  /**
44
26
  * Compute sleep ms before reading the next MoQ object.
@@ -46,41 +28,62 @@ var FrameCountPacer = class {
46
28
  * - pacing is disabled (NullBlockMapper → threshold=0)
47
29
  * - the anchor is not yet set
48
30
  * - still in warmup
31
+ * - the caller reports a standing backlog (see `observedDelayMs`)
49
32
  * - decoder is not ahead of wall clock by more than threshold
50
33
  * Otherwise returns aheadMs - thresholdMs/2 (leaves half the threshold as headroom).
34
+ *
35
+ * `observedDelayMs` is how far this frame is behind the producer's own clock,
36
+ * measured by the caller against a producer-supplied sending instant (for
37
+ * MMTP, the header send-wall timestamp). It is optional because the anchored
38
+ * rate below is blind to it: `#anchorWallMs` is the wall time of the FIRST
39
+ * frame read, so `aheadMs` measures consumption against the join instant and
40
+ * not against the producer. Once `aheadMs` reaches the threshold the loop
41
+ * consumes at exactly the source rate, and recovering latency present at join
42
+ * requires consuming FASTER than the source rate. So without this argument a
43
+ * consumer that joined a live stream mid-block keeps that join latency for the
44
+ * life of the subscription.
45
+ *
46
+ * A caller that can measure the real distance from the producer passes it and
47
+ * gets a drain: while the backlog exceeds the threshold there is nothing to
48
+ * pace against, so return 0 and let the transport set the rate. At the live
49
+ * edge the anchored-rate behavior below applies unchanged.
50
+ *
51
+ * Callers with no producer clock omit it and keep the pure ATSC3-style
52
+ * anchored pacing (see the class doc), where a first-frame anchor is correct
53
+ * because a broadcast push has no live edge to catch up to.
51
54
  */
52
- computeSleepMs() {
55
+ computeSleepMs(observedDelayMs) {
53
56
  if (this.thresholdMs <= 0) return 0;
54
- if (!__privateGet(this, _anchored)) return 0;
55
- if (__privateGet(this, _frameCount) <= this.warmupFrames) return 0;
56
- const mediaMs = __privateGet(this, _frameCount) * this.frameDurationMs;
57
- const wallMs = now() - __privateGet(this, _anchorWallMs);
57
+ if (!this.#anchored) return 0;
58
+ if (this.#frameCount <= this.warmupFrames) return 0;
59
+ if (observedDelayMs !== void 0 && Number.isFinite(observedDelayMs) && observedDelayMs > this.thresholdMs) {
60
+ return 0;
61
+ }
62
+ const mediaMs = this.#frameCount * this.frameDurationMs;
63
+ const wallMs = now() - this.#anchorWallMs;
58
64
  const aheadMs = mediaMs - wallMs;
59
65
  if (aheadMs <= this.thresholdMs) return 0;
60
66
  return aheadMs - this.thresholdMs / 2;
61
67
  }
62
68
  /** Reset anchor + counter. Call on source switch (MoQ ↔ multicast). */
63
69
  reset() {
64
- __privateSet(this, _frameCount, 0);
65
- __privateSet(this, _anchorWallMs, 0);
66
- __privateSet(this, _anchored, false);
70
+ this.#frameCount = 0;
71
+ this.#anchorWallMs = 0;
72
+ this.#anchored = false;
67
73
  }
68
74
  get snapshot() {
69
- const mediaMs = __privateGet(this, _frameCount) * this.frameDurationMs;
70
- const wallMs = __privateGet(this, _anchored) ? now() - __privateGet(this, _anchorWallMs) : 0;
75
+ const mediaMs = this.#frameCount * this.frameDurationMs;
76
+ const wallMs = this.#anchored ? now() - this.#anchorWallMs : 0;
71
77
  return {
72
- frameCount: __privateGet(this, _frameCount),
78
+ frameCount: this.#frameCount,
73
79
  mediaMs,
74
80
  wallMs,
75
81
  aheadMs: mediaMs - wallMs,
76
82
  thresholdMs: this.thresholdMs,
77
- anchored: __privateGet(this, _anchored)
83
+ anchored: this.#anchored
78
84
  };
79
85
  }
80
86
  };
81
- _frameCount = new WeakMap();
82
- _anchorWallMs = new WeakMap();
83
- _anchored = new WeakMap();
84
87
  function now() {
85
88
  if (typeof performance !== "undefined" && typeof performance.now === "function") {
86
89
  return performance.now();
@@ -111,260 +114,226 @@ function workletModuleUrl() {
111
114
  var WORKLET_PROCESSOR_NAME = "mmt-render";
112
115
 
113
116
  // src/audio/audio-render-pipeline.ts
114
- var _context, _pacer, _mapper, _codec, _packetId, _sampleRate, _channels, _description, _latencyMs, _startupFrames, _startupThresholdFrames, _capacityFrames, _diag, _warmupFrames, _onState, _onDiag, _onError, _reassemblyPolicy, _decoder, _pipeline, _worklet, _fecClient, _closed, _readyPromise, _workletGeneration, _startupReleased, _AudioRenderPipeline_instances, initialize_fn, onDecoded_fn;
115
117
  var AudioRenderPipeline = class {
118
+ #context;
119
+ #pacer;
120
+ #mapper;
121
+ #codec;
122
+ #packetId;
123
+ #sampleRate;
124
+ #channels;
125
+ #description;
126
+ #latencyMs;
127
+ #startupFrames;
128
+ #startupThresholdFrames;
129
+ #capacityFrames;
130
+ #diag;
131
+ #warmupFrames;
132
+ #onState;
133
+ #onDiag;
134
+ #onError;
135
+ #reassemblyPolicy;
136
+ #decoder = null;
137
+ #pipeline = null;
138
+ #worklet = null;
139
+ #fecClient;
140
+ #closed = false;
141
+ #readyPromise = null;
142
+ #workletGeneration = 0;
143
+ #startupReleased = false;
116
144
  constructor(opts) {
117
- __privateAdd(this, _AudioRenderPipeline_instances);
118
- __privateAdd(this, _context);
119
- __privateAdd(this, _pacer);
120
- __privateAdd(this, _mapper);
121
- __privateAdd(this, _codec);
122
- __privateAdd(this, _packetId);
123
- __privateAdd(this, _sampleRate);
124
- __privateAdd(this, _channels);
125
- __privateAdd(this, _description);
126
- __privateAdd(this, _latencyMs);
127
- __privateAdd(this, _startupFrames);
128
- __privateAdd(this, _startupThresholdFrames);
129
- __privateAdd(this, _capacityFrames);
130
- __privateAdd(this, _diag);
131
- __privateAdd(this, _warmupFrames);
132
- __privateAdd(this, _onState);
133
- __privateAdd(this, _onDiag);
134
- __privateAdd(this, _onError);
135
- __privateAdd(this, _reassemblyPolicy);
136
- __privateAdd(this, _decoder, null);
137
- __privateAdd(this, _pipeline, null);
138
- __privateAdd(this, _worklet, null);
139
- __privateAdd(this, _fecClient);
140
- __privateAdd(this, _closed, false);
141
- __privateAdd(this, _readyPromise, null);
142
- __privateAdd(this, _workletGeneration, 0);
143
- __privateAdd(this, _startupReleased, false);
144
- __privateSet(this, _context, opts.context);
145
- __privateSet(this, _mapper, opts.mapper);
146
- __privateSet(this, _codec, opts.codec);
147
- __privateSet(this, _packetId, opts.packetId);
148
- __privateSet(this, _sampleRate, opts.sampleRate);
149
- __privateSet(this, _channels, opts.channels);
150
- __privateSet(this, _description, opts.description);
151
- __privateSet(this, _latencyMs, opts.latencyMs);
152
- __privateSet(this, _startupFrames, opts.startupFrames);
153
- __privateSet(this, _startupThresholdFrames, opts.startupFrames ?? Math.ceil(opts.sampleRate * (opts.latencyMs / 1e3)));
154
- __privateSet(this, _capacityFrames, opts.capacityFrames);
155
- __privateSet(this, _diag, opts.diag ?? false);
156
- __privateSet(this, _warmupFrames, opts.warmupFrames ?? 0);
157
- __privateSet(this, _onState, opts.onState);
158
- __privateSet(this, _onDiag, opts.onDiag);
159
- __privateSet(this, _onError, opts.onError);
160
- __privateSet(this, _fecClient, opts.fecClient);
161
- __privateSet(this, _reassemblyPolicy, opts.reassemblyPolicy);
145
+ this.#context = opts.context;
146
+ this.#mapper = opts.mapper;
147
+ this.#codec = opts.codec;
148
+ this.#packetId = opts.packetId;
149
+ this.#sampleRate = opts.sampleRate;
150
+ this.#channels = opts.channels;
151
+ this.#description = opts.description;
152
+ this.#latencyMs = opts.latencyMs;
153
+ this.#startupFrames = opts.startupFrames;
154
+ this.#startupThresholdFrames = opts.startupFrames ?? Math.ceil(opts.sampleRate * (opts.latencyMs / 1e3));
155
+ this.#capacityFrames = opts.capacityFrames;
156
+ this.#diag = opts.diag ?? false;
157
+ this.#warmupFrames = opts.warmupFrames ?? 0;
158
+ this.#onState = opts.onState;
159
+ this.#onDiag = opts.onDiag;
160
+ this.#onError = opts.onError;
161
+ this.#fecClient = opts.fecClient;
162
+ this.#reassemblyPolicy = opts.reassemblyPolicy;
162
163
  const auDurationMs = auDurationMsFromCodec(opts.codec, opts.sampleRate);
163
- __privateSet(this, _pacer, new FrameCountPacer({
164
+ this.#pacer = new FrameCountPacer({
164
165
  frameDurationMs: auDurationMs,
165
166
  mapper: opts.mapper,
166
- warmupFrames: __privateGet(this, _warmupFrames)
167
- }));
167
+ warmupFrames: this.#warmupFrames
168
+ });
168
169
  }
169
170
  /** Load worklet module + create decoder + pipeline. Call once. */
170
171
  async ready() {
171
- if (__privateGet(this, _readyPromise)) return __privateGet(this, _readyPromise);
172
- __privateSet(this, _readyPromise, __privateMethod(this, _AudioRenderPipeline_instances, initialize_fn).call(this));
173
- return __privateGet(this, _readyPromise);
172
+ if (this.#readyPromise) return this.#readyPromise;
173
+ this.#readyPromise = this.#initialize();
174
+ return this.#readyPromise;
175
+ }
176
+ async #initialize() {
177
+ await this.#context.audioWorklet.addModule(workletModuleUrl());
178
+ const worklet = new AudioWorkletNode(this.#context, WORKLET_PROCESSOR_NAME, {
179
+ numberOfInputs: 0,
180
+ numberOfOutputs: 1,
181
+ outputChannelCount: [this.#channels]
182
+ });
183
+ const initMsg = {
184
+ type: "init",
185
+ generation: ++this.#workletGeneration,
186
+ channels: this.#channels,
187
+ rate: this.#sampleRate,
188
+ latencyMs: this.#latencyMs,
189
+ startupFrames: this.#startupFrames,
190
+ capacityFrames: this.#capacityFrames,
191
+ holdUntilStart: true,
192
+ diag: this.#diag
193
+ };
194
+ worklet.port.postMessage(initMsg);
195
+ worklet.port.onmessage = (ev) => {
196
+ const m = ev.data;
197
+ if (m.type === "state") {
198
+ if (m.generation !== this.#workletGeneration) return;
199
+ this.#onState?.({
200
+ timestampUs: m.timestamp,
201
+ stalled: m.stalled,
202
+ bufferedFrames: m.bufferedFrames,
203
+ writtenFrames: m.writtenFrames
204
+ });
205
+ } else if (m.type === "ringBufDiag") {
206
+ if (m.generation !== this.#workletGeneration) return;
207
+ this.#onDiag?.({
208
+ reads: m.reads,
209
+ avgFill: m.avgFill,
210
+ capacity: m.capacity,
211
+ skipsPerSec: m.skipsPerSec,
212
+ dupsPerSec: m.dupsPerSec,
213
+ overflowSamplesPerSec: m.overflowSamplesPerSec,
214
+ underflowSamplesPerSec: m.underflowSamplesPerSec
215
+ });
216
+ } else if (m.type === "writeAck") {
217
+ if (m.generation !== this.#workletGeneration || this.#startupReleased || m.bufferedFrames < this.#startupThresholdFrames) return;
218
+ this.#startupReleased = true;
219
+ const start = {
220
+ type: "start",
221
+ generation: this.#workletGeneration
222
+ };
223
+ worklet.port.postMessage(start);
224
+ }
225
+ };
226
+ this.#worklet = worklet;
227
+ const decoder = new AudioDecoder({
228
+ output: (data) => this.#onDecoded(data),
229
+ error: (err) => this.#onError?.(err)
230
+ });
231
+ const config = {
232
+ codec: this.#codec,
233
+ sampleRate: this.#sampleRate,
234
+ numberOfChannels: this.#channels,
235
+ ...this.#description ? { description: this.#description } : {}
236
+ };
237
+ decoder.configure(config);
238
+ this.#decoder = decoder;
239
+ const pipeline = new MmtpDecodePipeline();
240
+ pipeline.configure({
241
+ codec: this.#codec,
242
+ packetId: this.#packetId,
243
+ description: this.#description,
244
+ reorderWindow: 0,
245
+ // audio doesn't need reorder — AAC/Opus frames are self-contained
246
+ reassemblyPolicy: this.#reassemblyPolicy
247
+ });
248
+ if (this.#fecClient) pipeline.setFecClient(this.#fecClient);
249
+ pipeline.onFrame((codecData, meta) => {
250
+ if (!this.#decoder || this.#decoder.state !== "configured") return;
251
+ if (codecData.byteLength === 0) return;
252
+ this.#pacer.notifyFrame();
253
+ try {
254
+ this.#decoder.decode(new EncodedAudioChunk({
255
+ type: "key",
256
+ data: codecData,
257
+ timestamp: meta.timestamp
258
+ }));
259
+ } catch (err) {
260
+ this.#onError?.(err);
261
+ }
262
+ });
263
+ this.#pipeline = pipeline;
174
264
  }
175
265
  /** Feed one MoQ object (raw MMTP packet). */
176
266
  feedMoqObject(packet) {
177
- __privateGet(this, _pipeline)?.feedMoqObject(packet);
267
+ this.#pipeline?.feedMoqObject(packet);
178
268
  }
179
269
  /** ms to sleep before the next object read. 0 when not anchored / not ahead. */
180
270
  paceSleepMs() {
181
- return __privateGet(this, _pacer).computeSleepMs();
271
+ return this.#pacer.computeSleepMs();
182
272
  }
183
273
  /** Pacer snapshot (for diagnostics / UI). */
184
274
  get pacerSnapshot() {
185
- return __privateGet(this, _pacer).snapshot;
275
+ return this.#pacer.snapshot;
186
276
  }
187
277
  /** Reset pacer on source switch (MoQ ↔ multicast). */
188
278
  resetPacer() {
189
- __privateGet(this, _pacer).reset();
279
+ this.#pacer.reset();
190
280
  }
191
281
  /** Drop queued PCM and its timestamp epoch at an explicit source boundary. */
192
282
  resetPlayout(startUnstalled = false) {
193
- __privateGet(this, _pacer).reset();
194
- __privateSet(this, _startupReleased, true);
283
+ this.#pacer.reset();
284
+ this.#startupReleased = true;
195
285
  const message = {
196
286
  type: "reset",
197
- generation: ++__privateWrapper(this, _workletGeneration)._,
287
+ generation: ++this.#workletGeneration,
198
288
  startUnstalled
199
289
  };
200
- __privateGet(this, _worklet)?.port.postMessage(message);
290
+ this.#worklet?.port.postMessage(message);
201
291
  }
202
292
  /** Node to connect to destination / gain. */
203
293
  get rootNode() {
204
- if (!__privateGet(this, _worklet)) throw new Error("AudioRenderPipeline.ready() must resolve first");
205
- return __privateGet(this, _worklet);
294
+ if (!this.#worklet) throw new Error("AudioRenderPipeline.ready() must resolve first");
295
+ return this.#worklet;
206
296
  }
207
297
  close() {
208
- if (__privateGet(this, _closed)) return;
209
- __privateSet(this, _closed, true);
298
+ if (this.#closed) return;
299
+ this.#closed = true;
210
300
  try {
211
- __privateGet(this, _decoder)?.close();
301
+ this.#decoder?.close();
212
302
  } catch {
213
303
  }
214
304
  try {
215
- __privateGet(this, _pipeline)?.dispose();
305
+ this.#pipeline?.dispose();
216
306
  } catch {
217
307
  }
218
308
  try {
219
- __privateGet(this, _worklet)?.disconnect();
309
+ this.#worklet?.disconnect();
220
310
  } catch {
221
311
  }
222
- __privateSet(this, _decoder, null);
223
- __privateSet(this, _pipeline, null);
224
- __privateSet(this, _worklet, null);
312
+ this.#decoder = null;
313
+ this.#pipeline = null;
314
+ this.#worklet = null;
225
315
  }
226
- };
227
- _context = new WeakMap();
228
- _pacer = new WeakMap();
229
- _mapper = new WeakMap();
230
- _codec = new WeakMap();
231
- _packetId = new WeakMap();
232
- _sampleRate = new WeakMap();
233
- _channels = new WeakMap();
234
- _description = new WeakMap();
235
- _latencyMs = new WeakMap();
236
- _startupFrames = new WeakMap();
237
- _startupThresholdFrames = new WeakMap();
238
- _capacityFrames = new WeakMap();
239
- _diag = new WeakMap();
240
- _warmupFrames = new WeakMap();
241
- _onState = new WeakMap();
242
- _onDiag = new WeakMap();
243
- _onError = new WeakMap();
244
- _reassemblyPolicy = new WeakMap();
245
- _decoder = new WeakMap();
246
- _pipeline = new WeakMap();
247
- _worklet = new WeakMap();
248
- _fecClient = new WeakMap();
249
- _closed = new WeakMap();
250
- _readyPromise = new WeakMap();
251
- _workletGeneration = new WeakMap();
252
- _startupReleased = new WeakMap();
253
- _AudioRenderPipeline_instances = new WeakSet();
254
- initialize_fn = async function() {
255
- await __privateGet(this, _context).audioWorklet.addModule(workletModuleUrl());
256
- const worklet = new AudioWorkletNode(__privateGet(this, _context), WORKLET_PROCESSOR_NAME, {
257
- numberOfInputs: 0,
258
- numberOfOutputs: 1,
259
- outputChannelCount: [__privateGet(this, _channels)]
260
- });
261
- const initMsg = {
262
- type: "init",
263
- generation: ++__privateWrapper(this, _workletGeneration)._,
264
- channels: __privateGet(this, _channels),
265
- rate: __privateGet(this, _sampleRate),
266
- latencyMs: __privateGet(this, _latencyMs),
267
- startupFrames: __privateGet(this, _startupFrames),
268
- capacityFrames: __privateGet(this, _capacityFrames),
269
- holdUntilStart: true,
270
- diag: __privateGet(this, _diag)
271
- };
272
- worklet.port.postMessage(initMsg);
273
- worklet.port.onmessage = (ev) => {
274
- var _a, _b;
275
- const m = ev.data;
276
- if (m.type === "state") {
277
- if (m.generation !== __privateGet(this, _workletGeneration)) return;
278
- (_a = __privateGet(this, _onState)) == null ? void 0 : _a.call(this, {
279
- timestampUs: m.timestamp,
280
- stalled: m.stalled,
281
- bufferedFrames: m.bufferedFrames,
282
- writtenFrames: m.writtenFrames
283
- });
284
- } else if (m.type === "ringBufDiag") {
285
- if (m.generation !== __privateGet(this, _workletGeneration)) return;
286
- (_b = __privateGet(this, _onDiag)) == null ? void 0 : _b.call(this, {
287
- reads: m.reads,
288
- avgFill: m.avgFill,
289
- capacity: m.capacity,
290
- skipsPerSec: m.skipsPerSec,
291
- dupsPerSec: m.dupsPerSec,
292
- overflowSamplesPerSec: m.overflowSamplesPerSec,
293
- underflowSamplesPerSec: m.underflowSamplesPerSec
294
- });
295
- } else if (m.type === "writeAck") {
296
- if (m.generation !== __privateGet(this, _workletGeneration) || __privateGet(this, _startupReleased) || m.bufferedFrames < __privateGet(this, _startupThresholdFrames)) return;
297
- __privateSet(this, _startupReleased, true);
298
- const start = {
299
- type: "start",
300
- generation: __privateGet(this, _workletGeneration)
301
- };
302
- worklet.port.postMessage(start);
316
+ // ─── Private ─────────────────────────────────────────────────────
317
+ #onDecoded(sample) {
318
+ if (this.#closed || !this.#worklet) {
319
+ sample.close();
320
+ return;
303
321
  }
304
- };
305
- __privateSet(this, _worklet, worklet);
306
- const decoder = new AudioDecoder({
307
- output: (data) => __privateMethod(this, _AudioRenderPipeline_instances, onDecoded_fn).call(this, data),
308
- error: (err) => {
309
- var _a;
310
- return (_a = __privateGet(this, _onError)) == null ? void 0 : _a.call(this, err);
311
- }
312
- });
313
- const config = {
314
- codec: __privateGet(this, _codec),
315
- sampleRate: __privateGet(this, _sampleRate),
316
- numberOfChannels: __privateGet(this, _channels),
317
- ...__privateGet(this, _description) ? { description: __privateGet(this, _description) } : {}
318
- };
319
- decoder.configure(config);
320
- __privateSet(this, _decoder, decoder);
321
- const pipeline = new MmtpDecodePipeline();
322
- pipeline.configure({
323
- codec: __privateGet(this, _codec),
324
- packetId: __privateGet(this, _packetId),
325
- description: __privateGet(this, _description),
326
- reorderWindow: 0,
327
- // audio doesn't need reorder — AAC/Opus frames are self-contained
328
- reassemblyPolicy: __privateGet(this, _reassemblyPolicy)
329
- });
330
- if (__privateGet(this, _fecClient)) pipeline.setFecClient(__privateGet(this, _fecClient));
331
- pipeline.onFrame((codecData, meta) => {
332
- var _a;
333
- if (!__privateGet(this, _decoder) || __privateGet(this, _decoder).state !== "configured") return;
334
- if (codecData.byteLength === 0) return;
335
- __privateGet(this, _pacer).notifyFrame();
336
- try {
337
- __privateGet(this, _decoder).decode(new EncodedAudioChunk({
338
- type: "key",
339
- data: codecData,
340
- timestamp: meta.timestamp
341
- }));
342
- } catch (err) {
343
- (_a = __privateGet(this, _onError)) == null ? void 0 : _a.call(this, err);
322
+ const timestamp = sample.timestamp;
323
+ const channelData = [];
324
+ for (let ch = 0; ch < sample.numberOfChannels; ch++) {
325
+ const data = new Float32Array(sample.numberOfFrames);
326
+ sample.copyTo(data, { format: "f32-planar", planeIndex: ch });
327
+ channelData.push(data);
344
328
  }
345
- });
346
- __privateSet(this, _pipeline, pipeline);
347
- };
348
- // ─── Private ─────────────────────────────────────────────────────
349
- onDecoded_fn = function(sample) {
350
- if (__privateGet(this, _closed) || !__privateGet(this, _worklet)) {
351
329
  sample.close();
352
- return;
353
- }
354
- const timestamp = sample.timestamp;
355
- const channelData = [];
356
- for (let ch = 0; ch < sample.numberOfChannels; ch++) {
357
- const data = new Float32Array(sample.numberOfFrames);
358
- sample.copyTo(data, { format: "f32-planar", planeIndex: ch });
359
- channelData.push(data);
330
+ const msg = {
331
+ type: "data",
332
+ data: channelData,
333
+ timestamp
334
+ };
335
+ this.#worklet.port.postMessage(msg, channelData.map((d) => d.buffer));
360
336
  }
361
- sample.close();
362
- const msg = {
363
- type: "data",
364
- data: channelData,
365
- timestamp
366
- };
367
- __privateGet(this, _worklet).port.postMessage(msg, channelData.map((d) => d.buffer));
368
337
  };
369
338
  export {
370
339
  AudioRenderPipeline