audio 2.0.0-1 → 2.1.0

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.
package/dist/audio.js ADDED
@@ -0,0 +1,3571 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn3, res) => function __init() {
4
+ return fn3 && (res = (0, fn3[__getOwnPropNames(fn3)[0]])(fn3 = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // node_modules/audio-mic/browser.js
12
+ var browser_exports = {};
13
+ __export(browser_exports, {
14
+ default: () => mic
15
+ });
16
+ async function mic(opts = {}) {
17
+ const channels2 = opts.channels || 1;
18
+ const sampleRate2 = opts.sampleRate || 44100;
19
+ const bitDepth = opts.bitDepth || 16;
20
+ const constraints = {
21
+ audio: {
22
+ sampleRate: { ideal: sampleRate2 },
23
+ channelCount: { ideal: channels2 },
24
+ echoCancellation: opts.echoCancellation ?? false,
25
+ noiseSuppression: opts.noiseSuppression ?? false,
26
+ autoGainControl: opts.autoGainControl ?? false
27
+ }
28
+ };
29
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
30
+ const ownCtx = !opts.context;
31
+ const ctx = opts.context || new AudioContext({ sampleRate: sampleRate2 });
32
+ const source = ctx.createMediaStreamSource(stream);
33
+ let closed = false;
34
+ let pending = null;
35
+ let node;
36
+ if (ctx.audioWorklet) {
37
+ const workletCode = `
38
+ class MicProcessor extends AudioWorkletProcessor {
39
+ process(inputs) {
40
+ const input = inputs[0]
41
+ if (input && input.length > 0) {
42
+ const channels = []
43
+ for (let i = 0; i < input.length; i++) channels.push(input[i].slice())
44
+ this.port.postMessage(channels)
45
+ }
46
+ return true
47
+ }
48
+ }
49
+ registerProcessor('mic-processor', MicProcessor)
50
+ `;
51
+ const blob = new Blob([workletCode], { type: "application/javascript" });
52
+ const url = URL.createObjectURL(blob);
53
+ await ctx.audioWorklet.addModule(url);
54
+ URL.revokeObjectURL(url);
55
+ node = new AudioWorkletNode(ctx, "mic-processor", {
56
+ numberOfInputs: 1,
57
+ numberOfOutputs: 0,
58
+ channelCount: channels2
59
+ });
60
+ source.connect(node);
61
+ node.port.onmessage = (e) => {
62
+ if (closed || !pending) return;
63
+ const cb = pending;
64
+ pending = null;
65
+ cb(null, float32ToPCM(e.data, bitDepth));
66
+ };
67
+ } else {
68
+ const bufSize = 2048;
69
+ node = ctx.createScriptProcessor(bufSize, channels2, 1);
70
+ source.connect(node);
71
+ node.connect(ctx.destination);
72
+ node.onaudioprocess = (e) => {
73
+ if (closed || !pending) return;
74
+ const cb = pending;
75
+ pending = null;
76
+ const chans = [];
77
+ for (let i = 0; i < channels2; i++) chans.push(e.inputBuffer.getChannelData(i).slice());
78
+ cb(null, float32ToPCM(chans, bitDepth));
79
+ };
80
+ }
81
+ read.close = close;
82
+ read.end = close;
83
+ read.backend = "mediastream";
84
+ return read;
85
+ function read(cb) {
86
+ if (cb == null || closed) {
87
+ close();
88
+ return;
89
+ }
90
+ if (ctx.state === "suspended") ctx.resume();
91
+ pending = cb;
92
+ }
93
+ function close() {
94
+ if (closed) return;
95
+ closed = true;
96
+ pending = null;
97
+ source.disconnect();
98
+ stream.getTracks().forEach((t) => t.stop());
99
+ if (ownCtx) ctx.close?.();
100
+ }
101
+ function float32ToPCM(channelData, bits) {
102
+ const ch = channelData.length;
103
+ const len = channelData[0].length;
104
+ const bps = bits / 8;
105
+ const buf = new Uint8Array(len * ch * bps);
106
+ const view = new DataView(buf.buffer);
107
+ for (let i = 0; i < len; i++) {
108
+ for (let c = 0; c < ch; c++) {
109
+ const sample = channelData[c][i];
110
+ const offset = (i * ch + c) * bps;
111
+ if (bits === 16) {
112
+ view.setInt16(offset, Math.max(-32768, Math.min(32767, Math.round(sample * 32767))), true);
113
+ } else if (bits === 32) {
114
+ view.setFloat32(offset, sample, true);
115
+ } else if (bits === 8) {
116
+ buf[offset] = Math.max(0, Math.min(255, Math.round((sample + 1) * 127.5)));
117
+ }
118
+ }
119
+ }
120
+ return buf;
121
+ }
122
+ }
123
+ var init_browser = __esm({
124
+ "node_modules/audio-mic/browser.js"() {
125
+ }
126
+ });
127
+
128
+ // node_modules/audio-type/audio-type.js
129
+ function audioType(buf) {
130
+ if (!buf) return;
131
+ buf = new Uint8Array(buf.buffer || buf);
132
+ if (isWav(buf)) return "wav";
133
+ if (isAiff(buf)) return "aiff";
134
+ if (isMp3(buf)) return "mp3";
135
+ if (isAac(buf)) return "aac";
136
+ if (isFlac(buf)) return "flac";
137
+ if (isM4a(buf)) return "m4a";
138
+ if (isOpus(buf)) return "opus";
139
+ if (isOgg(buf)) return "oga";
140
+ if (isQoa(buf)) return "qoa";
141
+ if (isMidi(buf)) return "mid";
142
+ if (isCaf(buf)) return "caf";
143
+ if (isWma(buf)) return "wma";
144
+ if (isAmr(buf)) return "amr";
145
+ if (isWebm(buf)) return "webm";
146
+ }
147
+ function isMp3(buf) {
148
+ if (!buf || buf.length < 3) return;
149
+ return buf[0] === 73 && buf[1] === 68 && buf[2] === 51 || // ID3
150
+ buf[0] === 255 && (buf[1] & 224) === 224 && (buf[1] & 6) !== 0 || // MPEG sync, layer != 0 (excludes AAC)
151
+ buf[0] === 84 && buf[1] === 65 && buf[2] === 71;
152
+ }
153
+ function isWav(buf) {
154
+ if (!buf || buf.length < 12) return;
155
+ return buf[0] === 82 && buf[1] === 73 && buf[2] === 70 && buf[3] === 70 && buf[8] === 87 && buf[9] === 65 && buf[10] === 86 && buf[11] === 69;
156
+ }
157
+ function isOgg(buf) {
158
+ if (!buf || buf.length < 4) return;
159
+ return buf[0] === 79 && buf[1] === 103 && buf[2] === 103 && buf[3] === 83;
160
+ }
161
+ function isFlac(buf) {
162
+ if (!buf || buf.length < 4) return;
163
+ return buf[0] === 102 && buf[1] === 76 && buf[2] === 97 && buf[3] === 67;
164
+ }
165
+ function isM4a(buf) {
166
+ if (!buf || buf.length < 8) return;
167
+ return buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112 || buf[0] === 77 && buf[1] === 52 && buf[2] === 65 && buf[3] === 32;
168
+ }
169
+ function isOpus(buf) {
170
+ if (!buf || buf.length < 36) return;
171
+ return buf[0] === 79 && buf[1] === 103 && buf[2] === 103 && buf[3] === 83 && buf[28] === 79 && buf[29] === 112 && buf[30] === 117 && buf[31] === 115 && buf[32] === 72 && buf[33] === 101 && buf[34] === 97 && buf[35] === 100;
172
+ }
173
+ function isQoa(buf) {
174
+ if (!buf || buf.length < 4) return;
175
+ return buf[0] === 113 && buf[1] === 111 && buf[2] === 97 && buf[3] === 102;
176
+ }
177
+ function isAiff(buf) {
178
+ if (!buf || buf.length < 12) return;
179
+ return buf[0] === 70 && buf[1] === 79 && buf[2] === 82 && buf[3] === 77 && buf[8] === 65 && buf[9] === 73 && buf[10] === 70 && (buf[11] === 70 || buf[11] === 67);
180
+ }
181
+ function isAac(buf) {
182
+ if (!buf || buf.length < 2) return;
183
+ return buf[0] === 255 && (buf[1] & 240) === 240 && (buf[1] & 6) === 0;
184
+ }
185
+ function isMidi(buf) {
186
+ if (!buf || buf.length < 4) return;
187
+ return buf[0] === 77 && buf[1] === 84 && buf[2] === 104 && buf[3] === 100;
188
+ }
189
+ function isCaf(buf) {
190
+ if (!buf || buf.length < 4) return;
191
+ return buf[0] === 99 && buf[1] === 97 && buf[2] === 102 && buf[3] === 102;
192
+ }
193
+ function isWma(buf) {
194
+ if (!buf || buf.length < 8) return;
195
+ return buf[0] === 48 && buf[1] === 38 && buf[2] === 178 && buf[3] === 117 && buf[4] === 142 && buf[5] === 102 && buf[6] === 207 && buf[7] === 17;
196
+ }
197
+ function isAmr(buf) {
198
+ if (!buf || buf.length < 5) return;
199
+ return buf[0] === 35 && buf[1] === 33 && buf[2] === 65 && buf[3] === 77 && buf[4] === 82;
200
+ }
201
+ function isWebm(buf) {
202
+ if (!buf || buf.length < 4) return;
203
+ return buf[0] === 26 && buf[1] === 69 && buf[2] === 223 && buf[3] === 163;
204
+ }
205
+
206
+ // node_modules/audio-decode/audio-decode.js
207
+ var EMPTY = Object.freeze({ channelData: Object.freeze([]), sampleRate: 0 });
208
+ async function decode(src) {
209
+ if (!src || typeof src === "string" || !(src.buffer || src.byteLength || src.length))
210
+ throw TypeError("Expected ArrayBuffer or Uint8Array");
211
+ let buf = new Uint8Array(src);
212
+ let type = audioType(buf);
213
+ if (!type) throw Error("Unknown audio format");
214
+ if (!decode[type]) throw Error("No decoder for " + type);
215
+ let dec = await decode[type]();
216
+ try {
217
+ let result = await dec(buf);
218
+ let flushed = await dec();
219
+ return merge(result, flushed);
220
+ } catch (e) {
221
+ dec.free();
222
+ throw e;
223
+ }
224
+ }
225
+ function reg(name, load) {
226
+ decode[name] = fmt(name, async () => {
227
+ let mod = await load();
228
+ if (mod.decoder) {
229
+ let codec2 = await mod.decoder();
230
+ return streamDecoder(
231
+ (chunk) => codec2.decode(chunk),
232
+ codec2.flush ? () => codec2.flush() : null,
233
+ codec2.free ? () => codec2.free() : null
234
+ );
235
+ }
236
+ let init2 = mod.default || mod;
237
+ let codec = typeof init2 === "function" ? await init2() : init2;
238
+ if (codec.ready) await codec.ready;
239
+ return streamDecoder(
240
+ (chunk) => codec.decode(chunk),
241
+ codec.flush ? () => codec.flush() : null,
242
+ codec.free ? () => codec.free() : null
243
+ );
244
+ });
245
+ }
246
+ function fmt(name, init2) {
247
+ let fn3 = async (src) => {
248
+ if (!src) return init2();
249
+ console.warn("decode." + name + "(data) is deprecated, use decode(data) or let dec = await decode." + name + "()");
250
+ let dec = await init2();
251
+ try {
252
+ let result = await dec(src instanceof Uint8Array ? src : new Uint8Array(src.buffer || src));
253
+ let flushed = await dec();
254
+ return merge(result, flushed);
255
+ } catch (e) {
256
+ dec.free();
257
+ throw e;
258
+ }
259
+ };
260
+ fn3.stream = init2;
261
+ return fn3;
262
+ }
263
+ reg("mp3", () => import("mpg123-decoder").then((m2) => ({ decoder: async () => {
264
+ let d2 = new m2.MPEGDecoder();
265
+ await d2.ready;
266
+ return d2;
267
+ } })));
268
+ reg("flac", () => import("@wasm-audio-decoders/flac").then((m2) => ({ decoder: async () => {
269
+ let d2 = new m2.FLACDecoder();
270
+ await d2.ready;
271
+ return d2;
272
+ } })));
273
+ reg("opus", () => import("ogg-opus-decoder").then((m2) => ({ decoder: async () => {
274
+ let d2 = new m2.OggOpusDecoder();
275
+ await d2.ready;
276
+ return d2;
277
+ } })));
278
+ reg("oga", () => import("@wasm-audio-decoders/ogg-vorbis").then((m2) => ({ decoder: async () => {
279
+ let d2 = new m2.OggVorbisDecoder();
280
+ await d2.ready;
281
+ return d2;
282
+ } })));
283
+ reg("m4a", () => import("@audio/decode-aac"));
284
+ reg("wav", () => import("@audio/decode-wav"));
285
+ reg("qoa", () => import("qoa-format").then((m2) => ({ decoder: async () => ({ decode: (chunk) => m2.decode(chunk) }) })));
286
+ reg("aac", () => import("@audio/decode-aac"));
287
+ reg("aiff", () => import("@audio/decode-aiff"));
288
+ reg("caf", () => import("@audio/decode-caf"));
289
+ reg("webm", () => import("@audio/decode-webm"));
290
+ reg("amr", () => import("@audio/decode-amr"));
291
+ reg("wma", () => import("@audio/decode-wma"));
292
+ function streamDecoder(onDecode, onFlush, onFree) {
293
+ let done = false;
294
+ let fn3 = async (chunk) => {
295
+ if (chunk) {
296
+ if (done) throw Error("Decoder already freed");
297
+ try {
298
+ return norm(await onDecode(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk)));
299
+ } catch (e) {
300
+ done = true;
301
+ onFree?.();
302
+ throw e;
303
+ }
304
+ }
305
+ if (done) return EMPTY;
306
+ done = true;
307
+ try {
308
+ let result = onFlush ? norm(await onFlush()) : EMPTY;
309
+ onFree?.();
310
+ return result;
311
+ } catch (e) {
312
+ onFree?.();
313
+ throw e;
314
+ }
315
+ };
316
+ fn3.decode = fn3;
317
+ fn3.flush = async () => {
318
+ if (done) return EMPTY;
319
+ return onFlush ? norm(await onFlush()) : EMPTY;
320
+ };
321
+ fn3.free = () => {
322
+ if (done) return;
323
+ done = true;
324
+ onFree?.();
325
+ };
326
+ return fn3;
327
+ }
328
+ function norm(r) {
329
+ if (!r?.channelData?.length) return EMPTY;
330
+ let { channelData, sampleRate: sampleRate2, samplesDecoded } = r;
331
+ if (samplesDecoded != null && samplesDecoded < channelData[0].length)
332
+ channelData = channelData.map((ch) => ch.subarray(0, samplesDecoded));
333
+ if (!channelData[0]?.length) return EMPTY;
334
+ if (channelData.length === 2) {
335
+ let a2 = channelData[0], b = channelData[1], same = true;
336
+ for (let i = 0; i < a2.length; i += 37) {
337
+ if (a2[i] !== b[i]) {
338
+ same = false;
339
+ break;
340
+ }
341
+ }
342
+ if (same) channelData = [a2];
343
+ }
344
+ return { channelData, sampleRate: sampleRate2 };
345
+ }
346
+ function merge(a2, b) {
347
+ if (!b?.channelData?.length) return a2;
348
+ if (!a2?.channelData?.length) return b;
349
+ let ach = a2.channelData.length, bch = b.channelData.length;
350
+ let ch = Math.max(ach, bch);
351
+ return {
352
+ channelData: Array.from({ length: ch }, (_, i) => {
353
+ let ac = a2.channelData[i % ach], bc = b.channelData[i % bch];
354
+ let merged = new Float32Array(ac.length + bc.length);
355
+ merged.set(ac);
356
+ merged.set(bc, ac.length);
357
+ return merged;
358
+ }),
359
+ sampleRate: a2.sampleRate
360
+ };
361
+ }
362
+
363
+ // node_modules/encode-audio/audio-encode.js
364
+ var EMPTY2 = new Uint8Array(0);
365
+ var encode = {};
366
+ var audio_encode_default = encode;
367
+ function reg2(name, load) {
368
+ encode[name] = fmt2(async (opts) => {
369
+ let init2 = (await load()).default;
370
+ let codec = await init2(opts);
371
+ return streamEncoder((ch) => codec.encode(ch), () => codec.flush(), () => codec.free());
372
+ });
373
+ }
374
+ reg2("wav", () => import("@audio/encode-wav"));
375
+ reg2("aiff", () => import("@audio/encode-aiff"));
376
+ reg2("mp3", () => import("@audio/encode-mp3"));
377
+ reg2("ogg", () => import("@audio/encode-ogg"));
378
+ reg2("flac", () => import("@audio/encode-flac"));
379
+ reg2("opus", () => import("@audio/encode-opus"));
380
+ function fmt2(init2) {
381
+ let fn3 = async (data, opts) => {
382
+ if (!opts) return init2(data);
383
+ if (!opts.sampleRate) throw Error("sampleRate is required");
384
+ let ch = channels(data);
385
+ if (!ch.length || !ch[0].length) return EMPTY2;
386
+ let enc = await init2({ channels: ch.length, ...opts });
387
+ try {
388
+ let result = await enc(ch);
389
+ let flushed = await enc();
390
+ return merge2(result, flushed);
391
+ } catch (e) {
392
+ enc.free();
393
+ throw e;
394
+ }
395
+ };
396
+ fn3.stream = init2;
397
+ return fn3;
398
+ }
399
+ function channels(data) {
400
+ if (!data) return [];
401
+ if (Array.isArray(data)) {
402
+ if (data[0] instanceof Float32Array) return data;
403
+ return [];
404
+ }
405
+ if (data instanceof Float32Array) return [data];
406
+ if (data.getChannelData && data.numberOfChannels) {
407
+ let ch = [];
408
+ for (let i = 0; i < data.numberOfChannels; i++) ch.push(data.getChannelData(i));
409
+ return ch;
410
+ }
411
+ return [];
412
+ }
413
+ function streamEncoder(onEncode, onFlush, onFree) {
414
+ let done = false;
415
+ let fn3 = async (data) => {
416
+ if (data) {
417
+ if (done) throw Error("Encoder already freed");
418
+ let ch = channels(data);
419
+ try {
420
+ return norm2(await onEncode(ch));
421
+ } catch (e) {
422
+ done = true;
423
+ onFree?.();
424
+ throw e;
425
+ }
426
+ }
427
+ if (done) return EMPTY2;
428
+ done = true;
429
+ try {
430
+ let result = onFlush ? norm2(await onFlush()) : EMPTY2;
431
+ onFree?.();
432
+ return result;
433
+ } catch (e) {
434
+ onFree?.();
435
+ throw e;
436
+ }
437
+ };
438
+ fn3.encode = fn3;
439
+ fn3.flush = async () => {
440
+ if (done) return EMPTY2;
441
+ return onFlush ? norm2(await onFlush()) : EMPTY2;
442
+ };
443
+ fn3.free = () => {
444
+ if (done) return;
445
+ done = true;
446
+ onFree?.();
447
+ };
448
+ return fn3;
449
+ }
450
+ function norm2(r) {
451
+ if (!r?.length) return EMPTY2;
452
+ if (r instanceof Uint8Array) return r;
453
+ if (r.buffer) return new Uint8Array(r.buffer, r.byteOffset, r.byteLength);
454
+ return new Uint8Array(r);
455
+ }
456
+ function merge2(a2, b) {
457
+ if (!b?.length) return a2 || EMPTY2;
458
+ if (!a2?.length) return b || EMPTY2;
459
+ let out = new Uint8Array(a2.length + b.length);
460
+ out.set(a2);
461
+ out.set(b, a2.length);
462
+ return out;
463
+ }
464
+
465
+ // node_modules/pcm-convert/index.js
466
+ var sampleRate = [8e3, 11025, 16e3, 22050, 44100, 48e3, 88200, 96e3, 176400, 192e3, 352800, 384e3];
467
+ var _AudioBuffer = typeof AudioBuffer !== "undefined" ? AudioBuffer : null;
468
+ try {
469
+ _AudioBuffer ??= (await import("audio-buffer")).default;
470
+ } catch {
471
+ }
472
+ var RATE_SET = new Set(sampleRate);
473
+ var DTYPE = {
474
+ float32: { C: Float32Array, min: -1, max: 1 },
475
+ float64: { C: Float64Array, min: -1, max: 1 },
476
+ uint8: { C: Uint8Array, min: 0, max: 255 },
477
+ uint16: { C: Uint16Array, min: 0, max: 65535 },
478
+ uint32: { C: Uint32Array, min: 0, max: 4294967295 },
479
+ int8: { C: Int8Array, min: -128, max: 127 },
480
+ int16: { C: Int16Array, min: -32768, max: 32767 },
481
+ int32: { C: Int32Array, min: -2147483648, max: 2147483647 }
482
+ };
483
+ var dtype = (d2) => DTYPE[d2] && d2 || DTYPE[d2 + "32"] && d2 + "32";
484
+ var CONTAINER = { array: 1, arraybuffer: 1, buffer: 1, audiobuffer: 1 };
485
+ var CHANNELS = { mono: 1, stereo: 2, "2.1": 3, quad: 4, "5.1": 6 };
486
+ for (let i = 3; i <= 32; i++) CHANNELS[i + "-channel"] ||= i;
487
+ var CHANNEL_NAME = {};
488
+ for (let k in CHANNELS) CHANNEL_NAME[CHANNELS[k]] ||= k;
489
+ var isTyped = (v) => ArrayBuffer.isView(v) && !(v instanceof DataView);
490
+ var isPlanar = (v) => Array.isArray(v) && v.length > 0 && isTyped(v[0]);
491
+ var isContainer = (v) => v != null && typeof v !== "string" && !isPlanar(v) && (Array.isArray(v) || isTyped(v) || v instanceof ArrayBuffer);
492
+ var isAudioBuffer = (v) => v != null && typeof v.getChannelData === "function" && typeof v.numberOfChannels === "number";
493
+ function parse(fmt3) {
494
+ if (!fmt3) return {};
495
+ if (typeof fmt3 !== "string") {
496
+ let r2 = {};
497
+ let d2 = fmt3.dtype || fmt3.type;
498
+ if (dtype(d2)) r2.dtype = dtype(d2);
499
+ if (d2 && CONTAINER[d2]) r2.container = d2;
500
+ if (fmt3.channels != null) r2.channels = CHANNELS[fmt3.channels] || +fmt3.channels;
501
+ if (fmt3.numberOfChannels != null) r2.channels ??= fmt3.numberOfChannels;
502
+ if (fmt3.interleaved != null) r2.interleaved = fmt3.interleaved;
503
+ if (fmt3.endianness) r2.endianness = fmt3.endianness;
504
+ if (fmt3.sampleRate != null) r2.sampleRate = fmt3.sampleRate;
505
+ if (fmt3.rate != null) r2.sampleRate ??= fmt3.rate;
506
+ if (fmt3.container) r2.container = fmt3.container;
507
+ return r2;
508
+ }
509
+ let r = {};
510
+ for (let t of fmt3.split(/\s*[,;_]\s*|\s+/)) {
511
+ let lo = t.toLowerCase();
512
+ if (dtype(lo)) r.dtype = dtype(lo);
513
+ else if (CONTAINER[lo]) r.container = lo;
514
+ else if (CHANNELS[lo]) r.channels = CHANNELS[lo];
515
+ else if (lo === "interleaved") r.interleaved = true;
516
+ else if (lo === "planar") r.interleaved = false;
517
+ else if (lo === "le") r.endianness = "le";
518
+ else if (lo === "be") r.endianness = "be";
519
+ else if (/^\d+$/.test(lo) && RATE_SET.has(+lo)) r.sampleRate = +lo;
520
+ else throw Error("Unknown format token: " + t);
521
+ }
522
+ return r;
523
+ }
524
+ function detect(data) {
525
+ if (data == null) return {};
526
+ if (isAudioBuffer(data))
527
+ return { dtype: "float32", channels: data.numberOfChannels, interleaved: false, sampleRate: data.sampleRate };
528
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) return { dtype: "uint8", container: "buffer" };
529
+ if (data instanceof Float32Array) return { dtype: "float32" };
530
+ if (data instanceof Float64Array) return { dtype: "float64" };
531
+ if (data instanceof Int8Array) return { dtype: "int8" };
532
+ if (data instanceof Int16Array) return { dtype: "int16" };
533
+ if (data instanceof Int32Array) return { dtype: "int32" };
534
+ if (data instanceof Uint8Array) return { dtype: "uint8" };
535
+ if (data instanceof Uint8ClampedArray) return { dtype: "uint8" };
536
+ if (data instanceof Uint16Array) return { dtype: "uint16" };
537
+ if (data instanceof Uint32Array) return { dtype: "uint32" };
538
+ if (data instanceof ArrayBuffer) return { container: "arraybuffer" };
539
+ if (Array.isArray(data)) {
540
+ if (isPlanar(data))
541
+ return { ...detect(data[0]), channels: data.length, interleaved: false };
542
+ return { container: "array" };
543
+ }
544
+ return {};
545
+ }
546
+ function range(d2) {
547
+ return DTYPE[d2] || { min: -1, max: 1 };
548
+ }
549
+ function convert(src, from, to, dst) {
550
+ if (!src) throw Error("Source data required");
551
+ if (from == null) throw Error("Format required");
552
+ let srcInfo = detect(src);
553
+ if (to === void 0 && dst === void 0) {
554
+ if (isContainer(from)) {
555
+ dst = from;
556
+ to = detect(dst);
557
+ from = srcInfo;
558
+ } else {
559
+ to = parse(from);
560
+ from = srcInfo;
561
+ }
562
+ } else if (dst === void 0) {
563
+ if (isContainer(to)) {
564
+ dst = to;
565
+ to = parse(from);
566
+ from = srcInfo;
567
+ } else {
568
+ from = { ...srcInfo, ...parse(from) };
569
+ to = parse(to);
570
+ }
571
+ } else {
572
+ from = { ...srcInfo, ...parse(from) };
573
+ to = { ...dst ? detect(dst) : {}, ...parse(to) };
574
+ }
575
+ if (to.container === "audiobuffer") to.dtype = "float32";
576
+ if (!to.dtype) to.dtype = from.dtype;
577
+ if (to.channels == null && from.channels != null) to.channels = from.channels;
578
+ if (to.interleaved != null && from.interleaved == null) {
579
+ from.interleaved = !to.interleaved;
580
+ if (!from.channels) from.channels = 2;
581
+ }
582
+ if (from.interleaved != null && !from.channels) from.channels = 2;
583
+ let fromR = from.container === "array" ? { min: -1, max: 1 } : range(from.dtype);
584
+ let toR = to.container === "array" ? { min: -1, max: 1 } : range(to.dtype);
585
+ let samples;
586
+ if (isPlanar(src)) {
587
+ let ch2 = src.length, len2 = src[0].length;
588
+ samples = new src[0].constructor(len2 * ch2);
589
+ for (let c = 0; c < ch2; c++) samples.set(src[c], len2 * c);
590
+ } else if (isAudioBuffer(src)) {
591
+ let nc = src.numberOfChannels, len2 = src.length;
592
+ samples = new Float32Array(len2 * nc);
593
+ for (let c = 0; c < nc; c++) samples.set(src.getChannelData(c), len2 * c);
594
+ } else if (src instanceof ArrayBuffer) {
595
+ samples = new (DTYPE[from.dtype]?.C || Uint8Array)(src);
596
+ } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(src)) {
597
+ samples = new (DTYPE[from.dtype]?.C || Uint8Array)(
598
+ src.buffer.slice(src.byteOffset, src.byteOffset + src.byteLength)
599
+ );
600
+ } else {
601
+ samples = src;
602
+ }
603
+ let len = samples.length;
604
+ let needsMap = fromR.min !== toR.min || fromR.max !== toR.max;
605
+ let reinterleave = from.interleaved != null && to.interleaved != null && from.interleaved !== to.interleaved;
606
+ let ch = from.channels || 1, seg2 = Math.floor(len / ch);
607
+ let Ctor = DTYPE[to.dtype]?.C || Float32Array;
608
+ let out;
609
+ if (!needsMap && !reinterleave) {
610
+ out = to.container === "array" ? Array.from(samples) : new Ctor(samples);
611
+ } else {
612
+ out = to.container === "array" ? new Array(len) : new Ctor(len);
613
+ let fromSpan = fromR.max - fromR.min;
614
+ let toIsInt = toR.max > 1;
615
+ let toSpan = fromR.min === -1 && fromR.max === 1 && toIsInt ? toR.max - toR.min + 1 : toR.max - toR.min;
616
+ let roundInt = fromR.min === -1 && fromR.max === 1 && toIsInt;
617
+ if (!reinterleave) {
618
+ for (let i = 0; i < len; i++) {
619
+ let v = (samples[i] - fromR.min) / fromSpan * toSpan + toR.min;
620
+ if (roundInt) v = Math.round(v);
621
+ out[i] = v < toR.min ? toR.min : v > toR.max ? toR.max : v;
622
+ }
623
+ } else {
624
+ let deint = from.interleaved;
625
+ for (let i = 0; i < len; i++) {
626
+ let si = deint ? i % seg2 * ch + ~~(i / seg2) : i % ch * seg2 + ~~(i / ch);
627
+ let v = samples[si];
628
+ if (needsMap) {
629
+ v = (v - fromR.min) / fromSpan * toSpan + toR.min;
630
+ if (roundInt) v = Math.round(v);
631
+ if (v < toR.min) v = toR.min;
632
+ else if (v > toR.max) v = toR.max;
633
+ }
634
+ out[i] = v;
635
+ }
636
+ }
637
+ }
638
+ if (dst) {
639
+ if (Array.isArray(dst)) {
640
+ for (let i = 0; i < len; i++) dst[i] = out[i];
641
+ out = dst;
642
+ } else if (dst instanceof ArrayBuffer) {
643
+ let tc = new (DTYPE[to.dtype]?.C || Uint8Array)(dst);
644
+ tc.set(out);
645
+ out = tc;
646
+ } else {
647
+ dst.set(out);
648
+ out = dst;
649
+ }
650
+ }
651
+ let info = DTYPE[to.dtype];
652
+ if (info && info.C.BYTES_PER_ELEMENT > 1 && from.endianness && to.endianness && from.endianness !== to.endianness && out.buffer) {
653
+ let le = to.endianness === "le";
654
+ let view = new DataView(out.buffer);
655
+ let step = info.C.BYTES_PER_ELEMENT;
656
+ let fn3 = "set" + to.dtype[0].toUpperCase() + to.dtype.slice(1);
657
+ for (let i = 0; i < len; i++) view[fn3](i * step, out[i], le);
658
+ }
659
+ if (to.container === "audiobuffer") {
660
+ let ABCtor = typeof AudioBuffer !== "undefined" ? AudioBuffer : _AudioBuffer;
661
+ if (!ABCtor) throw Error("AudioBuffer not available. In Node.js: install audio-buffer package or set globalThis.AudioBuffer");
662
+ let ch2 = to.channels || 1, segLen = Math.floor(out.length / ch2);
663
+ let sr = to.sampleRate || from.sampleRate || 44100;
664
+ let ab = new ABCtor({ length: segLen, numberOfChannels: ch2, sampleRate: sr });
665
+ let interleaved = reinterleave ? to.interleaved : from.interleaved ?? false;
666
+ if (interleaved && ch2 > 1) {
667
+ for (let c = 0; c < ch2; c++) {
668
+ let data = new Float32Array(segLen);
669
+ for (let i = 0; i < segLen; i++) data[i] = out[i * ch2 + c];
670
+ ab.copyToChannel(data, c);
671
+ }
672
+ } else {
673
+ for (let c = 0; c < ch2; c++) ab.copyToChannel(out.subarray(c * segLen, (c + 1) * segLen), c);
674
+ }
675
+ return ab;
676
+ }
677
+ if (to.container === "arraybuffer" || to.container === "buffer") return out.buffer || out;
678
+ return out;
679
+ }
680
+
681
+ // node_modules/parse-duration/locale/en.js
682
+ var unit = /* @__PURE__ */ Object.create(null);
683
+ var m = 6e4;
684
+ var h = m * 60;
685
+ var d = h * 24;
686
+ var y = d * 365.25;
687
+ unit.year = unit.yr = unit.y = y;
688
+ unit.month = unit.mo = unit.mth = y / 12;
689
+ unit.week = unit.wk = unit.w = d * 7;
690
+ unit.day = unit.d = d;
691
+ unit.hour = unit.hr = unit.h = h;
692
+ unit.minute = unit.min = unit.m = m;
693
+ unit.second = unit.sec = unit.s = 1e3;
694
+ unit.millisecond = unit.millisec = unit.ms = 1;
695
+ unit.microsecond = unit.microsec = unit.us = unit.\u00B5s = 1e-3;
696
+ unit.nanosecond = unit.nanosec = unit.ns = 1e-6;
697
+ unit.group = ",";
698
+ unit.decimal = ".";
699
+ unit.placeholder = " _";
700
+ var en_default = unit;
701
+
702
+ // node_modules/parse-duration/index.js
703
+ var durationRE = /((?:\d{1,16}(?:\.\d{1,16})?|\.\d{1,16})(?:[eE][-+]?\d{1,4})?)\s?([\p{L}]{0,14})/gu;
704
+ parse2.unit = en_default;
705
+ function parse2(str = "", format = "ms") {
706
+ let result = null, prevUnits;
707
+ String(str).replace(new RegExp(`(\\d)[${parse2.unit.placeholder}${parse2.unit.group}](\\d)`, "g"), "$1$2").replace(parse2.unit.decimal, ".").replace(durationRE, (_, n, units) => {
708
+ if (!units) {
709
+ if (prevUnits) {
710
+ for (const u in parse2.unit) if (parse2.unit[u] < prevUnits) {
711
+ units = u;
712
+ break;
713
+ }
714
+ } else units = format;
715
+ } else units = units.toLowerCase();
716
+ prevUnits = units = parse2.unit[units] || parse2.unit[units.replace(/s$/, "")];
717
+ if (units) result = (result || 0) + n * units;
718
+ });
719
+ return result && result / (parse2.unit[format] || 1) * (str[0] === "-" ? -1 : 1);
720
+ }
721
+
722
+ // core.js
723
+ audio.version = "2.1.0";
724
+ function parseTime(v) {
725
+ if (v == null) return v;
726
+ if (typeof v === "number") {
727
+ if (!Number.isFinite(v)) throw new Error(`Invalid time: ${v}`);
728
+ return v;
729
+ }
730
+ let tc = v.match(/^(\d+):(\d{1,2})(?::(\d{1,2}))?(?:\.(\d+))?$/);
731
+ if (tc) {
732
+ let [, a2, b, c, frac] = tc;
733
+ let s2 = c != null ? +a2 * 3600 + +b * 60 + +c : +a2 * 60 + +b;
734
+ if (frac) s2 += +("0." + frac);
735
+ return s2;
736
+ }
737
+ let s = parse2(v, "s");
738
+ if (s != null && isFinite(s)) return s;
739
+ throw new Error(`Invalid time: ${v}`);
740
+ }
741
+ function audio(source, opts = {}) {
742
+ if (source == null) {
743
+ let sr = opts.sampleRate || 44100, ch = opts.channels || 1;
744
+ let waiters2 = [];
745
+ let notify2 = () => {
746
+ for (let w of waiters2.splice(0)) w();
747
+ };
748
+ let a3 = create([], sr, ch, 0, opts, null);
749
+ a3.decoded = false;
750
+ a3.recording = false;
751
+ a3._.acc = pageAccumulator({ pages: a3.pages, notify: notify2, ondata: (...args) => emit(a3, "data", ...args) });
752
+ a3._.waiters = waiters2;
753
+ return a3;
754
+ }
755
+ if (source && typeof source === "object" && !Array.isArray(source) && source.edits) {
756
+ if (!source.source) throw new TypeError("audio: cannot restore document without source reference");
757
+ let a3 = audio(source.source, opts);
758
+ if (a3.run) for (let e of source.edits) a3.run(e);
759
+ return a3;
760
+ }
761
+ if (Array.isArray(source) && source.length && !(source[0] instanceof Float32Array)) {
762
+ let instances = source.map((s) => s?.pages ? s : audio(s, opts));
763
+ let first = instances[0].clip ? instances[0].clip() : audio.from(instances[0]);
764
+ if (!first.insert) throw new Error('audio([...]): concat requires insert plugin \u2014 import "audio" instead of "audio/core.js"');
765
+ for (let i = 1; i < instances.length; i++) first.insert(instances[i]);
766
+ let loading = instances.filter((s) => !s.decoded);
767
+ if (loading.length) {
768
+ first.ready = Promise.all(loading.map((s) => s.ready)).then(() => {
769
+ delete first.then;
770
+ delete first.catch;
771
+ return true;
772
+ });
773
+ first.ready.catch(() => {
774
+ });
775
+ makeThenable(first);
776
+ }
777
+ return first;
778
+ }
779
+ if (source?.getChannelData && source?.numberOfChannels) return audio.from(source, opts);
780
+ if (Array.isArray(source) && source[0] instanceof Float32Array || typeof source === "number") {
781
+ let a3 = audio.from(source, opts);
782
+ if (audio.evict && a3.cache && a3.budget !== Infinity) {
783
+ a3.ready = audio.evict(a3).then(() => {
784
+ delete a3.then;
785
+ delete a3.catch;
786
+ return true;
787
+ });
788
+ a3.ready.catch(() => {
789
+ });
790
+ makeThenable(a3);
791
+ }
792
+ return a3;
793
+ }
794
+ let ref = typeof source === "string" ? source : source instanceof URL ? source.href : null;
795
+ let pages = [], waiters = [];
796
+ let notify = () => {
797
+ for (let w of waiters.splice(0)) w();
798
+ };
799
+ let a2 = create(pages, 0, 0, 0, { ...opts, source: ref }, null);
800
+ a2._.waiters = waiters;
801
+ a2.decoded = false;
802
+ let readyResolve, readyReject;
803
+ a2._.ready = new Promise((r, j) => {
804
+ readyResolve = r;
805
+ readyReject = j;
806
+ });
807
+ a2._.ready.catch(() => {
808
+ });
809
+ a2.ready = (async () => {
810
+ try {
811
+ if (opts.storage === "persistent") {
812
+ if (!audio.opfsCache) throw new Error('Persistent storage requires cache module (import "./cache.js")');
813
+ try {
814
+ opts = { ...opts, cache: await audio.opfsCache(), budget: opts.budget ?? audio.DEFAULT_BUDGET ?? Infinity };
815
+ } catch {
816
+ throw new Error('OPFS not available (required by storage: "persistent")');
817
+ }
818
+ a2.cache = opts.cache;
819
+ a2.budget = opts.budget;
820
+ }
821
+ let result = await decodeSource(source, { pages, notify, ondata: (...args) => emit(a2, "data", ...args) });
822
+ a2.sampleRate = result.sampleRate;
823
+ a2._.ch = result.channels;
824
+ a2._.chV = -1;
825
+ if (result.acc) a2._.acc = result.acc;
826
+ emit(a2, "metadata", { sampleRate: result.sampleRate, channels: result.channels });
827
+ readyResolve();
828
+ let final = await result.decoding;
829
+ a2._.len = final.length;
830
+ a2._.lenV = -1;
831
+ a2.stats = final.stats;
832
+ a2.decoded = true;
833
+ notify();
834
+ audio.evict?.(a2);
835
+ delete a2.then;
836
+ delete a2.catch;
837
+ return true;
838
+ } catch (e) {
839
+ readyReject(e);
840
+ throw e;
841
+ }
842
+ })();
843
+ a2.ready.catch(() => {
844
+ });
845
+ makeThenable(a2);
846
+ return a2;
847
+ }
848
+ function makeThenable(a2) {
849
+ a2.then = function(resolve, reject) {
850
+ return a2.ready.then(() => {
851
+ delete a2.then;
852
+ delete a2.catch;
853
+ return a2;
854
+ }).then(resolve, reject);
855
+ };
856
+ a2.catch = function(reject) {
857
+ return a2.then(null, reject);
858
+ };
859
+ }
860
+ audio.from = function(source, opts = {}) {
861
+ if (Array.isArray(source) && source[0] instanceof Float32Array) return fromChannels(source, opts);
862
+ if (typeof source === "number") return fromSilence(source, opts);
863
+ if (typeof source === "function") return fromFunction(source, opts);
864
+ if (source?.pages) {
865
+ return create(
866
+ source.pages,
867
+ opts.sampleRate ?? source.sampleRate,
868
+ opts.channels ?? source._.ch,
869
+ source._.len,
870
+ { source: source.source, storage: source.storage, cache: source.cache, budget: opts.budget ?? source.budget },
871
+ source.stats
872
+ );
873
+ }
874
+ if (source?.getChannelData) {
875
+ let chs = Array.from({ length: source.numberOfChannels }, (_, i) => new Float32Array(source.getChannelData(i)));
876
+ return fromChannels(chs, { sampleRate: source.sampleRate, ...opts });
877
+ }
878
+ if (ArrayBuffer.isView(source) && opts.format) {
879
+ let fmt3 = parse(opts.format);
880
+ let ch = fmt3.channels || opts.channels || 1;
881
+ let sr = fmt3.sampleRate || opts.sampleRate || 44100;
882
+ let src = { ...fmt3, channels: ch };
883
+ if (ch > 1 && src.interleaved == null) src.interleaved = true;
884
+ let pcm = convert(source, src, { dtype: "float32", interleaved: false, channels: ch });
885
+ let perCh = pcm.length / ch;
886
+ let chs = Array.from({ length: ch }, (_, c) => pcm.subarray(c * perCh, (c + 1) * perCh));
887
+ return fromChannels(chs, { sampleRate: sr });
888
+ }
889
+ throw new TypeError("audio.from: expected Float32Array[], AudioBuffer, audio instance, function, or number");
890
+ };
891
+ var fn = {};
892
+ audio.fn = fn;
893
+ audio.BLOCK_SIZE = 1024;
894
+ audio.PAGE_SIZE = 1024 * audio.BLOCK_SIZE;
895
+ var LOAD = /* @__PURE__ */ Symbol("load");
896
+ var READ = /* @__PURE__ */ Symbol("read");
897
+ function emit(a2, event, ...args) {
898
+ let arr = a2._.ev[event];
899
+ if (arr) for (let cb of arr) cb(...args);
900
+ }
901
+ fn.on = function(event, cb) {
902
+ (this._.ev[event] ??= []).push(cb);
903
+ return this;
904
+ };
905
+ fn.off = function(event, cb) {
906
+ if (!event) {
907
+ this._.ev = {};
908
+ return this;
909
+ }
910
+ if (!cb) {
911
+ delete this._.ev[event];
912
+ return this;
913
+ }
914
+ let arr = this._.ev[event];
915
+ if (arr) {
916
+ let i = arr.indexOf(cb);
917
+ if (i >= 0) arr.splice(i, 1);
918
+ }
919
+ return this;
920
+ };
921
+ fn.dispose = function() {
922
+ this.stop();
923
+ this._.ev = {};
924
+ this._.pcm = null;
925
+ this._.plan = null;
926
+ this.pages.length = 0;
927
+ this.stats = null;
928
+ this._.waiters = null;
929
+ this._.acc = null;
930
+ };
931
+ if (Symbol.dispose) fn[Symbol.dispose] = fn.dispose;
932
+ audio.use = function(...plugins) {
933
+ for (let p of plugins) p(audio);
934
+ };
935
+ function create(pages, sampleRate2, ch, length, opts = {}, stats) {
936
+ let a2 = Object.create(fn);
937
+ a2.pages = pages;
938
+ a2.sampleRate = sampleRate2;
939
+ a2.source = opts.source ?? null;
940
+ a2.storage = opts.storage || "memory";
941
+ a2.cache = opts.cache || null;
942
+ a2.budget = opts.budget ?? Infinity;
943
+ a2.stats = stats;
944
+ a2.decoded = true;
945
+ a2.ready = Promise.resolve(true);
946
+ a2._ = {
947
+ ch,
948
+ // source channel count
949
+ len: length,
950
+ // source sample length
951
+ waiters: null,
952
+ // decode notify queue (null when not streaming)
953
+ ev: {},
954
+ // instance event listeners
955
+ ct: 0,
956
+ ctStamp: 0,
957
+ // currentTime wall-clock interpolation
958
+ vol: 1,
959
+ muted: false
960
+ // volume 0..1 linear with change events
961
+ };
962
+ a2.edits = [];
963
+ a2.version = 0;
964
+ a2._.pcm = null;
965
+ a2._.pcmV = -1;
966
+ a2._.plan = null;
967
+ a2._.planV = -1;
968
+ a2._.statsV = -1;
969
+ a2._.lenC = a2._.len;
970
+ a2._.lenV = 0;
971
+ a2._.chC = a2._.ch;
972
+ a2._.chV = 0;
973
+ Object.defineProperties(a2, {
974
+ currentTime: {
975
+ get() {
976
+ if (this.playing && !this.paused) {
977
+ let t = this._.ct + (performance.now() - this._.ctStamp) / 1e3;
978
+ let d2 = this.duration;
979
+ return d2 > 0 ? Math.min(t, d2) : t;
980
+ }
981
+ return this._.ct;
982
+ },
983
+ set(v) {
984
+ this._.ct = v;
985
+ this._.ctStamp = performance.now();
986
+ },
987
+ enumerable: true,
988
+ configurable: true
989
+ },
990
+ volume: {
991
+ get() {
992
+ return this._.vol;
993
+ },
994
+ set(v) {
995
+ v = Math.max(0, Math.min(1, +v || 0));
996
+ if (this._.vol !== v) {
997
+ this._.vol = v;
998
+ emit(this, "volumechange");
999
+ }
1000
+ },
1001
+ enumerable: true,
1002
+ configurable: true
1003
+ },
1004
+ muted: {
1005
+ get() {
1006
+ return this._.muted;
1007
+ },
1008
+ set(v) {
1009
+ v = !!v;
1010
+ if (this._.muted !== v) {
1011
+ this._.muted = v;
1012
+ emit(this, "volumechange");
1013
+ }
1014
+ },
1015
+ enumerable: true,
1016
+ configurable: true
1017
+ }
1018
+ });
1019
+ a2.playing = false;
1020
+ a2.paused = false;
1021
+ a2.ended = false;
1022
+ a2.seeking = false;
1023
+ a2.loop = false;
1024
+ a2.block = null;
1025
+ a2._.lru = /* @__PURE__ */ new Set();
1026
+ return a2;
1027
+ }
1028
+ function fromChannels(channelData, opts = {}) {
1029
+ let sr = opts.sampleRate || 44100;
1030
+ return create(paginate(channelData), sr, channelData.length, channelData[0].length, opts, audio.statSession?.(sr).page(channelData).done());
1031
+ }
1032
+ function fromSilence(seconds, opts = {}) {
1033
+ let sr = opts.sampleRate || 44100, ch = opts.channels || 1;
1034
+ return fromChannels(Array.from({ length: ch }, () => new Float32Array(Math.round(seconds * sr))), { ...opts, sampleRate: sr });
1035
+ }
1036
+ function fromFunction(fn3, opts = {}) {
1037
+ let sr = opts.sampleRate || 44100, ch = opts.channels || 1;
1038
+ let dur = opts.duration;
1039
+ if (dur == null) throw new TypeError("audio.from(fn): duration required");
1040
+ let len = Math.round(dur * sr);
1041
+ let chs = Array.from({ length: ch }, () => new Float32Array(len));
1042
+ for (let i = 0; i < len; i++) {
1043
+ let v = fn3(i / sr, i);
1044
+ if (typeof v === "number") for (let c = 0; c < ch; c++) chs[c][i] = v;
1045
+ else for (let c = 0; c < ch; c++) chs[c][i] = v[c] ?? 0;
1046
+ }
1047
+ return fromChannels(chs, { sampleRate: sr });
1048
+ }
1049
+ Object.defineProperties(fn, {
1050
+ length: { get() {
1051
+ return this._.len;
1052
+ }, configurable: true },
1053
+ duration: { get() {
1054
+ return this.length / this.sampleRate;
1055
+ }, configurable: true },
1056
+ channels: { get() {
1057
+ return this._.ch;
1058
+ }, configurable: true }
1059
+ });
1060
+ fn[LOAD] = async function() {
1061
+ if (this._.ready) await this._.ready;
1062
+ this._.acc?.drain();
1063
+ };
1064
+ fn[READ] = function(offset, duration) {
1065
+ return readPages(this, offset, duration);
1066
+ };
1067
+ fn.push = function(data, fmt3) {
1068
+ let acc = this._.acc;
1069
+ if (!acc) throw new Error("push: instance is not pushable \u2014 create with audio()");
1070
+ let ch = this._.ch, sr = this.sampleRate;
1071
+ let chData;
1072
+ if (Array.isArray(data) && data[0] instanceof Float32Array) chData = data;
1073
+ else if (data instanceof Float32Array) chData = [data];
1074
+ else if (ArrayBuffer.isView(data)) {
1075
+ let f = fmt3 || {};
1076
+ let srcFmt = typeof f === "string" ? f : f.format || "int16";
1077
+ let nch = f.channels || ch;
1078
+ let src = { dtype: srcFmt, channels: nch };
1079
+ if (nch > 1) src.interleaved = true;
1080
+ let pcm = convert(data, src, { dtype: "float32", interleaved: false, channels: nch });
1081
+ let perCh = pcm.length / nch;
1082
+ chData = Array.from({ length: nch }, (_, c) => pcm.subarray(c * perCh, (c + 1) * perCh));
1083
+ } else throw new TypeError("push: expected Float32Array[], Float32Array, or typed array");
1084
+ if (!this._.ch) {
1085
+ this._.ch = chData.length;
1086
+ this._.chV = -1;
1087
+ } else if (chData.length !== this._.ch) throw new TypeError(`push: expected ${this._.ch} channels, got ${chData.length}`);
1088
+ acc.push(chData, fmt3 && fmt3.sampleRate || sr);
1089
+ this._.len = acc.length;
1090
+ this._.lenV = -1;
1091
+ return this;
1092
+ };
1093
+ fn.stop = function() {
1094
+ this.playing = false;
1095
+ this.paused = false;
1096
+ this.seeking = false;
1097
+ if (this._._wake) this._._wake();
1098
+ if (this.recording) {
1099
+ this.recording = false;
1100
+ if (this._._mic) {
1101
+ this._._mic(null);
1102
+ this._._mic = null;
1103
+ }
1104
+ }
1105
+ if (this._.acc && !this.decoded) {
1106
+ this._.acc.drain();
1107
+ this.decoded = true;
1108
+ if (this._.waiters) for (let w of this._.waiters.splice(0)) w();
1109
+ }
1110
+ return this;
1111
+ };
1112
+ fn.record = function(opts = {}) {
1113
+ if (!this._.acc) throw new Error("record: instance is not pushable \u2014 create with audio()");
1114
+ if (this.recording) return this;
1115
+ this.recording = true;
1116
+ this.decoded = false;
1117
+ let self = this, sr = this.sampleRate, ch = this._.ch;
1118
+ let _rec = (async () => {
1119
+ try {
1120
+ let { default: mic2 } = await Promise.resolve().then(() => (init_browser(), browser_exports));
1121
+ let read = mic2({ sampleRate: sr, channels: ch, bitDepth: 16, ...opts });
1122
+ self._._mic = read;
1123
+ read((err, buf) => {
1124
+ if (!self.recording) return;
1125
+ if (err || !buf) return;
1126
+ self.push(new Int16Array(buf.buffer, buf.byteOffset, buf.byteLength / 2), "int16");
1127
+ });
1128
+ } catch (e) {
1129
+ self.recording = false;
1130
+ self.decoded = true;
1131
+ if (self._.waiters) for (let w of self._.waiters.splice(0)) w();
1132
+ throw e.code === "ERR_MODULE_NOT_FOUND" ? new Error("record: audio-mic not installed \u2014 npm i audio-mic") : e;
1133
+ }
1134
+ })();
1135
+ _rec.catch(() => {
1136
+ });
1137
+ return this;
1138
+ };
1139
+ fn.seek = function(t) {
1140
+ t = Math.max(0, t);
1141
+ this.seeking = true;
1142
+ this.currentTime = t;
1143
+ if (this.cache) {
1144
+ let page = Math.floor(t * this.sampleRate / audio.PAGE_SIZE);
1145
+ (async () => {
1146
+ for (let i = Math.max(0, page - 1); i <= Math.min(page + 2, this.pages.length - 1); i++)
1147
+ if (this.pages[i] === null && await this.cache.has(i)) this.pages[i] = await this.cache.read(i);
1148
+ })();
1149
+ }
1150
+ if (this.playing) {
1151
+ this._._seekTo = t;
1152
+ if (this._._wake) this._._wake();
1153
+ } else this.seeking = false;
1154
+ return this;
1155
+ };
1156
+ fn.read = async function(opts) {
1157
+ if (typeof opts !== "object" || opts === null) opts = {};
1158
+ let { at, duration, format, channel, meta } = opts;
1159
+ at = parseTime(at);
1160
+ duration = parseTime(duration);
1161
+ await this[LOAD]();
1162
+ let pcm = await this[READ](at, duration);
1163
+ if (channel != null) pcm = [pcm[channel]];
1164
+ if (!format) return channel != null ? pcm[0] : pcm;
1165
+ let converted = audio_encode_default[format] ? await audio_encode_default[format](pcm, { sampleRate: this.sampleRate, ...meta }) : pcm.map((ch) => convert(ch, "float32", format));
1166
+ return channel != null ? Array.isArray(converted) ? converted[0] : converted : converted;
1167
+ };
1168
+ function paginate(channelData) {
1169
+ let len = channelData[0].length, pages = [];
1170
+ for (let off = 0; off < len; off += audio.PAGE_SIZE)
1171
+ pages.push(channelData.map((ch) => ch.subarray(off, Math.min(off + audio.PAGE_SIZE, len))));
1172
+ return pages;
1173
+ }
1174
+ function walkPages(a2, c, srcOff, len, visitor) {
1175
+ let p0 = Math.floor(srcOff / audio.PAGE_SIZE), pos = p0 * audio.PAGE_SIZE;
1176
+ for (let p = p0; p < a2.pages.length && pos < srcOff + len; p++) {
1177
+ let pg = a2.pages[p], pLen = pg ? pg[0].length : audio.PAGE_SIZE;
1178
+ if (pos + pLen > srcOff && pg) {
1179
+ let s = Math.max(srcOff - pos, 0), e = Math.min(srcOff + len - pos, pLen);
1180
+ if (a2._.lru) {
1181
+ a2._.lru.delete(p);
1182
+ a2._.lru.add(p);
1183
+ }
1184
+ visitor(pg, c, s, e, Math.max(pos - srcOff, 0));
1185
+ }
1186
+ pos += pLen;
1187
+ }
1188
+ }
1189
+ function copyPages(a2, c, srcOff, len, target, tOff) {
1190
+ walkPages(a2, c, srcOff, len, (pg, ch, s, e, off) => target.set(pg[ch].subarray(s, e), tOff + off));
1191
+ }
1192
+ function readPages(a2, offset, duration) {
1193
+ let sr = a2.sampleRate, ch = a2._.ch;
1194
+ let s = offset != null ? Math.min(Math.max(Math.round(offset * sr), 0), a2._.len) : 0;
1195
+ let len = duration != null ? Math.round(duration * sr) : a2._.len - s;
1196
+ len = Math.min(Math.max(len, 0), a2._.len - s);
1197
+ let out = Array.from({ length: ch }, () => new Float32Array(len));
1198
+ for (let c = 0; c < ch; c++) copyPages(a2, c, s, len, out[c], 0);
1199
+ return out;
1200
+ }
1201
+ async function resolveSource(source) {
1202
+ if (source instanceof ArrayBuffer) return source;
1203
+ if (source instanceof Uint8Array) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
1204
+ if (source instanceof URL) return resolveSource(source.href);
1205
+ if (typeof source === "string") {
1206
+ if (/^(https?|data|blob):/.test(source) || typeof window !== "undefined")
1207
+ return (await fetch(source)).arrayBuffer();
1208
+ if (source.startsWith("file:")) {
1209
+ let { fileURLToPath } = await import("url");
1210
+ source = fileURLToPath(source);
1211
+ }
1212
+ let { readFile } = await import("fs/promises");
1213
+ let buf = await readFile(source);
1214
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
1215
+ }
1216
+ throw new TypeError("audio: unsupported source type");
1217
+ }
1218
+ async function detectSource(source) {
1219
+ if (source instanceof ArrayBuffer || source instanceof Uint8Array) {
1220
+ let bytes2 = source instanceof ArrayBuffer ? new Uint8Array(source) : source.byteOffset || source.byteLength !== source.buffer.byteLength ? new Uint8Array(source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength)) : new Uint8Array(source.buffer);
1221
+ return { format: audioType(bytes2), bytes: bytes2 };
1222
+ }
1223
+ if (typeof source === "string" && !/^(https?|data|blob):/.test(source) && typeof window === "undefined") {
1224
+ let path = source;
1225
+ if (source.startsWith("file:")) {
1226
+ let { fileURLToPath } = await import("url");
1227
+ path = fileURLToPath(source);
1228
+ }
1229
+ let { open } = await import("fs/promises");
1230
+ let fh = await open(path, "r");
1231
+ let hdr = new Uint8Array(12);
1232
+ await fh.read(hdr, 0, 12, 0);
1233
+ await fh.close();
1234
+ let format = audioType(new Uint8Array(hdr));
1235
+ let { createReadStream } = await import("fs");
1236
+ return { format, reader: createReadStream(path) };
1237
+ }
1238
+ let buf = await resolveSource(source);
1239
+ let bytes = new Uint8Array(buf);
1240
+ return { format: audioType(bytes), bytes };
1241
+ }
1242
+ function pageAccumulator(opts = {}) {
1243
+ let { pages = [], notify, ondata } = opts;
1244
+ let sr = 0, ch = 0, totalLen = 0, pagePos = 0;
1245
+ let pageBuf = null, session;
1246
+ function emit2(page) {
1247
+ pages.push(page);
1248
+ totalLen += page[0].length;
1249
+ notify?.();
1250
+ }
1251
+ return {
1252
+ pages,
1253
+ get sampleRate() {
1254
+ return sr;
1255
+ },
1256
+ get channels() {
1257
+ return ch;
1258
+ },
1259
+ get length() {
1260
+ return totalLen + pagePos;
1261
+ },
1262
+ get partial() {
1263
+ return pagePos > 0 ? pageBuf.map((c) => c.subarray(0, pagePos)) : null;
1264
+ },
1265
+ get partialLen() {
1266
+ return pagePos;
1267
+ },
1268
+ push(chData, sampleRate2) {
1269
+ if (!pageBuf) {
1270
+ sr = sampleRate2;
1271
+ ch = chData.length;
1272
+ pageBuf = Array.from({ length: ch }, () => new Float32Array(audio.PAGE_SIZE));
1273
+ session = audio.statSession?.(sr);
1274
+ }
1275
+ session?.page(chData);
1276
+ let srcPos = 0, chunkLen = chData[0].length;
1277
+ while (srcPos < chunkLen) {
1278
+ let n = Math.min(chunkLen - srcPos, audio.PAGE_SIZE - pagePos);
1279
+ for (let c = 0; c < ch; c++) pageBuf[c].set(chData[c].subarray(srcPos, srcPos + n), pagePos);
1280
+ srcPos += n;
1281
+ pagePos += n;
1282
+ if (pagePos === audio.PAGE_SIZE) {
1283
+ emit2(pageBuf);
1284
+ pageBuf = Array.from({ length: ch }, () => new Float32Array(audio.PAGE_SIZE));
1285
+ pagePos = 0;
1286
+ }
1287
+ }
1288
+ if (ondata) {
1289
+ let delta = session?.delta();
1290
+ if (delta) ondata({ delta, offset: (totalLen + pagePos) / sr, sampleRate: sr, channels: ch, pages });
1291
+ }
1292
+ notify?.();
1293
+ },
1294
+ /** Flush partial page into pages array. Non-destructive — accumulator stays open. */
1295
+ drain() {
1296
+ if (pagePos > 0) {
1297
+ emit2(pageBuf.map((c) => c.slice(0, pagePos)));
1298
+ pageBuf = Array.from({ length: ch }, () => new Float32Array(audio.PAGE_SIZE));
1299
+ pagePos = 0;
1300
+ }
1301
+ },
1302
+ done() {
1303
+ if (pagePos > 0) emit2(pageBuf.map((c) => c.slice(0, pagePos)));
1304
+ session?.flush();
1305
+ if (ondata && session) {
1306
+ let delta = session.delta();
1307
+ if (delta) ondata({ delta, offset: totalLen / sr, sampleRate: sr, channels: ch, pages });
1308
+ }
1309
+ return { stats: session?.done(), length: totalLen };
1310
+ }
1311
+ };
1312
+ }
1313
+ async function decodeSource(source, opts = {}) {
1314
+ let { format, bytes, reader } = await detectSource(source);
1315
+ if (!format || !decode[format]) {
1316
+ if (!bytes) bytes = new Uint8Array(await resolveSource(source));
1317
+ let { channelData, sampleRate: sampleRate2 } = await decode(bytes.buffer || bytes);
1318
+ let pages = opts.pages || [];
1319
+ let ps = paginate(channelData);
1320
+ for (let p of ps) {
1321
+ pages.push(p);
1322
+ opts.notify?.();
1323
+ }
1324
+ let stats = audio.statSession?.(sampleRate2)?.page(channelData)?.done() ?? null;
1325
+ return { pages, sampleRate: sampleRate2, channels: channelData.length, decoding: Promise.resolve({ stats, length: channelData[0].length }) };
1326
+ }
1327
+ let dec = await decode[format]();
1328
+ let yieldLoop = () => new Promise((r) => setTimeout(r, 0));
1329
+ let firstResolve;
1330
+ let origNotify = opts.notify;
1331
+ let firstReady = new Promise((r) => {
1332
+ firstResolve = r;
1333
+ });
1334
+ let acc = pageAccumulator({
1335
+ pages: opts.pages,
1336
+ ondata: opts.ondata,
1337
+ notify: () => {
1338
+ origNotify?.();
1339
+ if (firstResolve) {
1340
+ let f = firstResolve;
1341
+ firstResolve = null;
1342
+ f();
1343
+ }
1344
+ }
1345
+ });
1346
+ let decoding = (async () => {
1347
+ try {
1348
+ if (reader) {
1349
+ for await (let chunk of reader) {
1350
+ let buf = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
1351
+ let r = await dec(buf);
1352
+ if (r.channelData.length) acc.push(r.channelData, r.sampleRate);
1353
+ await yieldLoop();
1354
+ }
1355
+ } else {
1356
+ let FEED = 64 * 1024;
1357
+ for (let off = 0; off < bytes.length; off += FEED) {
1358
+ let r = await dec(bytes.subarray(off, Math.min(off + FEED, bytes.length)));
1359
+ if (r.channelData.length) acc.push(r.channelData, r.sampleRate);
1360
+ await yieldLoop();
1361
+ }
1362
+ }
1363
+ let flushed = await dec();
1364
+ if (flushed.channelData.length) acc.push(flushed.channelData, flushed.sampleRate);
1365
+ let final = acc.done();
1366
+ return final;
1367
+ } catch (e) {
1368
+ if (firstResolve) {
1369
+ let f = firstResolve;
1370
+ firstResolve = null;
1371
+ f();
1372
+ }
1373
+ ;
1374
+ throw e;
1375
+ }
1376
+ })();
1377
+ await firstReady;
1378
+ if (!acc.sampleRate) throw new Error("audio: decoded no audio data");
1379
+ return { pages: acc.pages, sampleRate: acc.sampleRate, channels: acc.channels, decoding, acc };
1380
+ }
1381
+
1382
+ // plan.js
1383
+ var fn2 = audio.fn;
1384
+ var ops = {};
1385
+ function seg(src, count, dst, rate, ref) {
1386
+ let s = [src, count, dst];
1387
+ if (rate != null && rate !== 1) s[3] = rate;
1388
+ if (ref !== void 0) s[4] = ref;
1389
+ return s;
1390
+ }
1391
+ function planOffset(offset, total, dflt = 0) {
1392
+ let s = offset ?? dflt;
1393
+ if (s < 0) s = total + s;
1394
+ return Math.min(Math.max(0, s), total);
1395
+ }
1396
+ function opRange(ctx, len) {
1397
+ let sr = ctx.sampleRate;
1398
+ let s = ctx.at != null ? Math.round(ctx.at * sr) : 0;
1399
+ return [s, ctx.duration != null ? s + Math.round(ctx.duration * sr) : len];
1400
+ }
1401
+ function isOpts(v) {
1402
+ return v != null && typeof v === "object" && !Array.isArray(v) && !ArrayBuffer.isView(v) && !v.pages && !v.getChannelData;
1403
+ }
1404
+ audio.op = function(name, arg1, arg2, arg3) {
1405
+ if (!arguments.length) return ops;
1406
+ if (arguments.length === 1) return ops[name];
1407
+ let desc;
1408
+ if (typeof arg1 !== "function") {
1409
+ desc = arg1;
1410
+ } else {
1411
+ let plan, opts;
1412
+ if (typeof arg2 === "function") {
1413
+ plan = arg2;
1414
+ opts = arg3;
1415
+ } else opts = arg2;
1416
+ desc = { process: arg1 };
1417
+ if (plan) desc.plan = plan;
1418
+ if (opts) Object.assign(desc, opts);
1419
+ }
1420
+ if (!fn2[name] && !desc.hidden) {
1421
+ let stdMethod = function(...a2) {
1422
+ let edit = { type: name, args: a2 }, last = a2[a2.length - 1];
1423
+ if (a2.length && isOpts(last)) {
1424
+ let { at, duration, channel, offset, length, ...extra } = last;
1425
+ edit.args = a2.slice(0, -1);
1426
+ if (at != null) edit.at = parseTime(at);
1427
+ if (duration != null) edit.duration = parseTime(duration);
1428
+ if (offset != null) edit.offset = offset;
1429
+ if (length != null) edit.length = length;
1430
+ if (channel != null) edit.channel = channel;
1431
+ Object.assign(edit, extra);
1432
+ }
1433
+ return this.run(edit);
1434
+ };
1435
+ fn2[name] = desc.call ? function(...a2) {
1436
+ return desc.call.call(this, stdMethod, ...a2);
1437
+ } : stdMethod;
1438
+ }
1439
+ ops[name] = desc;
1440
+ };
1441
+ function pushEdit(a2, edit) {
1442
+ a2.edits.push(edit);
1443
+ a2.version++;
1444
+ emit(a2, "change");
1445
+ }
1446
+ function popEdit(a2) {
1447
+ let e = a2.edits.pop();
1448
+ if (e) {
1449
+ a2.version++;
1450
+ emit(a2, "change");
1451
+ }
1452
+ return e;
1453
+ }
1454
+ Object.defineProperties(fn2, {
1455
+ length: { get() {
1456
+ if (this._.lenV === this.version) return this._.lenC;
1457
+ let len = this.edits.length ? buildPlan(this).totalLen : this._.len;
1458
+ this._.lenC = len;
1459
+ this._.lenV = this.version;
1460
+ return len;
1461
+ }, configurable: true },
1462
+ channels: { get() {
1463
+ if (this._.chV === this.version) return this._.chC;
1464
+ let ch = this._.ch;
1465
+ for (let edit of this.edits) {
1466
+ if (ops[edit.type]?.ch) ch = ops[edit.type].ch(ch, edit.args);
1467
+ }
1468
+ this._.chC = ch;
1469
+ this._.chV = this.version;
1470
+ return ch;
1471
+ }, configurable: true }
1472
+ });
1473
+ async function ensurePlan(a2, plan, offset, duration) {
1474
+ if (!audio.ensurePages) return;
1475
+ let { segs, sr } = plan;
1476
+ let s = Math.round((offset || 0) * sr);
1477
+ let e = duration != null ? s + Math.round(duration * sr) : plan.totalLen;
1478
+ for (let sg of segs) {
1479
+ let iStart = Math.max(s, sg[2]), iEnd = Math.min(e, sg[2] + sg[1]);
1480
+ if (iStart >= iEnd) continue;
1481
+ let absR = Math.abs(sg[3] || 1);
1482
+ let srcStart = sg[0] + (iStart - sg[2]) * absR;
1483
+ let srcLen = (iEnd - iStart) * absR + 1;
1484
+ let target = sg[4] === null ? null : sg[4] || a2;
1485
+ if (target) await audio.ensurePages(target, srcStart / sr, srcLen / sr);
1486
+ }
1487
+ }
1488
+ async function loadRefs(a2) {
1489
+ for (let { args } of a2.edits) if (args?.[0]?.pages) await args[0][LOAD]();
1490
+ }
1491
+ fn2[READ] = async function(offset, duration) {
1492
+ if (!this.edits.length) {
1493
+ if (audio.ensurePages) await audio.ensurePages(this, offset, duration);
1494
+ return readPages(this, offset, duration);
1495
+ }
1496
+ await this[LOAD]();
1497
+ await loadRefs(this);
1498
+ let plan = buildPlan(this);
1499
+ await ensurePlan(this, plan, offset, duration);
1500
+ return readPlan(this, plan, offset, duration);
1501
+ };
1502
+ fn2[Symbol.asyncIterator] = fn2.stream = async function* (opts) {
1503
+ let offset = parseTime(opts?.at), duration = parseTime(opts?.duration);
1504
+ if (this._.waiters && !this.decoded && !this.edits.length) {
1505
+ let sr = this.sampleRate, acc = this._.acc, PS = audio.PAGE_SIZE;
1506
+ let startSample = offset ? Math.round(offset * sr) : 0;
1507
+ let endSample = duration != null ? startSample + Math.round(duration * sr) : Infinity;
1508
+ let pos = startSample;
1509
+ while (pos < endSample) {
1510
+ let available = acc ? this.pages.length * PS + acc.partialLen : this._.len;
1511
+ while (pos >= available && !this.decoded) {
1512
+ await new Promise((r) => this._.waiters.push(r));
1513
+ available = acc ? this.pages.length * PS + acc.partialLen : this._.len;
1514
+ }
1515
+ if (pos >= available) break;
1516
+ let end = Math.min(endSample, available);
1517
+ let pi = Math.floor(pos / PS), po = pos % PS;
1518
+ if (pi < this.pages.length) {
1519
+ let page = this.pages[pi], e = Math.min(page[0].length - po, end - pos);
1520
+ yield page.map((ch) => ch.subarray(po, po + e));
1521
+ pos += e;
1522
+ } else if (acc) {
1523
+ let e = Math.min(acc.partialLen - po, end - pos);
1524
+ if (e > 0) {
1525
+ yield acc.partial.map((ch) => ch.subarray(po, po + e).slice());
1526
+ pos += e;
1527
+ }
1528
+ }
1529
+ }
1530
+ return;
1531
+ }
1532
+ await this.ready;
1533
+ await this[LOAD]();
1534
+ await loadRefs(this);
1535
+ let plan = buildPlan(this);
1536
+ let seen = /* @__PURE__ */ new Set();
1537
+ for (let s of plan.segs) if (s[4] && s[4] !== null && !seen.has(s[4])) {
1538
+ seen.add(s[4]);
1539
+ await s[4][LOAD]();
1540
+ }
1541
+ await ensurePlan(this, plan, offset, duration);
1542
+ for (let chunk of streamPlan(this, plan, offset, duration)) yield chunk;
1543
+ };
1544
+ fn2.undo = function(n = 1) {
1545
+ if (!this.edits.length) return n === 1 ? null : [];
1546
+ let removed = [];
1547
+ for (let i = 0; i < n && this.edits.length; i++) removed.push(popEdit(this));
1548
+ return n === 1 ? removed[0] : removed;
1549
+ };
1550
+ fn2.run = function(...edits) {
1551
+ let sr = this.sampleRate;
1552
+ for (let e of edits) {
1553
+ if (!e.type) throw new TypeError("audio.run: edit must have type");
1554
+ let edit = { ...e, args: e.args || [] };
1555
+ if (edit.at != null) edit.at = parseTime(edit.at);
1556
+ if (edit.duration != null) edit.duration = parseTime(edit.duration);
1557
+ if (edit.offset != null) {
1558
+ edit.at = edit.offset / sr;
1559
+ delete edit.offset;
1560
+ }
1561
+ if (edit.length != null) {
1562
+ edit.duration = edit.length / sr;
1563
+ delete edit.length;
1564
+ }
1565
+ pushEdit(this, edit);
1566
+ }
1567
+ return this;
1568
+ };
1569
+ fn2.toJSON = function() {
1570
+ let edits = this.edits.filter((e) => !e.args?.some((a2) => typeof a2 === "function"));
1571
+ return { source: this.source, edits, sampleRate: this.sampleRate, channels: this.channels, duration: this.duration };
1572
+ };
1573
+ fn2.clone = function() {
1574
+ let b = audio.from(this);
1575
+ for (let e of this.edits) pushEdit(b, { ...e });
1576
+ return b;
1577
+ };
1578
+ var MAX_FLAT_SIZE = 2 ** 29;
1579
+ function render(a2, offset, count) {
1580
+ if (Array.isArray(a2) && a2[0] instanceof Float32Array) {
1581
+ return offset != null ? a2.map((ch) => ch.subarray(offset, offset + count)) : a2;
1582
+ }
1583
+ if (a2?.getChannelData && !a2.pages) {
1584
+ let chs = Array.from({ length: a2.numberOfChannels }, (_, i) => new Float32Array(a2.getChannelData(i)));
1585
+ return offset != null ? chs.map((ch) => ch.subarray(offset, offset + count)) : chs;
1586
+ }
1587
+ if (offset != null) return readRange(a2, offset, count);
1588
+ if (a2._.pcm && a2._.pcmV === a2.version) return a2._.pcm;
1589
+ if (!a2.edits.length) {
1590
+ let r2 = readPages(a2);
1591
+ a2._.pcm = r2;
1592
+ a2._.pcmV = a2.version;
1593
+ return r2;
1594
+ }
1595
+ let plan = buildPlan(a2);
1596
+ let virtualLen = planLen(plan.segs);
1597
+ if (virtualLen > MAX_FLAT_SIZE) throw new Error(`Audio too large for flat render (${(virtualLen / 1e6).toFixed(0)}M samples). Use streaming.`);
1598
+ let r = readPlan(a2, plan);
1599
+ a2._.pcm = r;
1600
+ a2._.pcmV = a2.version;
1601
+ return r;
1602
+ }
1603
+ function planLen(segs) {
1604
+ let m2 = 0;
1605
+ for (let s of segs) m2 = Math.max(m2, s[2] + s[1]);
1606
+ return m2;
1607
+ }
1608
+ function buildPlan(a2) {
1609
+ if (a2._.plan && a2._.planV === a2.version) return a2._.plan;
1610
+ let sr = a2.sampleRate, ch = a2._.ch;
1611
+ let segs = [[0, a2._.len, 0]], pipeline = [];
1612
+ for (let edit of a2.edits) {
1613
+ let { type, args = [], at, duration, channel, ...extra } = edit;
1614
+ let op = ops[type];
1615
+ if (!op) throw new Error(`Unknown op: ${type}`);
1616
+ if (op.resolve) {
1617
+ let ctx = { ...extra, stats: a2._.srcStats || a2.stats, sampleRate: sr, channelCount: ch, channel, at, duration, totalDuration: planLen(segs) / sr };
1618
+ let resolved2 = op.resolve(args, ctx);
1619
+ if (resolved2 === false) continue;
1620
+ if (resolved2) {
1621
+ let edits = Array.isArray(resolved2) ? resolved2 : [resolved2];
1622
+ for (let r of edits) {
1623
+ if (channel != null && r.channel == null) r.channel = channel;
1624
+ if (at != null && r.at == null) r.at = at;
1625
+ if (duration != null && r.duration == null) r.duration = duration;
1626
+ let rOp = ops[r.type];
1627
+ if (rOp?.plan && typeof rOp.plan === "function") {
1628
+ let t = planLen(segs), rOffset = r.at != null ? Math.round(r.at * sr) : null, rLength = r.duration != null ? Math.round(r.duration * sr) : null;
1629
+ segs = rOp.plan(segs, { total: t, sampleRate: sr, args: r.args || [], offset: rOffset, length: rLength });
1630
+ } else {
1631
+ pipeline.push(r);
1632
+ }
1633
+ }
1634
+ continue;
1635
+ }
1636
+ }
1637
+ if (op.plan) {
1638
+ let t = planLen(segs), offset = at != null ? Math.round(at * sr) : null, length = duration != null ? Math.round(duration * sr) : null;
1639
+ segs = op.plan(segs, { total: t, sampleRate: sr, args, offset, length });
1640
+ } else {
1641
+ pipeline.push(edit);
1642
+ }
1643
+ }
1644
+ let plan = { segs, pipeline, totalLen: planLen(segs), sr };
1645
+ a2._.plan = plan;
1646
+ a2._.planV = a2.version;
1647
+ return plan;
1648
+ }
1649
+ var _rsBuf = null;
1650
+ var _rsLen = 0;
1651
+ function readSource(a2, c, srcOff, n, target, tOff, rate) {
1652
+ let r = rate || 1, absR = Math.abs(r);
1653
+ if (absR === 1) {
1654
+ if (r > 0) return copyPages(a2, c, srcOff, n, target, tOff);
1655
+ return walkPages(a2, c, srcOff, n, (pg, ch, s, e, off) => {
1656
+ for (let i = s; i < e; i++) target[tOff + (n - 1 - (off + i - s))] = pg[ch][i];
1657
+ });
1658
+ }
1659
+ let srcN = Math.ceil(n * absR) + 1;
1660
+ if (srcN > _rsLen) {
1661
+ _rsLen = srcN;
1662
+ _rsBuf = new Float32Array(srcN);
1663
+ }
1664
+ let buf = _rsBuf.subarray(0, srcN);
1665
+ buf.fill(0);
1666
+ copyPages(a2, c, srcOff, srcN, buf, 0);
1667
+ resample(buf, target, tOff, n, r);
1668
+ }
1669
+ function resample(src, target, tOff, n, rate) {
1670
+ let absR = Math.abs(rate), rev = rate < 0;
1671
+ for (let i = 0; i < n; i++) {
1672
+ let pos = (rev ? n - 1 - i : i) * absR;
1673
+ let idx = pos | 0, frac = pos - idx;
1674
+ target[tOff + i] = idx + 1 < src.length ? src[idx] + (src[idx + 1] - src[idx]) * frac : src[idx] || 0;
1675
+ }
1676
+ }
1677
+ function readRange(a2, srcStart, n) {
1678
+ if (!a2.edits.length) {
1679
+ return Array.from({ length: a2._.ch }, (_, c) => {
1680
+ let out = new Float32Array(n);
1681
+ copyPages(a2, c, srcStart, n, out, 0);
1682
+ return out;
1683
+ });
1684
+ }
1685
+ let plan = buildPlan(a2), sr = plan.sr;
1686
+ return readPlan(a2, plan, srcStart / sr, n / sr);
1687
+ }
1688
+ function* streamPlan(a2, plan, offset, duration) {
1689
+ let { segs, pipeline, totalLen, sr } = plan;
1690
+ let s = Math.round((offset || 0) * sr), e = duration != null ? s + Math.round(duration * sr) : totalLen;
1691
+ let totalDur = totalLen / sr;
1692
+ let procs = pipeline.map((ed) => {
1693
+ let m2 = ops[ed.type];
1694
+ let { type, args, at, duration: duration2, channel, ...extra } = ed;
1695
+ return {
1696
+ op: m2.process,
1697
+ at: at != null && at < 0 ? totalDur + at : at,
1698
+ dur: duration2,
1699
+ channel,
1700
+ ctx: { ...extra, args: args || [], duration: duration2, sampleRate: sr, totalDuration: totalDur, render }
1701
+ };
1702
+ });
1703
+ let WARMUP = 8;
1704
+ let ws = s > 0 && procs.length ? Math.max(0, s - audio.BLOCK_SIZE * WARMUP) : s;
1705
+ for (let outOff = ws; outOff < e; outOff += audio.BLOCK_SIZE) {
1706
+ let blockEnd = outOff < s ? s : e;
1707
+ let len = Math.min(audio.BLOCK_SIZE, blockEnd - outOff);
1708
+ let chunk = Array.from({ length: a2._.ch }, () => new Float32Array(len));
1709
+ for (let sg of segs) {
1710
+ let iStart = Math.max(outOff, sg[2]), iEnd = Math.min(outOff + len, sg[2] + sg[1]);
1711
+ if (iStart >= iEnd) continue;
1712
+ let rate = sg[3] || 1, ref = sg[4], absR = Math.abs(rate);
1713
+ let n = iEnd - iStart, dstOff = iStart - outOff;
1714
+ let srcStart = rate < 0 ? sg[0] + (sg[1] - (iStart - sg[2]) - n) * absR : sg[0] + (iStart - sg[2]) * absR;
1715
+ if (ref === null) {
1716
+ } else if (ref) {
1717
+ if (ref.edits.length === 0) {
1718
+ for (let c = 0; c < a2._.ch; c++)
1719
+ readSource(ref, c % ref._.ch, srcStart, n, chunk[c], dstOff, rate);
1720
+ } else {
1721
+ let srcN = Math.ceil(n * absR) + 1;
1722
+ let srcPcm = readRange(ref, srcStart, srcN);
1723
+ for (let c = 0; c < a2._.ch; c++) {
1724
+ let src = srcPcm[c % srcPcm.length];
1725
+ if (absR === 1) {
1726
+ if (rate < 0) {
1727
+ for (let i = 0; i < n; i++) chunk[c][dstOff + i] = src[n - 1 - i];
1728
+ } else chunk[c].set(src.subarray(0, n), dstOff);
1729
+ } else resample(src, chunk[c], dstOff, n, rate);
1730
+ }
1731
+ }
1732
+ } else {
1733
+ for (let c = 0; c < a2._.ch; c++) readSource(a2, c, srcStart, n, chunk[c], dstOff, rate);
1734
+ }
1735
+ }
1736
+ let blockOff = outOff / sr;
1737
+ for (let proc of procs) {
1738
+ let { op, at, channel, ctx } = proc;
1739
+ if (!op) continue;
1740
+ ctx.at = at != null ? at - blockOff : void 0;
1741
+ ctx.blockOffset = blockOff;
1742
+ if (channel != null) {
1743
+ let chs = typeof channel === "number" ? [channel] : channel;
1744
+ let sub = chs.map((c) => chunk[c]);
1745
+ let result = op(sub, ctx);
1746
+ if (result && result !== false) for (let i = 0; i < chs.length; i++) chunk[chs[i]] = result[i];
1747
+ } else {
1748
+ let result = op(chunk, ctx);
1749
+ if (result === false || result === null) continue;
1750
+ if (result) chunk = result;
1751
+ }
1752
+ }
1753
+ if (outOff >= s) yield chunk;
1754
+ }
1755
+ }
1756
+ function readPlan(a2, plan, offset, duration) {
1757
+ let chunks = [];
1758
+ for (let chunk of streamPlan(a2, plan, offset, duration)) chunks.push(chunk);
1759
+ if (!chunks.length) return Array.from({ length: a2.channels }, () => new Float32Array(0));
1760
+ let ch = chunks[0].length, totalLen = chunks.reduce((n, c) => n + c[0].length, 0);
1761
+ return Array.from({ length: ch }, (_, c) => {
1762
+ let out = new Float32Array(totalLen), pos = 0;
1763
+ for (let chunk of chunks) {
1764
+ out.set(chunk[c], pos);
1765
+ pos += chunk[0].length;
1766
+ }
1767
+ return out;
1768
+ });
1769
+ }
1770
+
1771
+ // cache.js
1772
+ var DEFAULT_BUDGET = 500 * 1024 * 1024;
1773
+ async function evict(a2) {
1774
+ if (!a2.cache || a2.budget === Infinity) return;
1775
+ let bytes = (p) => p ? p.reduce((s, ch) => s + ch.byteLength, 0) : 0;
1776
+ let current = a2.pages.reduce((sum, p) => sum + bytes(p), 0);
1777
+ if (current <= a2.budget) return;
1778
+ let order = a2._.lru && a2._.lru.size ? [...a2._.lru] : a2.pages.map((_, i) => i);
1779
+ for (let i of order) {
1780
+ if (current <= a2.budget) break;
1781
+ if (!a2.pages[i]) continue;
1782
+ await a2.cache.write(i, a2.pages[i]);
1783
+ current -= bytes(a2.pages[i]);
1784
+ a2.pages[i] = null;
1785
+ if (a2._.lru) a2._.lru.delete(i);
1786
+ }
1787
+ }
1788
+ async function ensurePages(a2, offset, duration) {
1789
+ if (!a2.cache) return;
1790
+ let PS = audio.PAGE_SIZE, sr = a2.sampleRate;
1791
+ let s = offset != null ? Math.max(0, Math.round(offset * sr)) : 0;
1792
+ let len = duration != null ? Math.round(duration * sr) : a2._.len - s;
1793
+ let p0 = Math.floor(s / PS), pEnd = Math.min(Math.ceil((s + len) / PS), a2.pages.length);
1794
+ for (let i = p0; i < pEnd; i++)
1795
+ if (a2.pages[i] === null && await a2.cache.has(i)) a2.pages[i] = await a2.cache.read(i);
1796
+ }
1797
+ async function opfsCache(dirName = "audio-cache") {
1798
+ if (typeof navigator === "undefined" || !navigator.storage?.getDirectory)
1799
+ throw new Error("OPFS not available in this environment");
1800
+ let root = await navigator.storage.getDirectory();
1801
+ let dir = await root.getDirectoryHandle(dirName, { create: true });
1802
+ return {
1803
+ async read(i) {
1804
+ let handle = await dir.getFileHandle(`p${i}`);
1805
+ let file = await handle.getFile();
1806
+ let buf = await file.arrayBuffer();
1807
+ let view = new Float32Array(buf);
1808
+ let ch = view[0] | 0, samplesPerCh = (view.length - 1) / ch | 0;
1809
+ let data = [];
1810
+ for (let c = 0; c < ch; c++) data.push(view.slice(1 + c * samplesPerCh, 1 + (c + 1) * samplesPerCh));
1811
+ return data;
1812
+ },
1813
+ async write(i, data) {
1814
+ let handle = await dir.getFileHandle(`p${i}`, { create: true });
1815
+ let writable = await handle.createWritable();
1816
+ let total = 1 + data.reduce((s, ch) => s + ch.length, 0);
1817
+ let packed = new Float32Array(total);
1818
+ packed[0] = data.length;
1819
+ let off = 1;
1820
+ for (let ch of data) {
1821
+ packed.set(ch, off);
1822
+ off += ch.length;
1823
+ }
1824
+ await writable.write(packed.buffer);
1825
+ await writable.close();
1826
+ },
1827
+ has(i) {
1828
+ return dir.getFileHandle(`p${i}`).then(() => true, () => false);
1829
+ },
1830
+ async evict(i) {
1831
+ try {
1832
+ await dir.removeEntry(`p${i}`);
1833
+ } catch {
1834
+ }
1835
+ },
1836
+ async clear() {
1837
+ for await (let [name] of dir) await dir.removeEntry(name);
1838
+ }
1839
+ };
1840
+ }
1841
+ audio.opfsCache = opfsCache;
1842
+ audio.evict = evict;
1843
+ audio.ensurePages = ensurePages;
1844
+ audio.DEFAULT_BUDGET = DEFAULT_BUDGET;
1845
+
1846
+ // stats.js
1847
+ var statDefs = {};
1848
+ audio.stat = function(name, desc) {
1849
+ if (!arguments.length) return statDefs;
1850
+ if (arguments.length === 1) return statDefs[name];
1851
+ if (typeof desc === "function") desc = { block: desc };
1852
+ statDefs[name] = desc;
1853
+ };
1854
+ function statSession(sr) {
1855
+ let fns, acc, ch, last = 0, rem = null, remLen = 0;
1856
+ function init2(c) {
1857
+ ch = c;
1858
+ fns = Object.entries(audio.stat()).filter(([_, d2]) => d2.block).map(([name, d2]) => ({ name, fn: d2.block, ctx: { sampleRate: sr } }));
1859
+ acc = /* @__PURE__ */ Object.create(null);
1860
+ for (let { name } of fns) acc[name] = Array.from({ length: ch }, () => []);
1861
+ }
1862
+ function processBlock(block) {
1863
+ for (let { name, fn: fn3, ctx } of fns) {
1864
+ let v = fn3(block, ctx);
1865
+ if (typeof v === "number") for (let c = 0; c < ch; c++) acc[name][c].push(v);
1866
+ else for (let c = 0; c < ch; c++) acc[name][c].push(v[c]);
1867
+ }
1868
+ }
1869
+ return {
1870
+ page(page) {
1871
+ if (!acc) init2(page.length);
1872
+ let BS = audio.BLOCK_SIZE, off = 0, len = page[0].length;
1873
+ if (remLen > 0) {
1874
+ let need = BS - remLen;
1875
+ if (len >= need) {
1876
+ for (let c = 0; c < ch; c++) rem[c].set(page[c].subarray(0, need), remLen);
1877
+ processBlock(rem);
1878
+ off = need;
1879
+ remLen = 0;
1880
+ } else {
1881
+ for (let c = 0; c < ch; c++) rem[c].set(page[c].subarray(0, len), remLen);
1882
+ remLen += len;
1883
+ return this;
1884
+ }
1885
+ }
1886
+ while (off + BS <= len) {
1887
+ processBlock(Array.from({ length: ch }, (_, c) => page[c].subarray(off, off + BS)));
1888
+ off += BS;
1889
+ }
1890
+ if (off < len) {
1891
+ if (!rem) rem = Array.from({ length: ch }, () => new Float32Array(BS));
1892
+ for (let c = 0; c < ch; c++) rem[c].set(page[c].subarray(off));
1893
+ remLen = len - off;
1894
+ }
1895
+ return this;
1896
+ },
1897
+ /** Flush any buffered partial block as a short final block. */
1898
+ flush() {
1899
+ if (remLen > 0) {
1900
+ processBlock(Array.from({ length: ch }, (_, c) => rem[c].subarray(0, remLen)));
1901
+ remLen = 0;
1902
+ }
1903
+ },
1904
+ delta() {
1905
+ if (!acc) return;
1906
+ let firstKey = Object.keys(acc)[0];
1907
+ if (!firstKey) return;
1908
+ let cur = acc[firstKey][0].length;
1909
+ if (cur <= last) return;
1910
+ let d2 = { fromBlock: last };
1911
+ for (let name in acc) d2[name] = acc[name].map((a2) => new Float32Array(a2.slice(last)));
1912
+ last = cur;
1913
+ return d2;
1914
+ },
1915
+ done() {
1916
+ this.flush();
1917
+ let out = { blockSize: audio.BLOCK_SIZE };
1918
+ if (acc) for (let name in acc) out[name] = acc[name].map((a2) => new Float32Array(a2));
1919
+ return out;
1920
+ }
1921
+ };
1922
+ }
1923
+ function binReduce(src, from, to, bins, reduce) {
1924
+ if (bins <= 0 || to <= from) return new Float32Array(Math.max(0, bins));
1925
+ from = Math.max(0, from);
1926
+ to = Math.min(to, src.length);
1927
+ if (to <= from) return new Float32Array(bins);
1928
+ let out = new Float32Array(bins), bpp = (to - from) / bins;
1929
+ for (let i = 0; i < bins; i++) {
1930
+ let a2 = from + Math.floor(i * bpp), b = Math.min(from + Math.floor((i + 1) * bpp), to);
1931
+ if (b <= a2) b = a2 + 1;
1932
+ out[i] = reduce(src, a2, b);
1933
+ }
1934
+ return out;
1935
+ }
1936
+ function remapStats(srcStats, plan, sr) {
1937
+ let bs = srcStats.blockSize, segs = plan.segs, totalLen = plan.totalLen;
1938
+ for (let s of segs) {
1939
+ let rate = s[3] || 1, ref = s[4];
1940
+ if (ref !== void 0 && ref !== null) return null;
1941
+ if (Math.abs(rate) !== 1) return null;
1942
+ if (s[0] % bs !== 0 || s[2] % bs !== 0) return null;
1943
+ }
1944
+ let outBlocks = Math.ceil(totalLen / bs);
1945
+ let fields = Object.keys(srcStats).filter((k) => k !== "blockSize" && Array.isArray(srcStats[k]));
1946
+ let ch = srcStats[fields[0]]?.length || 1;
1947
+ let out = { blockSize: bs };
1948
+ for (let f of fields) out[f] = Array.from({ length: ch }, () => new Float32Array(outBlocks));
1949
+ for (let s of segs) {
1950
+ let srcOff = s[0], count = s[1], dstOff = s[2], rate = s[3] || 1, ref = s[4];
1951
+ let dstBlockStart = Math.floor(dstOff / bs);
1952
+ let dstBlockEnd = Math.ceil((dstOff + count) / bs);
1953
+ if (ref === null) continue;
1954
+ let srcBlockStart = Math.floor(srcOff / bs);
1955
+ let srcBlocks = srcStats[fields[0]][0].length;
1956
+ let rev = rate < 0;
1957
+ for (let i = dstBlockStart; i < dstBlockEnd && i < outBlocks; i++) {
1958
+ let si = rev ? srcBlockStart + (dstBlockEnd - 1 - i) : srcBlockStart + (i - dstBlockStart);
1959
+ if (si < 0 || si >= srcBlocks) continue;
1960
+ for (let f of fields) for (let c = 0; c < ch; c++) out[f][c][i] = srcStats[f][c][si];
1961
+ }
1962
+ }
1963
+ return out;
1964
+ }
1965
+ audio.statSession = statSession;
1966
+ async function queryRange(inst, opts) {
1967
+ await inst[LOAD]();
1968
+ let at = parseTime(opts?.at), dur = parseTime(opts?.duration);
1969
+ let hasRange = at != null || dur != null;
1970
+ if (inst.edits?.length && inst._.statsV !== inst.version) {
1971
+ if (!inst._.srcStats) inst._.srcStats = inst.stats;
1972
+ if (hasRange) {
1973
+ let plan2 = buildPlan(inst);
1974
+ await ensurePlan(inst, plan2, at || 0, dur);
1975
+ let s = statSession(inst.sampleRate);
1976
+ for (let chunk of streamPlan(inst, plan2, at || 0, dur)) s.page(chunk);
1977
+ let stats = s.done();
1978
+ let first2 = Object.values(stats).find((v) => v?.[0]?.length);
1979
+ let blocks2 = first2?.[0]?.length || 0;
1980
+ return { stats, ch: inst.channels, sr: inst.sampleRate, from: 0, to: blocks2 };
1981
+ }
1982
+ let plan = buildPlan(inst);
1983
+ if (!plan.pipeline.length && inst._.srcStats?.blockSize) {
1984
+ let remapped = remapStats(inst._.srcStats, plan, inst.sampleRate);
1985
+ if (remapped) {
1986
+ inst.stats = remapped;
1987
+ inst._.statsV = inst.version;
1988
+ } else {
1989
+ let s = statSession(inst.sampleRate);
1990
+ await ensurePlan(inst, plan);
1991
+ for (let chunk of streamPlan(inst, plan)) s.page(chunk);
1992
+ inst.stats = s.done();
1993
+ inst._.statsV = inst.version;
1994
+ }
1995
+ } else {
1996
+ let s = statSession(inst.sampleRate);
1997
+ await ensurePlan(inst, plan);
1998
+ for (let chunk of streamPlan(inst, plan)) s.page(chunk);
1999
+ inst.stats = s.done();
2000
+ inst._.statsV = inst.version;
2001
+ }
2002
+ }
2003
+ let sr = inst.sampleRate, bs = inst.stats?.blockSize;
2004
+ if (!bs) return { stats: inst.stats, ch: inst.channels, sr, from: 0, to: 0 };
2005
+ let first = Object.values(inst.stats).find((v) => v?.[0]?.length);
2006
+ let blocks = first?.[0]?.length || 0;
2007
+ let atN = at != null && at < 0 ? inst.duration + at : at;
2008
+ let from = atN != null ? Math.floor(atN * sr / bs) : 0;
2009
+ let to = dur != null ? Math.ceil(((atN || 0) + dur) * sr / bs) : blocks;
2010
+ from = Math.max(0, Math.min(from, blocks));
2011
+ to = Math.max(from, Math.min(to, blocks));
2012
+ return { stats: inst.stats, ch: inst.channels, sr, from, to };
2013
+ }
2014
+ audio.fn.stat = async function(name, opts) {
2015
+ if (Array.isArray(name)) return Promise.all(name.map((n) => this.stat(n, opts)));
2016
+ if (typeof this[name] === "function" && !audio.stat(name)) return this[name](opts);
2017
+ let { stats, ch, sr, from, to } = await queryRange(this, opts);
2018
+ let bins = opts?.bins;
2019
+ let chSel = opts?.channel;
2020
+ let perCh = Array.isArray(chSel);
2021
+ let chs = chSel != null ? perCh ? chSel : [chSel] : Array.from({ length: ch }, (_, i) => i);
2022
+ let desc = audio.stat(name);
2023
+ if (desc?.query && bins == null) return desc.query(stats, chs, from, to, sr);
2024
+ let src = stats[name], reduce = desc?.reduce;
2025
+ if (!src) throw new Error(`Unknown stat: '${name}'`);
2026
+ if (!reduce) throw new Error(`No reducer for stat: '${name}'`);
2027
+ if (bins != null) {
2028
+ let n = bins ?? to - from;
2029
+ let reduce1 = (c) => binReduce(src[c], from, to, n, reduce);
2030
+ if (perCh) return chs.map(reduce1);
2031
+ if (chs.length === 1) return reduce1(chs[0]);
2032
+ let out = new Float32Array(n), bpp = (to - from) / n;
2033
+ for (let i = 0; i < n; i++) {
2034
+ let a2 = from + Math.floor(i * bpp), b = Math.min(from + Math.floor((i + 1) * bpp), to);
2035
+ if (b <= a2) b = a2 + 1;
2036
+ let sum = 0;
2037
+ for (let c of chs) sum += reduce(src[c], a2, b);
2038
+ out[i] = sum / chs.length;
2039
+ }
2040
+ return out;
2041
+ }
2042
+ if (perCh) return chs.map((c) => reduce(src[c], from, to));
2043
+ if (chs.length === 1) return reduce(src[chs[0]], from, to);
2044
+ let vals = chs.map((c) => reduce(src[c], from, to));
2045
+ return vals.reduce((a2, b) => a2 + b, 0) / vals.length;
2046
+ };
2047
+
2048
+ // fn/crop.js
2049
+ function cropSegs(segs, off, len) {
2050
+ let r = [], end = off + len;
2051
+ for (let s of segs) {
2052
+ let a2 = Math.max(s[2], off), b = Math.min(s[2] + s[1], end);
2053
+ if (a2 < b) r.push(seg(s[0] + (a2 - s[2]) * Math.abs(s[3] || 1), b - a2, a2 - off, s[3], s[4]));
2054
+ }
2055
+ return r;
2056
+ }
2057
+ var cropPlan = (segs, ctx) => {
2058
+ let { total, length } = ctx;
2059
+ let s = planOffset(ctx.offset, total);
2060
+ return cropSegs(segs, s, Math.max(0, Math.min(length ?? total - s, total - s)));
2061
+ };
2062
+ audio.op("crop", { plan: cropPlan });
2063
+
2064
+ // fn/clip.js
2065
+ audio.fn.clip = function(opts) {
2066
+ let inst = this.clone ? this.clone() : audio.from(this);
2067
+ let at = parseTime(opts?.at), duration = parseTime(opts?.duration);
2068
+ return at != null || duration != null ? inst.crop({ at: at ?? 0, duration: duration ?? Math.max(0, this.duration - (at ?? 0)) }) : inst;
2069
+ };
2070
+
2071
+ // fn/split.js
2072
+ audio.fn.split = function(...args) {
2073
+ let offsets = (Array.isArray(args[0]) ? args[0] : args).map(parseTime);
2074
+ let dur = this.duration;
2075
+ let cuts = [0, ...offsets.sort((a2, b) => a2 - b).filter((t) => t > 0 && t < dur), dur];
2076
+ return cuts.slice(0, -1).map((start, i) => this.clip({ at: start, duration: cuts[i + 1] - start }));
2077
+ };
2078
+
2079
+ // fn/play.js
2080
+ import Speaker from "audio-speaker";
2081
+ function ramp(buf, ch, len, fadeIn, RAMP) {
2082
+ let n = Math.min(RAMP, len);
2083
+ if (fadeIn) {
2084
+ for (let i = 0; i < n; i++) {
2085
+ let t = i / n;
2086
+ for (let c = 0; c < ch; c++) buf[i * ch + c] *= t;
2087
+ }
2088
+ } else {
2089
+ let s = len - n;
2090
+ for (let i = 0; i < n; i++) {
2091
+ let t = 1 - i / n;
2092
+ for (let c = 0; c < ch; c++) buf[(s + i) * ch + c] *= t;
2093
+ }
2094
+ }
2095
+ }
2096
+ audio.fn.play = function(opts) {
2097
+ let offset = opts?.at ?? 0, duration = opts?.duration;
2098
+ let a2 = this, BLOCK = audio.BLOCK_SIZE;
2099
+ if (a2.playing) {
2100
+ a2.playing = false;
2101
+ a2.paused = false;
2102
+ if (a2._._wake) a2._._wake();
2103
+ }
2104
+ a2.playing = false;
2105
+ a2.paused = opts?.paused ?? false;
2106
+ a2.currentTime = offset;
2107
+ if (opts?.volume != null) a2.volume = opts.volume;
2108
+ a2.loop = opts?.loop ?? false;
2109
+ a2.block = null;
2110
+ a2._._wake = null;
2111
+ a2._._seekTo = null;
2112
+ a2.ended = false;
2113
+ let startResolve, startReject;
2114
+ a2.played = new Promise((r, j) => {
2115
+ startResolve = r;
2116
+ startReject = j;
2117
+ });
2118
+ a2.played.catch(() => {
2119
+ });
2120
+ (async () => {
2121
+ try {
2122
+ let ch = a2.channels, sr = a2.sampleRate;
2123
+ a2.playing = true;
2124
+ if (!a2.paused) emit(a2, "play");
2125
+ let resolved2 = false;
2126
+ let wait = async () => {
2127
+ while (a2.paused && a2.playing && a2._._seekTo == null) await new Promise((r) => {
2128
+ a2._._wake = r;
2129
+ });
2130
+ a2._._wake = null;
2131
+ };
2132
+ let from = offset, RAMP = 256;
2133
+ while (a2.playing) {
2134
+ if (a2.paused) {
2135
+ await wait();
2136
+ if (!a2.playing) break;
2137
+ if (a2._._seekTo != null) {
2138
+ from = a2._._seekTo;
2139
+ a2._._seekTo = null;
2140
+ a2.currentTime = from;
2141
+ a2.seeking = false;
2142
+ }
2143
+ }
2144
+ let write2 = Speaker({ sampleRate: sr, channels: ch, bitDepth: 32 });
2145
+ let seeked = false, played = 0, fadeIn = true;
2146
+ const flush = async () => {
2147
+ let pad = new Uint8Array(BLOCK * ch * 4);
2148
+ await new Promise((r) => write2(pad, r));
2149
+ await new Promise((r) => write2(pad, r));
2150
+ };
2151
+ for await (let chunk of a2.stream({ at: from, duration })) {
2152
+ if (!a2.playing) break;
2153
+ let cLen = chunk[0].length;
2154
+ for (let bOff = 0; bOff < cLen; bOff += BLOCK) {
2155
+ if (a2._._seekTo != null) {
2156
+ from = a2._._seekTo;
2157
+ a2._._seekTo = null;
2158
+ a2.currentTime = from;
2159
+ a2.seeking = false;
2160
+ seeked = true;
2161
+ break;
2162
+ }
2163
+ let end = Math.min(bOff + BLOCK, cLen), len = end - bOff;
2164
+ a2.block = chunk[0].subarray(bOff, end);
2165
+ let g = a2.muted ? 0 : a2.volume;
2166
+ let buf = new Float32Array(len * ch);
2167
+ for (let i = 0; i < len; i++) for (let c = 0; c < ch; c++)
2168
+ buf[i * ch + c] = (chunk[c] || chunk[0])[bOff + i] * g;
2169
+ let send = () => new Promise((r) => write2(new Uint8Array(buf.buffer), r));
2170
+ if (fadeIn) {
2171
+ ramp(buf, ch, len, true, RAMP);
2172
+ fadeIn = false;
2173
+ }
2174
+ if (a2.paused) {
2175
+ ramp(buf, ch, len, false, RAMP);
2176
+ await send();
2177
+ await flush();
2178
+ played += len;
2179
+ a2.currentTime = from + played / sr;
2180
+ await wait();
2181
+ if (a2._._seekTo != null) continue;
2182
+ if (!a2.playing) break;
2183
+ fadeIn = true;
2184
+ continue;
2185
+ }
2186
+ if (!a2.playing) {
2187
+ ramp(buf, ch, len, false, RAMP);
2188
+ await send();
2189
+ break;
2190
+ }
2191
+ await send();
2192
+ if (!resolved2) {
2193
+ resolved2 = true;
2194
+ startResolve();
2195
+ }
2196
+ played += len;
2197
+ if (a2._._seekTo == null) {
2198
+ a2.currentTime = from + played / sr;
2199
+ emit(a2, "timeupdate", a2.currentTime);
2200
+ }
2201
+ }
2202
+ if (seeked || !a2.playing) break;
2203
+ }
2204
+ if (!seeked && !a2.playing) await flush();
2205
+ if (seeked) {
2206
+ await flush();
2207
+ fadeIn = true;
2208
+ }
2209
+ write2(null);
2210
+ if (seeked) continue;
2211
+ if (!a2.playing) break;
2212
+ if (a2.loop) {
2213
+ from = 0;
2214
+ a2.currentTime = 0;
2215
+ emit(a2, "timeupdate", 0);
2216
+ continue;
2217
+ }
2218
+ a2.playing = false;
2219
+ a2.ended = true;
2220
+ emit(a2, "timeupdate", a2.currentTime);
2221
+ break;
2222
+ }
2223
+ a2.playing = false;
2224
+ emit(a2, "ended");
2225
+ if (!resolved2) startResolve();
2226
+ } catch (err) {
2227
+ console.error("Playback error:", err);
2228
+ a2.playing = false;
2229
+ if (!resolved) startReject(err);
2230
+ else emit(a2, "error", err);
2231
+ }
2232
+ })();
2233
+ return this;
2234
+ };
2235
+ var proto = audio.fn;
2236
+ proto.pause = function() {
2237
+ if (!this.paused && this.playing) {
2238
+ this.paused = true;
2239
+ emit(this, "pause");
2240
+ }
2241
+ };
2242
+ proto.resume = function() {
2243
+ if (this.paused) {
2244
+ this._.ctStamp = performance.now();
2245
+ this.paused = false;
2246
+ emit(this, "play");
2247
+ if (this._._wake) this._._wake();
2248
+ }
2249
+ };
2250
+
2251
+ // fn/save.js
2252
+ var FMT_ALIAS = { aif: "aiff", oga: "ogg" };
2253
+ function resolveFormat(fmt3) {
2254
+ return FMT_ALIAS[fmt3] || fmt3 || "wav";
2255
+ }
2256
+ async function encodeStream(inst, fmt3, opts, sink) {
2257
+ let enc = await audio_encode_default[fmt3]({ sampleRate: inst.sampleRate, channels: inst.channels, ...opts.meta });
2258
+ let written = 0, tick = 0;
2259
+ for await (let chunk of inst.stream({ at: opts.at, duration: opts.duration })) {
2260
+ let buf = await enc(chunk);
2261
+ if (buf.length) await sink(buf);
2262
+ written += chunk[0].length;
2263
+ if (++tick % 2 === 0) await new Promise((r) => setTimeout(r, 0));
2264
+ emit(inst, "progress", { offset: written / inst.sampleRate, total: (opts.duration != null ? parseTime(opts.duration) : null) ?? inst.duration });
2265
+ }
2266
+ let final = await enc();
2267
+ if (final.length) await sink(final);
2268
+ return sink(null);
2269
+ }
2270
+ audio.fn.encode = async function(fmt3, opts = {}) {
2271
+ if (typeof fmt3 === "object") {
2272
+ opts = fmt3;
2273
+ fmt3 = void 0;
2274
+ }
2275
+ fmt3 = resolveFormat(fmt3);
2276
+ if (!audio_encode_default[fmt3]) throw new Error("Unknown format: " + fmt3);
2277
+ let parts = [];
2278
+ await encodeStream(this, fmt3, opts, (buf) => {
2279
+ if (buf) parts.push(buf);
2280
+ });
2281
+ let total = parts.reduce((n, p) => n + p.length, 0);
2282
+ let out = new Uint8Array(total), pos = 0;
2283
+ for (let p of parts) {
2284
+ out.set(p, pos);
2285
+ pos += p.length;
2286
+ }
2287
+ return out;
2288
+ };
2289
+ audio.fn.save = async function(target, opts = {}) {
2290
+ let fmt3 = opts.format ?? (typeof target === "string" ? target.split(".").pop() : "wav");
2291
+ fmt3 = resolveFormat(fmt3);
2292
+ if (!audio_encode_default[fmt3]) throw new Error("Unknown format: " + fmt3);
2293
+ let write2, finish;
2294
+ if (typeof target === "string") {
2295
+ let { createWriteStream } = await import("fs");
2296
+ let ws = createWriteStream(target);
2297
+ write2 = (buf) => {
2298
+ if (!ws.write(Buffer.from(buf))) return new Promise((r) => ws.once("drain", r));
2299
+ };
2300
+ finish = () => new Promise((res, rej) => {
2301
+ ws.on("finish", res);
2302
+ ws.on("error", rej);
2303
+ ws.end();
2304
+ });
2305
+ } else if (target?.write) {
2306
+ write2 = (buf) => target.write(buf);
2307
+ finish = () => target.close?.();
2308
+ } else throw new Error("Invalid save target");
2309
+ await encodeStream(this, fmt3, opts, (buf) => buf ? write2(buf) : finish?.());
2310
+ };
2311
+
2312
+ // fn/remove.js
2313
+ function removeSegs(segs, off, dur) {
2314
+ let r = [], end = off + dur;
2315
+ for (let s of segs) {
2316
+ let se = s[2] + s[1];
2317
+ if (se <= off) r.push(s);
2318
+ else if (s[2] >= end) {
2319
+ let n = s.slice();
2320
+ n[2] = s[2] - dur;
2321
+ r.push(n);
2322
+ } else {
2323
+ let absR = Math.abs(s[3] || 1);
2324
+ if (s[2] < off) r.push(seg(s[0], off - s[2], s[2], s[3], s[4]));
2325
+ if (se > end) r.push(seg(s[0] + (end - s[2]) * absR, se - end, off, s[3], s[4]));
2326
+ }
2327
+ }
2328
+ return r;
2329
+ }
2330
+ var removePlan = (segs, ctx) => {
2331
+ let { total } = ctx;
2332
+ let s = planOffset(ctx.offset, total);
2333
+ return removeSegs(segs, s, Math.min(ctx.length ?? total - s, total - s));
2334
+ };
2335
+ audio.op("remove", { plan: removePlan });
2336
+
2337
+ // fn/insert.js
2338
+ function insertSegs(segs, at, len, ref) {
2339
+ let r = [];
2340
+ for (let s of segs) {
2341
+ if (s[2] + s[1] <= at) r.push(s);
2342
+ else if (s[2] >= at) {
2343
+ let n = s.slice();
2344
+ n[2] = s[2] + len;
2345
+ r.push(n);
2346
+ } else {
2347
+ let f = at - s[2], absR = Math.abs(s[3] || 1);
2348
+ r.push(seg(s[0], f, s[2], s[3], s[4]));
2349
+ r.push(seg(s[0] + f * absR, s[1] - f, at + len, s[3], s[4]));
2350
+ }
2351
+ }
2352
+ r.push(seg(0, len, at, void 0, ref ?? null));
2353
+ r.sort((a2, b) => a2[2] - b[2]);
2354
+ return r;
2355
+ }
2356
+ var insertPlan = (segs, ctx) => {
2357
+ let { total, sampleRate: sr, args } = ctx;
2358
+ let source = args[0], off = planOffset(ctx.offset, total, total);
2359
+ if (typeof source !== "number" && !source?.pages) source = audio.from(source, { sampleRate: sr });
2360
+ let iLen = typeof source === "number" ? Math.round(source * sr) : source.length;
2361
+ if (ctx.length != null) iLen = Math.min(iLen, ctx.length);
2362
+ return insertSegs(segs, off, iLen, typeof source === "number" ? null : source);
2363
+ };
2364
+ audio.op("insert", { plan: insertPlan });
2365
+
2366
+ // fn/repeat.js
2367
+ function repeatSegs(segs, times, total, off, dur) {
2368
+ if (off == null) {
2369
+ let r2 = [];
2370
+ for (let t = 0; t <= times; t++)
2371
+ for (let s of segs) {
2372
+ let n = s.slice();
2373
+ n[2] = s[2] + total * t;
2374
+ r2.push(n);
2375
+ }
2376
+ return r2;
2377
+ }
2378
+ let segLen = dur ?? total - off, clip = cropSegs(segs, off, segLen), r = [];
2379
+ for (let s of segs) {
2380
+ let se = s[2] + s[1];
2381
+ if (se <= off + segLen) r.push(s);
2382
+ else if (s[2] >= off + segLen) {
2383
+ let n = s.slice();
2384
+ n[2] = s[2] + segLen * times;
2385
+ r.push(n);
2386
+ } else {
2387
+ let absR = Math.abs(s[3] || 1), split = off + segLen - s[2];
2388
+ r.push(seg(s[0], split, s[2], s[3], s[4]));
2389
+ r.push(seg(s[0] + split * absR, se - off - segLen, off + segLen * (times + 1), s[3], s[4]));
2390
+ }
2391
+ }
2392
+ for (let t = 1; t <= times; t++)
2393
+ for (let c of clip) {
2394
+ let n = c.slice();
2395
+ n[2] = off + segLen * t + c[2];
2396
+ r.push(n);
2397
+ }
2398
+ r.sort((a2, b) => a2[2] - b[2]);
2399
+ return r;
2400
+ }
2401
+ var repeatPlan = (segs, ctx) => {
2402
+ let { total, args, length } = ctx;
2403
+ let off = ctx.offset != null ? planOffset(ctx.offset, total) : null;
2404
+ return repeatSegs(segs, args[0] ?? 1, total, off, length);
2405
+ };
2406
+ audio.op("repeat", { plan: repeatPlan });
2407
+
2408
+ // fn/gain.js
2409
+ var gain = (chs, ctx) => {
2410
+ let lin = ctx.unit === "linear", val = ctx.args[0] ?? (lin ? 1 : 0);
2411
+ let [s, end] = opRange(ctx, chs[0].length);
2412
+ let auto = typeof val === "function", f = auto ? 0 : lin ? val : 10 ** (val / 20);
2413
+ let off = (ctx.blockOffset || 0) * ctx.sampleRate;
2414
+ let toMul = lin ? (v) => v : (v) => 10 ** (v / 20);
2415
+ for (let ch of chs)
2416
+ for (let i = Math.max(0, s); i < Math.min(end, ch.length); i++)
2417
+ ch[i] *= auto ? toMul(val((off + i) / ctx.sampleRate)) : f;
2418
+ return chs;
2419
+ };
2420
+ audio.op("gain", { process: gain });
2421
+
2422
+ // fn/fade.js
2423
+ var CURVES = {
2424
+ linear: (t) => t,
2425
+ exp: (t) => t * t,
2426
+ log: (t) => Math.sqrt(t),
2427
+ cos: (t) => (1 - Math.cos(t * Math.PI)) / 2
2428
+ };
2429
+ var fade = (chs, ctx) => {
2430
+ let dur = ctx.args[0];
2431
+ let fn3 = CURVES[ctx.curve] ?? CURVES.linear;
2432
+ let fadeIn = dur > 0, n = Math.abs(dur);
2433
+ let sr = ctx.sampleRate, blockOffset = ctx.blockOffset || 0;
2434
+ let at = ctx.at != null ? ctx.at + blockOffset : void 0;
2435
+ if (at != null && at < 0) at = ctx.totalDuration + at;
2436
+ let totalSamples = Math.round((ctx.totalDuration || chs[0].length / sr + blockOffset) * sr);
2437
+ let fadeStart = at != null ? Math.round(at * sr) : fadeIn ? 0 : totalSamples - Math.round(n * sr);
2438
+ let samples = Math.round(n * sr);
2439
+ let chunkStart = Math.round(blockOffset * sr);
2440
+ for (let ch of chs)
2441
+ for (let i = 0; i < ch.length; i++) {
2442
+ let fi = chunkStart + i - fadeStart;
2443
+ if (fi < 0 || fi >= samples) continue;
2444
+ ch[i] *= fn3(fadeIn ? fi / samples : 1 - fi / samples);
2445
+ }
2446
+ return chs;
2447
+ };
2448
+ audio.op("fade", {
2449
+ process: fade,
2450
+ call(std, ...a2) {
2451
+ let last = a2[a2.length - 1];
2452
+ let opts = typeof last === "object" ? a2.pop() : typeof last === "string" ? { curve: a2.pop() } : null;
2453
+ if (typeof a2[a2.length - 1] === "string") opts = { ...opts, curve: a2.pop() };
2454
+ let [inDur, outDur] = a2;
2455
+ if (outDur != null) {
2456
+ std.call(this, Math.abs(inDur), opts || {});
2457
+ return std.call(this, -Math.abs(outDur), opts || {});
2458
+ }
2459
+ return opts ? std.call(this, inDur, opts) : std.call(this, inDur);
2460
+ }
2461
+ });
2462
+
2463
+ // fn/reverse.js
2464
+ function reverseSegs(segs, off, end) {
2465
+ let r = [];
2466
+ for (let s of segs) {
2467
+ let se = s[2] + s[1];
2468
+ if (se <= off || s[2] >= end) {
2469
+ r.push(s);
2470
+ continue;
2471
+ }
2472
+ let absR = Math.abs(s[3] || 1);
2473
+ if (s[2] < off) r.push(seg(s[0], off - s[2], s[2], s[3], s[4]));
2474
+ let iStart = Math.max(s[2], off), iEnd = Math.min(se, end);
2475
+ r.push(seg(s[0] + (iStart - s[2]) * absR, iEnd - iStart, off + end - iEnd, -(s[3] || 1), s[4]));
2476
+ if (se > end) r.push(seg(s[0] + (end - s[2]) * absR, se - end, end, s[3], s[4]));
2477
+ }
2478
+ r.sort((a2, b) => a2[2] - b[2]);
2479
+ return r;
2480
+ }
2481
+ var reversePlan = (segs, ctx) => {
2482
+ let { total, length } = ctx;
2483
+ let s = planOffset(ctx.offset, total);
2484
+ return reverseSegs(segs, s, s + (length ?? total - s));
2485
+ };
2486
+ audio.op("reverse", { plan: reversePlan });
2487
+
2488
+ // fn/mix.js
2489
+ var mix = (chs, ctx) => {
2490
+ let source = ctx.args[0], sr = ctx.sampleRate, chLen = chs[0].length;
2491
+ if (typeof source === "number") throw new TypeError("mix: expected audio instance or Float32Array[], not a number");
2492
+ let sLen = Array.isArray(source) ? source[0].length : source.length;
2493
+ let [s] = opRange(ctx, chLen);
2494
+ let srcOff = Math.max(0, -s), dstOff = Math.max(0, s);
2495
+ let n = Math.min(sLen - srcOff, chLen - dstOff);
2496
+ if (ctx.duration != null) n = Math.min(n, Math.round(ctx.duration * sr) - srcOff);
2497
+ if (n <= 0) return chs;
2498
+ let src = ctx.render(source, srcOff, n);
2499
+ for (let c = 0; c < chs.length; c++) {
2500
+ let m2 = src[c % src.length];
2501
+ for (let i = 0; i < n; i++) chs[c][dstOff + i] += m2[i];
2502
+ }
2503
+ return chs;
2504
+ };
2505
+ audio.op("mix", { process: mix });
2506
+
2507
+ // fn/write.js
2508
+ var write = (chs, ctx) => {
2509
+ let data = ctx.args[0];
2510
+ let [p, end] = opRange(ctx, chs[0].length);
2511
+ let srcOff = Math.max(0, -p), dstOff = Math.max(0, p);
2512
+ for (let c = 0; c < chs.length; c++) {
2513
+ let s = Array.isArray(data) ? data[c] || data[0] : data;
2514
+ for (let i = srcOff; i < s.length && dstOff + i - srcOff < end; i++) chs[c][dstOff + i - srcOff] = s[i];
2515
+ }
2516
+ return chs;
2517
+ };
2518
+ audio.op("write", { process: write });
2519
+
2520
+ // fn/remix.js
2521
+ var remix = (chs, ctx) => {
2522
+ let arg = ctx.args[0], len = chs[0].length;
2523
+ if (Array.isArray(arg)) {
2524
+ return arg.map(
2525
+ (src) => src == null ? new Float32Array(len) : new Float32Array(chs[(src % chs.length + chs.length) % chs.length])
2526
+ );
2527
+ }
2528
+ let n = chs.length, m2 = arg;
2529
+ if (n === m2) return false;
2530
+ if (m2 < n) {
2531
+ let out = new Float32Array(len);
2532
+ for (let c = 0; c < n; c++)
2533
+ for (let i = 0; i < len; i++) out[i] += chs[c][i];
2534
+ let inv = 1 / n;
2535
+ for (let i = 0; i < len; i++) out[i] *= inv;
2536
+ return Array.from({ length: m2 }, () => new Float32Array(out));
2537
+ }
2538
+ return Array.from({ length: m2 }, (_, c) => new Float32Array(chs[c % n]));
2539
+ };
2540
+ var remixCh = (_, args) => Array.isArray(args[0]) ? args[0].length : args[0];
2541
+ audio.op("remix", { process: remix, ch: remixCh });
2542
+
2543
+ // fn/trim.js
2544
+ function autoThreshold(energies) {
2545
+ let vals = energies.filter((e) => e > 0);
2546
+ if (!vals.length) return -40;
2547
+ vals.sort((a2, b) => a2 - b);
2548
+ let floor = vals[Math.floor(vals.length * 0.1)];
2549
+ return Math.max(-80, Math.min(-20, 10 * Math.log10(floor) + 12));
2550
+ }
2551
+ function resolveThreshold(stats, ch, from, to, db) {
2552
+ if (db == null) {
2553
+ let energies = [];
2554
+ for (let c = 0; c < ch; c++) for (let i = from; i < to; i++) energies.push(stats.energy[c][i]);
2555
+ db = autoThreshold(energies);
2556
+ }
2557
+ return 10 ** (db / 20);
2558
+ }
2559
+ var isLoud = (stats, i, ch, thresh) => {
2560
+ for (let c = 0; c < ch; c++)
2561
+ if (Math.max(Math.abs(stats.min[c][i]), Math.abs(stats.max[c][i])) > thresh) return true;
2562
+ return false;
2563
+ };
2564
+ var trim = (chs, ctx) => {
2565
+ let threshold = ctx.args[0];
2566
+ if (threshold == null) {
2567
+ let energies = [];
2568
+ for (let c = 0; c < chs.length; c++)
2569
+ for (let off = 0; off < chs[c].length; off += audio.BLOCK_SIZE) {
2570
+ let end = Math.min(off + audio.BLOCK_SIZE, chs[c].length), sum = 0;
2571
+ for (let i = off; i < end; i++) sum += chs[c][i] * chs[c][i];
2572
+ energies.push(sum / (end - off));
2573
+ }
2574
+ threshold = autoThreshold(energies);
2575
+ }
2576
+ let thresh = 10 ** (threshold / 20);
2577
+ let len = chs[0].length, s = 0, e = len - 1;
2578
+ for (; s < len; s++) {
2579
+ let loud = false;
2580
+ for (let c = 0; c < chs.length; c++) if (Math.abs(chs[c][s]) > thresh) {
2581
+ loud = true;
2582
+ break;
2583
+ }
2584
+ ;
2585
+ if (loud) break;
2586
+ }
2587
+ for (; e >= s; e--) {
2588
+ let loud = false;
2589
+ for (let c = 0; c < chs.length; c++) if (Math.abs(chs[c][e]) > thresh) {
2590
+ loud = true;
2591
+ break;
2592
+ }
2593
+ ;
2594
+ if (loud) break;
2595
+ }
2596
+ e++;
2597
+ return s === 0 && e === len ? false : chs.map((ch) => ch.slice(s, e));
2598
+ };
2599
+ var trimResolve = (args, { stats, sampleRate: sampleRate2, totalDuration }) => {
2600
+ if (!stats?.min || !stats?.energy) return null;
2601
+ let ch = stats.min.length, blocks = stats.min[0].length;
2602
+ let total = Math.round(totalDuration * sampleRate2);
2603
+ let thresh = resolveThreshold(stats, ch, 0, stats.energy[0].length, args[0]);
2604
+ let s = 0, e = blocks - 1;
2605
+ for (; s < blocks; s++) if (isLoud(stats, s, ch, thresh)) break;
2606
+ for (; e >= s; e--) if (isLoud(stats, e, ch, thresh)) break;
2607
+ e++;
2608
+ if (s === 0 && e === blocks) return false;
2609
+ if (s >= e) return { type: "crop", args: [], at: 0, duration: 0 };
2610
+ let startSample = s * audio.BLOCK_SIZE;
2611
+ let endSample = Math.min(e * audio.BLOCK_SIZE, total);
2612
+ return { type: "crop", args: [], at: startSample / sampleRate2, duration: (endSample - startSample) / sampleRate2 };
2613
+ };
2614
+ audio.op("trim", { process: trim, resolve: trimResolve });
2615
+
2616
+ // node_modules/digital-filter/core/filter.js
2617
+ function filter(data, params) {
2618
+ let coefs2 = params.coefs;
2619
+ if (!Array.isArray(coefs2)) coefs2 = [coefs2];
2620
+ let n = coefs2.length;
2621
+ if (!params.state) {
2622
+ params.state = new Array(n);
2623
+ for (let i = 0; i < n; i++) params.state[i] = [0, 0];
2624
+ }
2625
+ let state = params.state;
2626
+ for (let i = 0, l = data.length; i < l; i++) {
2627
+ let x = data[i];
2628
+ for (let j = 0; j < n; j++) {
2629
+ let c = coefs2[j], s = state[j];
2630
+ let y2 = c.b0 * x + s[0];
2631
+ s[0] = c.b1 * x - c.a1 * y2 + s[1];
2632
+ s[1] = c.b2 * x - c.a2 * y2;
2633
+ x = y2;
2634
+ }
2635
+ data[i] = x;
2636
+ }
2637
+ return data;
2638
+ }
2639
+
2640
+ // node_modules/digital-filter/iir/biquad.js
2641
+ var { sin, cos, sqrt, pow, PI } = Math;
2642
+ var SILENCE = { b0: 0, b1: 0, b2: 0, a1: 0, a2: 0 };
2643
+ var PASS = { b0: 1, b1: 0, b2: 0, a1: 0, a2: 0 };
2644
+ var gain2 = (A2) => ({ b0: A2, b1: 0, b2: 0, a1: 0, a2: 0 });
2645
+ function norm3(b0, b1, b2, a0, a1, a2) {
2646
+ return { b0: b0 / a0, b1: b1 / a0, b2: b2 / a0, a1: a1 / a0, a2: a2 / a0 };
2647
+ }
2648
+ function intermediates(fc, Q, fs) {
2649
+ let w0 = 2 * PI * fc / fs;
2650
+ let sinw = sin(w0), cosw = cos(w0);
2651
+ let alpha = sinw / (2 * Q);
2652
+ return { sinw, cosw, alpha };
2653
+ }
2654
+ function lowpass(fc, Q, fs) {
2655
+ if (fc <= 0) return SILENCE;
2656
+ if (fc >= fs / 2) return PASS;
2657
+ let { cosw, alpha } = intermediates(fc, Q, fs);
2658
+ return norm3(
2659
+ (1 - cosw) / 2,
2660
+ 1 - cosw,
2661
+ (1 - cosw) / 2,
2662
+ 1 + alpha,
2663
+ -2 * cosw,
2664
+ 1 - alpha
2665
+ );
2666
+ }
2667
+ function highpass(fc, Q, fs) {
2668
+ if (fc <= 0) return PASS;
2669
+ if (fc >= fs / 2) return SILENCE;
2670
+ let { cosw, alpha } = intermediates(fc, Q, fs);
2671
+ return norm3(
2672
+ (1 + cosw) / 2,
2673
+ -(1 + cosw),
2674
+ (1 + cosw) / 2,
2675
+ 1 + alpha,
2676
+ -2 * cosw,
2677
+ 1 - alpha
2678
+ );
2679
+ }
2680
+ function bandpass(fc, Q, fs) {
2681
+ if (fc <= 0 || fc >= fs / 2) return SILENCE;
2682
+ if (Q <= 0) return SILENCE;
2683
+ let { sinw, cosw, alpha } = intermediates(fc, Q, fs);
2684
+ return norm3(
2685
+ sinw / 2,
2686
+ 0,
2687
+ -sinw / 2,
2688
+ 1 + alpha,
2689
+ -2 * cosw,
2690
+ 1 - alpha
2691
+ );
2692
+ }
2693
+ function notch(fc, Q, fs) {
2694
+ if (fc <= 0 || fc >= fs / 2) return PASS;
2695
+ if (Q <= 0) return SILENCE;
2696
+ let { cosw, alpha } = intermediates(fc, Q, fs);
2697
+ return norm3(
2698
+ 1,
2699
+ -2 * cosw,
2700
+ 1,
2701
+ 1 + alpha,
2702
+ -2 * cosw,
2703
+ 1 - alpha
2704
+ );
2705
+ }
2706
+ function peaking(fc, Q, fs, dBgain) {
2707
+ if (fc <= 0 || fc >= fs / 2) return PASS;
2708
+ if (Q <= 0) return gain2(pow(10, dBgain / 20));
2709
+ let { cosw, alpha } = intermediates(fc, Q, fs);
2710
+ let A = pow(10, dBgain / 40);
2711
+ return norm3(
2712
+ 1 + alpha * A,
2713
+ -2 * cosw,
2714
+ 1 - alpha * A,
2715
+ 1 + alpha / A,
2716
+ -2 * cosw,
2717
+ 1 - alpha / A
2718
+ );
2719
+ }
2720
+ function lowshelf(fc, Q, fs, dBgain) {
2721
+ let A = pow(10, dBgain / 40);
2722
+ if (fc <= 0) return PASS;
2723
+ if (fc >= fs / 2) return gain2(A * A);
2724
+ let { cosw, alpha } = intermediates(fc, Q, fs);
2725
+ let s = 2 * sqrt(A) * alpha;
2726
+ return norm3(
2727
+ A * (A + 1 - (A - 1) * cosw + s),
2728
+ 2 * A * (A - 1 - (A + 1) * cosw),
2729
+ A * (A + 1 - (A - 1) * cosw - s),
2730
+ A + 1 + (A - 1) * cosw + s,
2731
+ -2 * (A - 1 + (A + 1) * cosw),
2732
+ A + 1 + (A - 1) * cosw - s
2733
+ );
2734
+ }
2735
+ function highshelf(fc, Q, fs, dBgain) {
2736
+ let A = pow(10, dBgain / 40);
2737
+ if (fc <= 0) return gain2(A * A);
2738
+ if (fc >= fs / 2) return PASS;
2739
+ let { cosw, alpha } = intermediates(fc, Q, fs);
2740
+ let s = 2 * sqrt(A) * alpha;
2741
+ return norm3(
2742
+ A * (A + 1 + (A - 1) * cosw + s),
2743
+ -2 * A * (A - 1 + (A + 1) * cosw),
2744
+ A * (A + 1 + (A - 1) * cosw - s),
2745
+ A + 1 - (A - 1) * cosw + s,
2746
+ 2 * (A - 1 - (A + 1) * cosw),
2747
+ A + 1 - (A - 1) * cosw - s
2748
+ );
2749
+ }
2750
+
2751
+ // node_modules/audio-filter/weighting/k-weighting.js
2752
+ function kWeighting(data, params = {}) {
2753
+ let fs = params.fs || 48e3;
2754
+ if (!params._sos || params._fs !== fs) {
2755
+ params._fs = fs;
2756
+ params._sos = kWeighting.coefs(fs);
2757
+ }
2758
+ if (!params.state) params.state = params._sos.map(() => [0, 0]);
2759
+ return filter(data, { coefs: params._sos, state: params.state });
2760
+ }
2761
+ kWeighting.coefs = function coefs(fs = 48e3) {
2762
+ if (fs === 48e3) return [
2763
+ { b0: 1.53512485958697, b1: -2.69169618940638, b2: 1.19839281085285, a1: -1.69065929318241, a2: 0.73248077421585 },
2764
+ { b0: 1, b1: -2, b2: 1, a1: -1.99004745483398, a2: 0.99007225036621 }
2765
+ ];
2766
+ return [
2767
+ highshelf(1681, 0.7072, fs, 3.9997),
2768
+ highpass(38, 0.7072, fs)
2769
+ ];
2770
+ };
2771
+
2772
+ // fn/loudness.js
2773
+ var GATE_WINDOW = 0.4;
2774
+ var ABS_GATE = -70;
2775
+ var REL_GATE = -10;
2776
+ var LUFS_OFFSET = -0.691;
2777
+ function lufsFromEnergy(energy, chs, sampleRate2, blockSize, from = 0, to) {
2778
+ if (to == null) to = energy[0].length;
2779
+ if (typeof chs === "number") chs = Array.from({ length: chs }, (_, i) => i);
2780
+ let winBlocks = Math.ceil(GATE_WINDOW * sampleRate2 / blockSize), gates = [];
2781
+ for (let i = from; i < to; i += winBlocks) {
2782
+ let we = Math.min(i + winBlocks, to), sum = 0, n = 0;
2783
+ for (let c of chs) for (let j = i; j < we; j++) {
2784
+ sum += energy[c][j];
2785
+ n++;
2786
+ }
2787
+ if (n > 0) gates.push(sum / n);
2788
+ }
2789
+ let absT = 10 ** (ABS_GATE / 10), gated = gates.filter((g) => g > absT);
2790
+ if (!gated.length) return null;
2791
+ let mean = gated.reduce((a2, b) => a2 + b, 0) / gated.length;
2792
+ let final = gated.filter((g) => g > mean * 10 ** (REL_GATE / 10));
2793
+ if (!final.length) return null;
2794
+ return LUFS_OFFSET + 10 * Math.log10(final.reduce((a2, b) => a2 + b, 0) / final.length);
2795
+ }
2796
+ function dcOffsets(stats, chs) {
2797
+ let off = new Float64Array(stats.dc.length);
2798
+ for (let c of chs) {
2799
+ let n = stats.dc[c].length;
2800
+ if (!n) {
2801
+ off[c] = 0;
2802
+ continue;
2803
+ }
2804
+ let sum = 0;
2805
+ for (let i = 0; i < n; i++) sum += stats.dc[c][i];
2806
+ off[c] = sum / n;
2807
+ }
2808
+ return off;
2809
+ }
2810
+ function peakDb(stats, chs, dcOff) {
2811
+ let peak = 0;
2812
+ for (let c of chs) {
2813
+ let d2 = dcOff?.[c] || 0;
2814
+ for (let i = 0; i < stats.min[c].length; i++)
2815
+ peak = Math.max(peak, Math.abs(stats.min[c][i] - d2), Math.abs(stats.max[c][i] - d2));
2816
+ }
2817
+ return peak ? 20 * Math.log10(peak) : null;
2818
+ }
2819
+ function rmsDb(stats, chs, dcOff) {
2820
+ if (!stats.rms) return null;
2821
+ let totalE = 0, n = 0;
2822
+ for (let c of chs) {
2823
+ let d2 = dcOff?.[c] || 0;
2824
+ for (let i = 0; i < stats.rms[c].length; i++) {
2825
+ totalE += stats.rms[c][i] - d2 * d2;
2826
+ n++;
2827
+ }
2828
+ }
2829
+ return n && totalE > 0 ? 10 * Math.log10(totalE / n) : null;
2830
+ }
2831
+ function lufsDb(stats, chs, sampleRate2) {
2832
+ return lufsFromEnergy(stats.energy, chs, sampleRate2, stats.blockSize) ?? null;
2833
+ }
2834
+ var rMean = (src, from, to) => {
2835
+ let n = to - from;
2836
+ if (!n) return 0;
2837
+ let v = 0;
2838
+ for (let i = from; i < to; i++) v += src[i];
2839
+ return v / n;
2840
+ };
2841
+ audio.stat("energy", {
2842
+ block: (chs, ctx) => {
2843
+ if (!ctx.k) ctx.k = chs.map(() => ({ fs: ctx.sampleRate }));
2844
+ return chs.map((ch, c) => {
2845
+ let k = new Float32Array(ch);
2846
+ kWeighting(k, ctx.k[c]);
2847
+ let sum = 0;
2848
+ for (let i = 0; i < k.length; i++) sum += k[i] * k[i];
2849
+ return sum / k.length;
2850
+ });
2851
+ },
2852
+ reduce: rMean
2853
+ });
2854
+ audio.stat("db", {
2855
+ query: (stats, chs, from, to) => {
2856
+ let peak = 0;
2857
+ for (let c of chs)
2858
+ for (let i = from; i < Math.min(to, stats.min[c].length); i++)
2859
+ peak = Math.max(peak, Math.abs(stats.min[c][i]), Math.abs(stats.max[c][i]));
2860
+ return peak > 0 ? 20 * Math.log10(peak) : -Infinity;
2861
+ }
2862
+ });
2863
+ audio.stat("loudness", {
2864
+ query: (stats, chs, from, to, sr) => {
2865
+ let v = lufsFromEnergy(stats.energy, chs, sr, stats.blockSize, from, to);
2866
+ return v ?? -Infinity;
2867
+ }
2868
+ });
2869
+
2870
+ // fn/normalize.js
2871
+ var PRESETS = { streaming: -14, podcast: -16, broadcast: -23 };
2872
+ audio.op("dc", {
2873
+ hidden: true,
2874
+ process: (chs, ctx) => {
2875
+ let offsets = ctx.args[0];
2876
+ if (typeof offsets === "number") offsets = [offsets];
2877
+ for (let c = 0; c < chs.length; c++) {
2878
+ let d2 = offsets[c % offsets.length] || 0;
2879
+ if (Math.abs(d2) < 1e-10) continue;
2880
+ for (let i = 0; i < chs[c].length; i++) chs[c][i] -= d2;
2881
+ }
2882
+ return chs;
2883
+ }
2884
+ });
2885
+ audio.op("clamp", {
2886
+ hidden: true,
2887
+ process: (chs, ctx) => {
2888
+ let limit = ctx.args[0];
2889
+ for (let c = 0; c < chs.length; c++)
2890
+ for (let i = 0; i < chs[c].length; i++)
2891
+ chs[c][i] = Math.max(-limit, Math.min(limit, chs[c][i]));
2892
+ return chs;
2893
+ }
2894
+ });
2895
+ audio.op("normalize", {
2896
+ process: () => false,
2897
+ resolve: (args, ctx) => {
2898
+ let { stats, sampleRate: sampleRate2 } = ctx;
2899
+ if (!stats?.min) return null;
2900
+ let arg = args[0];
2901
+ let mode = typeof arg === "string" ? "lufs" : ctx.mode || "peak";
2902
+ let targetDb = PRESETS[arg] ?? (typeof arg === "number" ? arg : ctx.target ?? 0);
2903
+ let totalCh = stats.min.length;
2904
+ let chs = ctx.channel != null ? Array.isArray(ctx.channel) ? ctx.channel : [ctx.channel] : Array.from({ length: totalCh }, (_, i) => i);
2905
+ let dcOff = new Float64Array(totalCh);
2906
+ if (ctx.dc !== false && stats.dc) dcOff = dcOffsets(stats, chs);
2907
+ let hasDc = chs.some((c) => Math.abs(dcOff[c]) > 1e-10);
2908
+ let levelDb;
2909
+ if (mode === "lufs") levelDb = lufsDb(stats, chs, sampleRate2);
2910
+ else if (mode === "rms") levelDb = rmsDb(stats, chs, dcOff);
2911
+ else levelDb = peakDb(stats, chs, dcOff);
2912
+ if (levelDb == null) return false;
2913
+ let edits = [];
2914
+ if (hasDc) edits.push({ type: "dc", args: [chs.map((c) => dcOff[c])] });
2915
+ if (ctx.ceiling != null) {
2916
+ let peakLevel = peakDb(stats, chs, dcOff);
2917
+ if (peakLevel == null) return false;
2918
+ edits.push({ type: "gain", args: [targetDb - peakLevel] });
2919
+ edits.push({ type: "clamp", args: [10 ** (ctx.ceiling / 20)] });
2920
+ } else {
2921
+ edits.push({ type: "gain", args: [targetDb - levelDb] });
2922
+ }
2923
+ return edits.length === 1 ? edits[0] : edits;
2924
+ },
2925
+ call(std, arg) {
2926
+ if (typeof arg === "string" || typeof arg === "number") return std.call(this, arg);
2927
+ if (arg != null && typeof arg === "object") {
2928
+ let { target, mode, at, duration, channel, ...extra } = arg;
2929
+ return std.call(this, target, { mode, at, duration, channel, ...extra });
2930
+ }
2931
+ return std.call(this);
2932
+ }
2933
+ });
2934
+
2935
+ // node_modules/audio-filter/effect/highpass.js
2936
+ var butterworth;
2937
+ function highpass2(data, params) {
2938
+ let fc = params.fc, fs = params.fs || 44100;
2939
+ let order = params.order || 2, Q = params.Q == null ? 0.707 : params.Q;
2940
+ if (!params.coefs || params._fc !== fc || params._order !== order || params._Q !== Q || params._fs !== fs) {
2941
+ if (order <= 2) params.coefs = [highpass(fc, Q, fs)];
2942
+ else {
2943
+ if (!butterworth) throw new Error("Import digital-filter/iir/butterworth.js for order > 2");
2944
+ params.coefs = butterworth(order, fc, fs, "highpass");
2945
+ }
2946
+ params._fc = fc;
2947
+ params._order = order;
2948
+ params._Q = Q;
2949
+ params._fs = fs;
2950
+ }
2951
+ return filter(data, params);
2952
+ }
2953
+ highpass2.useButterworth = (bw) => {
2954
+ butterworth = bw;
2955
+ };
2956
+
2957
+ // node_modules/audio-filter/effect/lowpass.js
2958
+ var butterworth2;
2959
+ function lowpass2(data, params) {
2960
+ let fc = params.fc, fs = params.fs || 44100;
2961
+ let order = params.order || 2, Q = params.Q == null ? 0.707 : params.Q;
2962
+ if (!params.coefs || params._fc !== fc || params._order !== order || params._Q !== Q || params._fs !== fs) {
2963
+ if (order <= 2) params.coefs = [lowpass(fc, Q, fs)];
2964
+ else {
2965
+ if (!butterworth2) throw new Error("Import digital-filter/iir/butterworth.js for order > 2");
2966
+ params.coefs = butterworth2(order, fc, fs, "lowpass");
2967
+ }
2968
+ params._fc = fc;
2969
+ params._order = order;
2970
+ params._Q = Q;
2971
+ params._fs = fs;
2972
+ }
2973
+ return filter(data, params);
2974
+ }
2975
+ lowpass2.useButterworth = (bw) => {
2976
+ butterworth2 = bw;
2977
+ };
2978
+
2979
+ // node_modules/audio-filter/effect/bandpass.js
2980
+ function bandpass2(data, params) {
2981
+ let fc = params.fc, Q = params.Q == null ? 0.707 : params.Q, fs = params.fs || 44100;
2982
+ if (!params.coefs || params._fc !== fc || params._Q !== Q || params._fs !== fs) {
2983
+ params.coefs = [bandpass(fc, Q, fs)];
2984
+ params._fc = fc;
2985
+ params._Q = Q;
2986
+ params._fs = fs;
2987
+ }
2988
+ return filter(data, params);
2989
+ }
2990
+
2991
+ // node_modules/audio-filter/effect/notch.js
2992
+ function notch2(data, params) {
2993
+ let fc = params.fc, Q = params.Q == null ? 30 : params.Q, fs = params.fs || 44100;
2994
+ if (!params.coefs || params._fc !== fc || params._Q !== Q || params._fs !== fs) {
2995
+ params.coefs = [notch(fc, Q, fs)];
2996
+ params._fc = fc;
2997
+ params._Q = Q;
2998
+ params._fs = fs;
2999
+ }
3000
+ return filter(data, params);
3001
+ }
3002
+
3003
+ // node_modules/audio-filter/eq/lowshelf.js
3004
+ function lowShelf(data, params) {
3005
+ let fc = params.fc || 200, gain3 = params.gain || 0;
3006
+ let Q = params.Q == null ? 0.707 : params.Q, fs = params.fs || 44100;
3007
+ if (!params._lo || params._fc !== fc || params._gain !== gain3 || params._Q !== Q || params._fs !== fs) {
3008
+ params._lo = { coefs: [lowshelf(fc, Q, fs, gain3)] };
3009
+ params._fc = fc;
3010
+ params._gain = gain3;
3011
+ params._Q = Q;
3012
+ params._fs = fs;
3013
+ }
3014
+ return filter(data, params._lo);
3015
+ }
3016
+
3017
+ // node_modules/audio-filter/eq/highshelf.js
3018
+ function highShelf(data, params) {
3019
+ let fc = params.fc || 4e3, gain3 = params.gain || 0;
3020
+ let Q = params.Q == null ? 0.707 : params.Q, fs = params.fs || 44100;
3021
+ if (!params._hi || params._fc !== fc || params._gain !== gain3 || params._Q !== Q || params._fs !== fs) {
3022
+ params._hi = { coefs: [highshelf(fc, Q, fs, gain3)] };
3023
+ params._fc = fc;
3024
+ params._gain = gain3;
3025
+ params._Q = Q;
3026
+ params._fs = fs;
3027
+ }
3028
+ return filter(data, params._hi);
3029
+ }
3030
+
3031
+ // node_modules/audio-filter/eq/parametric-eq.js
3032
+ function parametricEq(data, params) {
3033
+ let fs = params.fs || 44100;
3034
+ let bands = params.bands || [];
3035
+ if (!params._filters || params._dirty) {
3036
+ params._filters = bands.map((b) => {
3037
+ let fn3 = b.type === "lowshelf" ? lowshelf : b.type === "highshelf" ? highshelf : peaking;
3038
+ return { coefs: fn3(b.fc, b.Q || 1, fs, b.gain || 0) };
3039
+ });
3040
+ params._dirty = false;
3041
+ }
3042
+ for (let f of params._filters) filter(data, f);
3043
+ return data;
3044
+ }
3045
+
3046
+ // fn/filter.js
3047
+ function apply(chs, ctx, key, fn3, makeParams) {
3048
+ if (!ctx[key]) ctx[key] = chs.map(() => makeParams(ctx.sampleRate));
3049
+ let st = ctx[key];
3050
+ for (let c = 0; c < chs.length; c++) fn3(chs[c], st[c]);
3051
+ return chs;
3052
+ }
3053
+ var types = {
3054
+ highpass: (chs, ctx, args) => apply(chs, ctx, "_hp", highpass2, (fs) => ({ fc: args[0], fs })),
3055
+ lowpass: (chs, ctx, args) => apply(chs, ctx, "_lp", lowpass2, (fs) => ({ fc: args[0], fs })),
3056
+ eq: (chs, ctx, args) => apply(chs, ctx, "_eq", parametricEq, (fs) => ({ bands: [{ fc: args[0], Q: args[2] ?? 1, gain: args[1] ?? 0, type: "peak" }], fs })),
3057
+ lowshelf: (chs, ctx, args) => apply(chs, ctx, "_ls", lowShelf, (fs) => ({ fc: args[0], gain: args[1] ?? 0, Q: args[2] ?? 0.707, fs })),
3058
+ highshelf: (chs, ctx, args) => apply(chs, ctx, "_hs", highShelf, (fs) => ({ fc: args[0], gain: args[1] ?? 0, Q: args[2] ?? 0.707, fs })),
3059
+ notch: (chs, ctx, args) => apply(chs, ctx, "_notch", notch2, (fs) => ({ fc: args[0], Q: args[1] ?? 30, fs })),
3060
+ bandpass: (chs, ctx, args) => apply(chs, ctx, "_bp", bandpass2, (fs) => ({ fc: args[0], Q: args[1] ?? 0.707, fs }))
3061
+ };
3062
+ var filter2 = (chs, ctx) => {
3063
+ let [type, ...args] = ctx.args;
3064
+ if (typeof type === "function") {
3065
+ let opts = args[0] || {};
3066
+ return apply(chs, ctx, "_custom", type, (fs) => ({ ...opts, fs }));
3067
+ }
3068
+ let fn3 = types[type];
3069
+ if (!fn3) throw new Error(`Unknown filter type: ${type}`);
3070
+ return fn3(chs, ctx, args);
3071
+ };
3072
+ audio.op("filter", {
3073
+ process: filter2,
3074
+ call(std, type, ...args) {
3075
+ if (typeof type === "function") {
3076
+ let opts = args[0] || {};
3077
+ let { at, duration, channel, offset, length, ...rest } = opts;
3078
+ let edit = { type: "filter", args: [type, rest] };
3079
+ if (at != null) edit.at = at;
3080
+ if (duration != null) edit.duration = duration;
3081
+ if (channel != null) edit.channel = channel;
3082
+ if (offset != null) edit.offset = offset;
3083
+ if (length != null) edit.length = length;
3084
+ return this.run(edit);
3085
+ }
3086
+ return std.call(this, type, ...args);
3087
+ }
3088
+ });
3089
+ for (let name in types) {
3090
+ audio.op(name, { process: (chs, ctx) => types[name](chs, ctx, ctx.args) });
3091
+ }
3092
+
3093
+ // fn/pan.js
3094
+ var pan = (chs, ctx) => {
3095
+ let val = ctx.args[0] ?? 0;
3096
+ if (chs.length < 2) return false;
3097
+ let auto = typeof val === "function";
3098
+ let [s, end] = opRange(ctx, chs[0].length);
3099
+ let off = (ctx.blockOffset || 0) * ctx.sampleRate;
3100
+ if (!auto) {
3101
+ val = Math.max(-1, Math.min(1, val));
3102
+ let gL = val <= 0 ? 1 : 1 - val, gR = val >= 0 ? 1 : 1 + val, gains = [gL, gR];
3103
+ for (let c = 0; c < chs.length; c++) {
3104
+ let g = gains[c] ?? 1;
3105
+ if (g === 1) continue;
3106
+ for (let i = Math.max(0, s); i < Math.min(end, chs[c].length); i++) chs[c][i] *= g;
3107
+ }
3108
+ return chs;
3109
+ }
3110
+ let L = chs[0], R = chs[1];
3111
+ for (let i = Math.max(0, s); i < Math.min(end, L.length); i++) {
3112
+ let p = Math.max(-1, Math.min(1, val((off + i) / ctx.sampleRate)));
3113
+ L[i] *= p <= 0 ? 1 : 1 - p;
3114
+ R[i] *= p >= 0 ? 1 : 1 + p;
3115
+ }
3116
+ return chs;
3117
+ };
3118
+ audio.op("pan", { process: pan });
3119
+
3120
+ // fn/pad.js
3121
+ var padPlan = (segs, ctx) => {
3122
+ let { total, sampleRate: sr, args } = ctx;
3123
+ let before = args[0] ?? 0, after = args.length > 1 ? args[1] : before;
3124
+ let bN = Math.round(before * sr), aN = Math.round(after * sr);
3125
+ let r = segs.map((s) => {
3126
+ let n = s.slice();
3127
+ n[2] = s[2] + bN;
3128
+ return n;
3129
+ });
3130
+ if (bN > 0) r.unshift(seg(0, bN, 0, void 0, null));
3131
+ if (aN > 0) r.push(seg(0, aN, total + bN, void 0, null));
3132
+ return r;
3133
+ };
3134
+ audio.op("pad", { plan: padPlan });
3135
+
3136
+ // fn/speed.js
3137
+ var speedPlan = (segs, ctx) => {
3138
+ let rate = ctx.args[0];
3139
+ if (rate === 0) throw new RangeError("speed: rate cannot be 0");
3140
+ if (!rate || rate === 1) return segs;
3141
+ let absR = Math.abs(rate);
3142
+ let r = [], dst = 0;
3143
+ for (let s of segs) {
3144
+ let count = Math.round(s[1] / absR);
3145
+ r.push(seg(s[0], count, dst, s[4] === null ? s[3] : (s[3] || 1) * rate, s[4]));
3146
+ dst += count;
3147
+ }
3148
+ return r;
3149
+ };
3150
+ audio.op("speed", { plan: speedPlan });
3151
+
3152
+ // fn/transform.js
3153
+ audio.op("transform", {
3154
+ process: (chs, ctx) => ctx.args[0](chs, ctx),
3155
+ call(std, f) {
3156
+ return this.run({ type: "transform", args: [f] });
3157
+ }
3158
+ });
3159
+
3160
+ // fn/stat.js
3161
+ var rMin = (src, from, to) => {
3162
+ let v = Infinity;
3163
+ for (let i = from; i < to; i++) if (src[i] < v) v = src[i];
3164
+ return v === Infinity ? 0 : v;
3165
+ };
3166
+ var rMax = (src, from, to) => {
3167
+ let v = -Infinity;
3168
+ for (let i = from; i < to; i++) if (src[i] > v) v = src[i];
3169
+ return v === -Infinity ? 0 : v;
3170
+ };
3171
+ var rSum = (src, from, to) => {
3172
+ let v = 0;
3173
+ for (let i = from; i < to; i++) v += src[i];
3174
+ return v;
3175
+ };
3176
+ var rMean2 = (src, from, to) => {
3177
+ let n = to - from;
3178
+ if (!n) return 0;
3179
+ let v = 0;
3180
+ for (let i = from; i < to; i++) v += src[i];
3181
+ return v / n;
3182
+ };
3183
+ var rRms = (src, from, to) => {
3184
+ let n = to - from;
3185
+ if (!n) return 0;
3186
+ let v = 0;
3187
+ for (let i = from; i < to; i++) v += src[i];
3188
+ return Math.sqrt(v / n);
3189
+ };
3190
+ audio.stat("min", {
3191
+ block: (chs) => chs.map((ch) => {
3192
+ let mn = Infinity;
3193
+ for (let i = 0; i < ch.length; i++) if (ch[i] < mn) mn = ch[i];
3194
+ return mn;
3195
+ }),
3196
+ reduce: rMin,
3197
+ query: (stats, chs, from, to) => {
3198
+ let v = Infinity;
3199
+ for (let c of chs) for (let i = from; i < Math.min(to, stats.min[c].length); i++) if (stats.min[c][i] < v) v = stats.min[c][i];
3200
+ return v === Infinity ? 0 : v;
3201
+ }
3202
+ });
3203
+ audio.stat("max", {
3204
+ block: (chs) => chs.map((ch) => {
3205
+ let mx = -Infinity;
3206
+ for (let i = 0; i < ch.length; i++) if (ch[i] > mx) mx = ch[i];
3207
+ return mx;
3208
+ }),
3209
+ reduce: rMax,
3210
+ query: (stats, chs, from, to) => {
3211
+ let v = -Infinity;
3212
+ for (let c of chs) for (let i = from; i < Math.min(to, stats.max[c].length); i++) if (stats.max[c][i] > v) v = stats.max[c][i];
3213
+ return v === -Infinity ? 0 : v;
3214
+ }
3215
+ });
3216
+ audio.stat("dc", {
3217
+ block: (chs) => chs.map((ch) => {
3218
+ let sum = 0;
3219
+ for (let i = 0; i < ch.length; i++) sum += ch[i];
3220
+ return sum / ch.length;
3221
+ }),
3222
+ reduce: rMean2
3223
+ });
3224
+ audio.stat("clipping", {
3225
+ block: (chs) => chs.map((ch) => {
3226
+ let n = 0;
3227
+ for (let i = 0; i < ch.length; i++) if (ch[i] >= 1 || ch[i] <= -1) n++;
3228
+ return n;
3229
+ }),
3230
+ reduce: rSum,
3231
+ query: (stats, chs, from, to, sr) => {
3232
+ let bs = stats.blockSize, times = [];
3233
+ for (let i = from; i < to; i++) {
3234
+ let n = 0;
3235
+ for (let c of chs) n += stats.clipping[c][i] || 0;
3236
+ if (n > 0) times.push(i * bs / sr);
3237
+ }
3238
+ return new Float32Array(times);
3239
+ }
3240
+ });
3241
+ audio.stat("rms", {
3242
+ block: (chs) => chs.map((ch) => {
3243
+ let sum = 0;
3244
+ for (let i = 0; i < ch.length; i++) sum += ch[i] * ch[i];
3245
+ return sum / ch.length;
3246
+ }),
3247
+ reduce: rRms,
3248
+ query: (stats, chs, from, to) => {
3249
+ let sum = 0, n = 0;
3250
+ for (let c of chs)
3251
+ for (let i = from; i < Math.min(to, stats.rms[c].length); i++) {
3252
+ sum += stats.rms[c][i];
3253
+ n++;
3254
+ }
3255
+ return n ? Math.sqrt(sum / n) : 0;
3256
+ }
3257
+ });
3258
+
3259
+ // node_modules/fourier-transform/index.js
3260
+ var { sqrt: sqrt2, sin: sin2, cos: cos2, abs, SQRT1_2, SQRT2 } = Math;
3261
+ var TWO_PI = 6.283185307179586;
3262
+ var cache = /* @__PURE__ */ new Map();
3263
+ var lastN = 0;
3264
+ var lastEntry = null;
3265
+ function init(N) {
3266
+ const half = N >>> 1;
3267
+ const x = new Float64Array(N);
3268
+ const spectrum = new Float64Array(half);
3269
+ const im = new Float64Array(half + 1);
3270
+ const re = x.subarray(0, half + 1);
3271
+ const complex = [re, im];
3272
+ const bSi = 2 / N;
3273
+ const bits = 31 - Math.clz32(N);
3274
+ const perm = new Uint32Array(N);
3275
+ for (let i = 0; i < N; i++) {
3276
+ let rev = 0, v = i;
3277
+ for (let j = 0; j < bits; j++) {
3278
+ rev = rev << 1 | v & 1;
3279
+ v >>= 1;
3280
+ }
3281
+ perm[i] = rev;
3282
+ }
3283
+ let total = 0, n2 = 2, nn = half;
3284
+ const stages = [];
3285
+ while (nn = nn >>> 1) {
3286
+ n2 = n2 << 1;
3287
+ const n8 = n2 >>> 3;
3288
+ const count = n8 > 1 ? n8 - 1 : 0;
3289
+ stages.push({ offset: total, count });
3290
+ total += count;
3291
+ }
3292
+ const tw = new Float64Array(total << 2);
3293
+ n2 = 2;
3294
+ nn = half;
3295
+ let si = 0;
3296
+ while (nn = nn >>> 1) {
3297
+ n2 = n2 << 1;
3298
+ const n8 = n2 >>> 3;
3299
+ const e = TWO_PI / n2;
3300
+ const off = stages[si].offset << 2;
3301
+ for (let j = 1; j < n8; j++) {
3302
+ const a2 = j * e;
3303
+ const s = sin2(a2), c = cos2(a2);
3304
+ const idx = off + (j - 1 << 2);
3305
+ tw[idx] = c;
3306
+ tw[idx + 1] = s;
3307
+ tw[idx + 2] = 4 * c * (c * c - 0.75);
3308
+ tw[idx + 3] = 4 * s * (0.75 - s * s);
3309
+ }
3310
+ si++;
3311
+ }
3312
+ const entry = { x, spectrum, complex, bSi, tw, stages, perm };
3313
+ cache.set(N, entry);
3314
+ return entry;
3315
+ }
3316
+ function getEntry(N) {
3317
+ if (N === lastN) return lastEntry;
3318
+ const entry = cache.get(N) || init(N);
3319
+ lastN = N;
3320
+ lastEntry = entry;
3321
+ return entry;
3322
+ }
3323
+ function transform(input) {
3324
+ const N = input.length;
3325
+ if (N < 2 || N & N - 1) throw Error("Input length must be a power of 2 (>= 2).");
3326
+ const entry = getEntry(N);
3327
+ const { x, tw, stages, perm } = entry;
3328
+ for (let i = 0; i < N; i++) x[i] = input[perm[i]];
3329
+ for (let ix = 0, id = 4; ix < N; id *= 4) {
3330
+ for (let i0 = ix; i0 < N; i0 += id) {
3331
+ const t = x[i0] - x[i0 + 1];
3332
+ x[i0] += x[i0 + 1];
3333
+ x[i0 + 1] = t;
3334
+ }
3335
+ ix = 2 * (id - 1);
3336
+ }
3337
+ let n2 = 2, nn = N >>> 1, si = 0;
3338
+ while (nn = nn >>> 1) {
3339
+ let ix = 0;
3340
+ n2 = n2 << 1;
3341
+ let id = n2 << 1;
3342
+ const n4 = n2 >>> 2;
3343
+ const n8 = n2 >>> 3;
3344
+ do {
3345
+ if (n4 !== 1) {
3346
+ for (let i0 = ix; i0 < N; i0 += id) {
3347
+ let i1 = i0, i2 = i1 + n4, i3 = i2 + n4, i4 = i3 + n4;
3348
+ let t1 = x[i3] + x[i4];
3349
+ x[i4] -= x[i3];
3350
+ x[i3] = x[i1] - t1;
3351
+ x[i1] += t1;
3352
+ i1 += n8;
3353
+ i2 += n8;
3354
+ i3 += n8;
3355
+ i4 += n8;
3356
+ t1 = x[i3] + x[i4];
3357
+ let t2 = x[i3] - x[i4];
3358
+ t1 = -t1 * SQRT1_2;
3359
+ t2 *= SQRT1_2;
3360
+ const st1 = x[i2];
3361
+ x[i4] = t1 + st1;
3362
+ x[i3] = t1 - st1;
3363
+ x[i2] = x[i1] - t2;
3364
+ x[i1] += t2;
3365
+ }
3366
+ } else {
3367
+ for (let i0 = ix; i0 < N; i0 += id) {
3368
+ const i1 = i0, i3 = i1 + 2, i4 = i3 + 1;
3369
+ const t1 = x[i3] + x[i4];
3370
+ x[i4] -= x[i3];
3371
+ x[i3] = x[i1] - t1;
3372
+ x[i1] += t1;
3373
+ }
3374
+ }
3375
+ ix = (id << 1) - n2;
3376
+ id = id << 2;
3377
+ } while (ix < N);
3378
+ const { offset, count } = stages[si];
3379
+ for (let j = 0; j < count; j++) {
3380
+ const ti = offset + j << 2;
3381
+ const cc1 = tw[ti], ss1 = tw[ti + 1], cc3 = tw[ti + 2], ss3 = tw[ti + 3];
3382
+ ix = 0;
3383
+ id = n2 << 1;
3384
+ do {
3385
+ for (let i0 = ix; i0 < N; i0 += id) {
3386
+ const i1 = i0 + j + 1;
3387
+ const i2 = i1 + n4;
3388
+ const i3 = i2 + n4;
3389
+ const i4 = i3 + n4;
3390
+ const i5 = i0 + n4 - j - 1;
3391
+ const i6 = i5 + n4;
3392
+ const i7 = i6 + n4;
3393
+ const i8 = i7 + n4;
3394
+ let t2 = x[i7] * cc1 - x[i3] * ss1;
3395
+ let t1 = x[i7] * ss1 + x[i3] * cc1;
3396
+ let t4 = x[i8] * cc3 - x[i4] * ss3;
3397
+ let t3 = x[i8] * ss3 + x[i4] * cc3;
3398
+ const st1 = t2 - t4;
3399
+ t2 += t4;
3400
+ t4 = st1;
3401
+ x[i8] = t2 + x[i6];
3402
+ x[i3] = t2 - x[i6];
3403
+ const st2 = t3 - t1;
3404
+ t1 += t3;
3405
+ t3 = st2;
3406
+ x[i4] = t3 + x[i2];
3407
+ x[i7] = t3 - x[i2];
3408
+ x[i6] = x[i1] - t1;
3409
+ x[i1] += t1;
3410
+ x[i2] = t4 + x[i5];
3411
+ x[i5] -= t4;
3412
+ }
3413
+ ix = (id << 1) - n2;
3414
+ id = id << 2;
3415
+ } while (ix < N);
3416
+ }
3417
+ si++;
3418
+ }
3419
+ return entry;
3420
+ }
3421
+ function rfft(input, output) {
3422
+ const entry = transform(input);
3423
+ const N = input.length;
3424
+ const { x, spectrum, bSi } = entry;
3425
+ const out = output || spectrum;
3426
+ let i = N >>> 1;
3427
+ while (--i) {
3428
+ const rval = x[i], ival = x[N - i];
3429
+ out[i] = bSi * sqrt2(rval * rval + ival * ival);
3430
+ }
3431
+ out[0] = abs(bSi * x[0]);
3432
+ return out;
3433
+ }
3434
+
3435
+ // node_modules/window-function/util.js
3436
+ var { cos: cos3, sin: sin3, abs: abs2, exp, sqrt: sqrt3, PI: PI2, cosh, acosh, acos, pow: pow2, log10 } = Math;
3437
+ var PI22 = 2 * PI2;
3438
+
3439
+ // node_modules/window-function/hann.js
3440
+ function hann(i, N) {
3441
+ return 0.5 - 0.5 * cos3(PI22 * i / (N - 1));
3442
+ }
3443
+
3444
+ // node_modules/a-weighting/index.js
3445
+ function a(f) {
3446
+ let f2 = f * f;
3447
+ return 1.2588966 * 14884e4 * f2 * f2 / ((f2 + 424.36) * Math.sqrt((f2 + 11599.29) * (f2 + 544496.41)) * (f2 + 14884e4));
3448
+ }
3449
+
3450
+ // fn/spectrum.js
3451
+ var toMel = (f) => 2595 * Math.log10(1 + f / 700);
3452
+ var fromMel = (m2) => 700 * (10 ** (m2 / 2595) - 1);
3453
+ var windows = {};
3454
+ function hannWin(n) {
3455
+ if (windows[n]) return windows[n];
3456
+ let w = new Float32Array(n);
3457
+ for (let i = 0; i < n; i++) w[i] = hann(i, n);
3458
+ return windows[n] = w;
3459
+ }
3460
+ function melSpectrum(samples, sr, opts = {}) {
3461
+ let { bins = 128, fMin = 30, fMax = Math.min(sr / 2, 2e4), weight = true } = opts;
3462
+ let N = samples.length, win = hannWin(N);
3463
+ let buf = new Float32Array(N);
3464
+ for (let i = 0; i < N; i++) buf[i] = samples[i] * win[i];
3465
+ let mag = rfft(buf);
3466
+ let mMin = toMel(fMin), mMax = toMel(fMax), binHz = sr / N;
3467
+ let out = new Float32Array(bins);
3468
+ for (let b = 0; b < bins; b++) {
3469
+ let f0 = fromMel(mMin + (mMax - mMin) * b / bins);
3470
+ let f1 = fromMel(mMin + (mMax - mMin) * (b + 1) / bins);
3471
+ let k0 = Math.max(1, Math.floor(f0 / binHz));
3472
+ let k1 = Math.min(mag.length - 1, Math.ceil(f1 / binHz));
3473
+ let sum = 0, cnt = 0;
3474
+ for (let k = k0; k <= k1; k++) {
3475
+ sum += mag[k] ** 2;
3476
+ cnt++;
3477
+ }
3478
+ let rms = cnt > 0 ? Math.sqrt(sum / cnt) : 0;
3479
+ if (weight) rms *= a((f0 + f1) / 2, sr);
3480
+ out[b] = rms;
3481
+ }
3482
+ return out;
3483
+ }
3484
+ async function analyzeBlocks(inst, opts, N, bins, fn3) {
3485
+ let acc = new Float64Array(bins), cnt = 0, rem = new Float32Array(0);
3486
+ for await (let pcm of inst.stream({ at: opts?.at, duration: opts?.duration })) {
3487
+ let ch0 = pcm[0];
3488
+ if (!ch0 || !ch0.length) continue;
3489
+ let input = ch0;
3490
+ if (rem.length) {
3491
+ input = new Float32Array(rem.length + ch0.length);
3492
+ input.set(rem, 0);
3493
+ input.set(ch0, rem.length);
3494
+ }
3495
+ let limit = input.length - input.length % N;
3496
+ for (let off = 0; off < limit; off += N) {
3497
+ fn3(input.subarray(off, off + N), acc);
3498
+ cnt++;
3499
+ }
3500
+ rem = limit < input.length ? input.slice(limit) : new Float32Array(0);
3501
+ }
3502
+ return { acc, cnt };
3503
+ }
3504
+ audio.fn.spectrum = async function(opts) {
3505
+ let bins = opts?.bins ?? 128;
3506
+ let spectOpts = { bins, fMin: opts?.fMin, fMax: opts?.fMax, weight: opts?.weight };
3507
+ let sr = this.sampleRate;
3508
+ let { acc, cnt } = await analyzeBlocks(this, opts, 1024, bins, (block, acc2) => {
3509
+ let mag = melSpectrum(block, sr, spectOpts);
3510
+ for (let b = 0; b < bins; b++) acc2[b] += mag[b] ** 2;
3511
+ });
3512
+ if (cnt === 0) return new Float32Array(bins);
3513
+ let out = new Float32Array(bins);
3514
+ for (let b = 0; b < bins; b++) out[b] = 20 * Math.log10(Math.sqrt(acc[b] / cnt) + 1e-10);
3515
+ return out;
3516
+ };
3517
+
3518
+ // fn/cepstrum.js
3519
+ function mfcc(samples, sr, opts = {}) {
3520
+ let { bins = 13, nMel = 40 } = opts;
3521
+ let mag = melSpectrum(samples, sr, { bins: nMel, weight: false });
3522
+ let logMel = new Float32Array(nMel);
3523
+ for (let i = 0; i < nMel; i++) logMel[i] = Math.log(mag[i] ** 2 + 1e-10);
3524
+ let out = new Float32Array(bins);
3525
+ for (let k = 0; k < bins; k++) {
3526
+ let sum = 0;
3527
+ for (let n = 0; n < nMel; n++) sum += logMel[n] * Math.cos(Math.PI * k * (2 * n + 1) / (2 * nMel));
3528
+ out[k] = sum;
3529
+ }
3530
+ return out;
3531
+ }
3532
+ audio.fn.cepstrum = async function(opts) {
3533
+ let bins = opts?.bins ?? 13;
3534
+ let sr = this.sampleRate;
3535
+ let { acc, cnt } = await analyzeBlocks(this, opts, 1024, bins, (block, acc2) => {
3536
+ let c = mfcc(block, sr, { bins });
3537
+ for (let k = 0; k < bins; k++) acc2[k] += c[k];
3538
+ });
3539
+ if (cnt === 0) return new Float32Array(bins);
3540
+ let out = new Float32Array(bins);
3541
+ for (let k = 0; k < bins; k++) out[k] = acc[k] / cnt;
3542
+ return out;
3543
+ };
3544
+
3545
+ // fn/silence.js
3546
+ audio.fn.silence = async function(opts) {
3547
+ let { stats, ch, sr, from, to } = await queryRange(this, opts);
3548
+ let bs = stats.blockSize;
3549
+ let minDur = opts?.minDuration ?? 0.1;
3550
+ let thresh = resolveThreshold(stats, ch, from, to, opts?.threshold);
3551
+ let segs = [], start = null;
3552
+ for (let i = from; i < to; i++) {
3553
+ if (!isLoud(stats, i, ch, thresh)) {
3554
+ if (start == null) start = i;
3555
+ } else if (start != null) {
3556
+ let segAt = start * bs / sr, segEnd = i * bs / sr;
3557
+ if (segEnd - segAt >= minDur) segs.push({ at: segAt, duration: segEnd - segAt });
3558
+ start = null;
3559
+ }
3560
+ }
3561
+ if (start != null) {
3562
+ let segAt = start * bs / sr, segEnd = Math.min(to * bs / sr, this.duration);
3563
+ if (segEnd - segAt >= minDur) segs.push({ at: segAt, duration: segEnd - segAt });
3564
+ }
3565
+ return segs;
3566
+ };
3567
+ export {
3568
+ audio as default,
3569
+ parseTime,
3570
+ render
3571
+ };