@kano/stem-daw 0.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.
Files changed (67) hide show
  1. package/README.md +253 -0
  2. package/dist/chat-actions-54Z6URC4.js +7 -0
  3. package/dist/chat-actions-54Z6URC4.js.map +1 -0
  4. package/dist/chunk-56PWIP7O.js +1029 -0
  5. package/dist/chunk-56PWIP7O.js.map +1 -0
  6. package/dist/chunk-AAVC7KUW.js +145 -0
  7. package/dist/chunk-AAVC7KUW.js.map +1 -0
  8. package/dist/chunk-KCOOE2OP.js +1764 -0
  9. package/dist/chunk-KCOOE2OP.js.map +1 -0
  10. package/dist/chunk-LO74ZJ4H.js +23923 -0
  11. package/dist/chunk-LO74ZJ4H.js.map +1 -0
  12. package/dist/chunk-OFGZURP6.js +247 -0
  13. package/dist/chunk-OFGZURP6.js.map +1 -0
  14. package/dist/chunk-OYNES5W3.js +3085 -0
  15. package/dist/chunk-OYNES5W3.js.map +1 -0
  16. package/dist/chunk-QQ5NZTHT.js +336 -0
  17. package/dist/chunk-QQ5NZTHT.js.map +1 -0
  18. package/dist/chunk-TBXCZFAY.js +13713 -0
  19. package/dist/chunk-TBXCZFAY.js.map +1 -0
  20. package/dist/chunk-U44X6QP5.js +281 -0
  21. package/dist/chunk-U44X6QP5.js.map +1 -0
  22. package/dist/chunk-UKMELGZL.js +27 -0
  23. package/dist/chunk-UKMELGZL.js.map +1 -0
  24. package/dist/components/DAWView.d.ts +19 -0
  25. package/dist/components/DAWView.js +11 -0
  26. package/dist/components/DAWView.js.map +1 -0
  27. package/dist/daw-controller-BjRWcTol.d.ts +339 -0
  28. package/dist/engine/daw-controller.d.ts +3 -0
  29. package/dist/engine/daw-controller.js +5 -0
  30. package/dist/engine/daw-controller.js.map +1 -0
  31. package/dist/engine/daw-import-stem-fm-config.d.ts +224 -0
  32. package/dist/engine/daw-import-stem-fm-config.js +7 -0
  33. package/dist/engine/daw-import-stem-fm-config.js.map +1 -0
  34. package/dist/fetchStationTracks-SKFT4V3U.js +3 -0
  35. package/dist/fetchStationTracks-SKFT4V3U.js.map +1 -0
  36. package/dist/index.d.ts +308 -0
  37. package/dist/index.js +332 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/interface-DaRj7RkY.d.ts +66 -0
  40. package/dist/interfaces-5ZlG0Y4Y.d.ts +549 -0
  41. package/dist/media-session-XTP6PP7Q.js +3 -0
  42. package/dist/media-session-XTP6PP7Q.js.map +1 -0
  43. package/dist/note-detection-PPLM7R2H.js +148 -0
  44. package/dist/note-detection-PPLM7R2H.js.map +1 -0
  45. package/dist/sampler-audio-B7MBG3YN.js +3 -0
  46. package/dist/sampler-audio-B7MBG3YN.js.map +1 -0
  47. package/dist/sampler-store-QPHANXYP.js +3 -0
  48. package/dist/sampler-store-QPHANXYP.js.map +1 -0
  49. package/dist/services/track-search-api.d.ts +152 -0
  50. package/dist/services/track-search-api.js +4 -0
  51. package/dist/services/track-search-api.js.map +1 -0
  52. package/dist/store/daw-auth-store.d.ts +31 -0
  53. package/dist/store/daw-auth-store.js +3 -0
  54. package/dist/store/daw-auth-store.js.map +1 -0
  55. package/dist/store/daw-session-store.d.ts +255 -0
  56. package/dist/store/daw-session-store.js +3 -0
  57. package/dist/store/daw-session-store.js.map +1 -0
  58. package/dist/vite/index.d.ts +46 -0
  59. package/dist/vite/index.js +94 -0
  60. package/dist/vite/index.js.map +1 -0
  61. package/dist/workers/analysis-worker.js +379 -0
  62. package/dist/workers/buffer-player-processor-202602.lavv8e32-ts.js +1 -0
  63. package/dist/workers/daw-stem-processor.js +228 -0
  64. package/dist/workers/manifest.json +10 -0
  65. package/dist/workers/phase-vocoder3.js +920 -0
  66. package/dist/workers/realtime-pitch-shift-processor.js +2 -0
  67. package/package.json +151 -0
@@ -0,0 +1,3 @@
1
+ export { useDAWSessionStore } from '../chunk-KCOOE2OP.js';
2
+ //# sourceMappingURL=daw-session-store.js.map
3
+ //# sourceMappingURL=daw-session-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"daw-session-store.js"}
@@ -0,0 +1,46 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ /**
4
+ * `@kano/stem-daw/vite` — consumer Vite helper plugin.
5
+ *
6
+ * Usage in the consumer app (e.g. stem-player-rd):
7
+ *
8
+ * ```ts
9
+ * // vite.config.ts
10
+ * import { defineConfig } from 'vite';
11
+ * import { dawWorklets } from '@kano/stem-daw/vite';
12
+ *
13
+ * export default defineConfig({
14
+ * plugins: [dawWorklets()],
15
+ * });
16
+ * ```
17
+ *
18
+ * What it does:
19
+ * - DEV (`vite`): serves the worklet files shipped in
20
+ * `@kano/stem-daw/dist/workers/*` at the same `/workers/<name>.js`
21
+ * URLs that DAWController fetches at runtime, without copying them
22
+ * into the consumer's repo.
23
+ * - BUILD (`vite build`): copies those same files into the output
24
+ * `dist/workers/` directory so the production bundle is self-
25
+ * contained.
26
+ *
27
+ * The plugin never overwrites a file the consumer's own `public/workers/`
28
+ * already provides — the host app stays the source of truth for any
29
+ * shared filename, the DAW plugin only fills gaps.
30
+ */
31
+
32
+ interface DawWorkletsOptions {
33
+ /**
34
+ * Path under the dev server / build output where worklets are served.
35
+ * Defaults to `/workers` — matches DAWController's hard-coded
36
+ * `/workers/daw-stem-processor.js` fetch.
37
+ */
38
+ publicPath?: string;
39
+ }
40
+ /**
41
+ * Vite plugin: serve @kano/stem-daw's audio worklets at /workers/* in
42
+ * dev and emit them into dist/workers/* at build time.
43
+ */
44
+ declare function dawWorklets(options?: DawWorkletsOptions): Plugin;
45
+
46
+ export { dawWorklets, dawWorklets as default };
@@ -0,0 +1,94 @@
1
+ import { createRequire } from 'node:module';
2
+ import { existsSync, readFileSync, statSync, readdirSync } from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ // src/lib/vite-plugin.ts
6
+ function resolveDawWorkletsDir() {
7
+ const require2 = createRequire(import.meta.url);
8
+ try {
9
+ const pkgPath = require2.resolve("@kano/stem-daw/package.json");
10
+ const workletsDir = path.join(path.dirname(pkgPath), "dist", "workers");
11
+ if (existsSync(workletsDir) && statSync(workletsDir).isDirectory()) {
12
+ return workletsDir;
13
+ }
14
+ } catch {
15
+ }
16
+ return null;
17
+ }
18
+ function loadManifest(workletsDir) {
19
+ const manifestPath = path.join(workletsDir, "manifest.json");
20
+ if (!existsSync(manifestPath)) return null;
21
+ try {
22
+ const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
23
+ if (Array.isArray(parsed.worklets)) return parsed;
24
+ } catch {
25
+ }
26
+ return null;
27
+ }
28
+ function listWorkletsFromDir(dir) {
29
+ try {
30
+ return readdirSync(dir).filter((name) => name.endsWith(".js")).sort();
31
+ } catch {
32
+ return [];
33
+ }
34
+ }
35
+ function dawWorklets(options = {}) {
36
+ const publicPath = (options.publicPath ?? "/workers").replace(/\/$/, "");
37
+ const workletsDir = resolveDawWorkletsDir();
38
+ let consumerPublicDir = "";
39
+ let consumerOutDir = "";
40
+ return {
41
+ name: "@kano/stem-daw:vite-worklets",
42
+ configResolved(config) {
43
+ consumerPublicDir = path.resolve(config.root, config.publicDir || "public");
44
+ consumerOutDir = path.resolve(config.root, config.build?.outDir || "dist");
45
+ },
46
+ configureServer(server) {
47
+ if (!workletsDir) return;
48
+ const manifest = loadManifest(workletsDir);
49
+ const workletNames = manifest?.worklets ?? listWorkletsFromDir(workletsDir);
50
+ if (workletNames.length === 0) return;
51
+ server.middlewares.use((req, res, next) => {
52
+ if (!req.url) return next();
53
+ const urlPath = decodeURIComponent(req.url.split("?")[0].split("#")[0]);
54
+ if (!urlPath.startsWith(publicPath + "/")) return next();
55
+ const name = urlPath.slice(publicPath.length + 1);
56
+ if (!workletNames.includes(name)) return next();
57
+ const consumerCandidate = path.join(consumerPublicDir, "workers", name);
58
+ if (existsSync(consumerCandidate)) return next();
59
+ const filePath = path.join(workletsDir, name);
60
+ if (!existsSync(filePath)) return next();
61
+ try {
62
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
63
+ res.setHeader("Cache-Control", "no-cache");
64
+ res.end(readFileSync(filePath));
65
+ } catch {
66
+ next();
67
+ }
68
+ });
69
+ },
70
+ // Build-time: emit each worklet as a static asset at /workers/<name>.
71
+ generateBundle() {
72
+ if (!workletsDir) return;
73
+ const manifest = loadManifest(workletsDir);
74
+ const workletNames = manifest?.worklets ?? listWorkletsFromDir(workletsDir);
75
+ for (const name of workletNames) {
76
+ const consumerCandidate = path.join(consumerPublicDir, "workers", name);
77
+ if (existsSync(consumerCandidate)) continue;
78
+ const filePath = path.join(workletsDir, name);
79
+ if (!existsSync(filePath)) continue;
80
+ this.emitFile({
81
+ type: "asset",
82
+ fileName: path.posix.join(publicPath.replace(/^\//, ""), name),
83
+ source: readFileSync(filePath)
84
+ });
85
+ }
86
+ if (!consumerOutDir) return;
87
+ }
88
+ };
89
+ }
90
+ var vite_plugin_default = dawWorklets;
91
+
92
+ export { dawWorklets, vite_plugin_default as default };
93
+ //# sourceMappingURL=index.js.map
94
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/vite-plugin.ts"],"names":["require"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `@kano/stem-daw/vite` — consumer Vite helper plugin.\n *\n * Usage in the consumer app (e.g. stem-player-rd):\n *\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import { dawWorklets } from '@kano/stem-daw/vite';\n *\n * export default defineConfig({\n * plugins: [dawWorklets()],\n * });\n * ```\n *\n * What it does:\n * - DEV (`vite`): serves the worklet files shipped in\n * `@kano/stem-daw/dist/workers/*` at the same `/workers/<name>.js`\n * URLs that DAWController fetches at runtime, without copying them\n * into the consumer's repo.\n * - BUILD (`vite build`): copies those same files into the output\n * `dist/workers/` directory so the production bundle is self-\n * contained.\n *\n * The plugin never overwrites a file the consumer's own `public/workers/`\n * already provides — the host app stays the source of truth for any\n * shared filename, the DAW plugin only fills gaps.\n */\n\nimport type { Plugin } from 'vite';\nimport { createRequire } from 'node:module';\nimport { readFileSync, existsSync, statSync, readdirSync } from 'node:fs';\nimport path from 'node:path';\n\ninterface DawWorkletsOptions {\n /**\n * Path under the dev server / build output where worklets are served.\n * Defaults to `/workers` — matches DAWController's hard-coded\n * `/workers/daw-stem-processor.js` fetch.\n */\n publicPath?: string;\n}\n\ninterface WorkletManifest {\n version: number;\n worklets: string[];\n}\n\nfunction resolveDawWorkletsDir(): string | null {\n const require = createRequire(import.meta.url);\n try {\n const pkgPath = require.resolve('@kano/stem-daw/package.json');\n const workletsDir = path.join(path.dirname(pkgPath), 'dist', 'workers');\n if (existsSync(workletsDir) && statSync(workletsDir).isDirectory()) {\n return workletsDir;\n }\n } catch {\n // package not installed (e.g. self-test inside the stem-daw repo).\n }\n return null;\n}\n\nfunction loadManifest(workletsDir: string): WorkletManifest | null {\n const manifestPath = path.join(workletsDir, 'manifest.json');\n if (!existsSync(manifestPath)) return null;\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf8')) as WorkletManifest;\n if (Array.isArray(parsed.worklets)) return parsed;\n } catch {\n // fall through\n }\n return null;\n}\n\nfunction listWorkletsFromDir(dir: string): string[] {\n try {\n return readdirSync(dir)\n .filter((name) => name.endsWith('.js'))\n .sort();\n } catch {\n return [];\n }\n}\n\n/**\n * Vite plugin: serve @kano/stem-daw's audio worklets at /workers/* in\n * dev and emit them into dist/workers/* at build time.\n */\nexport function dawWorklets(options: DawWorkletsOptions = {}): Plugin {\n const publicPath = (options.publicPath ?? '/workers').replace(/\\/$/, '');\n const workletsDir = resolveDawWorkletsDir();\n\n let consumerPublicDir = '';\n let consumerOutDir = '';\n\n return {\n name: '@kano/stem-daw:vite-worklets',\n configResolved(config) {\n consumerPublicDir = path.resolve(config.root, config.publicDir || 'public');\n consumerOutDir = path.resolve(config.root, config.build?.outDir || 'dist');\n },\n configureServer(server) {\n if (!workletsDir) return;\n const manifest = loadManifest(workletsDir);\n const workletNames = manifest?.worklets ?? listWorkletsFromDir(workletsDir);\n if (workletNames.length === 0) return;\n\n server.middlewares.use((req, res, next) => {\n if (!req.url) return next();\n const urlPath = decodeURIComponent(req.url.split('?')[0].split('#')[0]);\n if (!urlPath.startsWith(publicPath + '/')) return next();\n const name = urlPath.slice(publicPath.length + 1);\n if (!workletNames.includes(name)) return next();\n\n // Consumer's own public/workers/ wins if a same-named file exists.\n const consumerCandidate = path.join(consumerPublicDir, 'workers', name);\n if (existsSync(consumerCandidate)) return next();\n\n const filePath = path.join(workletsDir, name);\n if (!existsSync(filePath)) return next();\n try {\n res.setHeader('Content-Type', 'application/javascript; charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache');\n res.end(readFileSync(filePath));\n } catch {\n next();\n }\n });\n },\n // Build-time: emit each worklet as a static asset at /workers/<name>.\n generateBundle() {\n if (!workletsDir) return;\n const manifest = loadManifest(workletsDir);\n const workletNames = manifest?.worklets ?? listWorkletsFromDir(workletsDir);\n for (const name of workletNames) {\n // Don't overwrite consumer's existing worklet (parent app wins).\n const consumerCandidate = path.join(consumerPublicDir, 'workers', name);\n if (existsSync(consumerCandidate)) continue;\n\n const filePath = path.join(workletsDir, name);\n if (!existsSync(filePath)) continue;\n this.emitFile({\n type: 'asset',\n fileName: path.posix.join(publicPath.replace(/^\\//, ''), name),\n source: readFileSync(filePath),\n });\n }\n // Quieter when consumerOutDir is unset (e.g. middleware mode).\n if (!consumerOutDir) return;\n },\n };\n}\n\nexport default dawWorklets;\n"]}
@@ -0,0 +1,379 @@
1
+ // src/daw/analysis/analysis-worker.ts
2
+ var YIN_WINDOW = 1024;
3
+ var YIN_HOP = 1024;
4
+ var YIN_THRESHOLD = 0.15;
5
+ function yinDetect(buffer, sr) {
6
+ const half = Math.floor(YIN_WINDOW / 2);
7
+ const diff = new Float32Array(half);
8
+ const cmndf = new Float32Array(half);
9
+ for (let tau = 0; tau < half; tau++) {
10
+ let sum = 0;
11
+ for (let i = 0; i < half; i++) {
12
+ const d = buffer[i] - buffer[i + tau];
13
+ sum += d * d;
14
+ }
15
+ diff[tau] = sum;
16
+ }
17
+ cmndf[0] = 1;
18
+ let run = 0;
19
+ for (let tau = 1; tau < half; tau++) {
20
+ run += diff[tau];
21
+ cmndf[tau] = diff[tau] * tau / run;
22
+ }
23
+ let tauEst = -1;
24
+ for (let tau = 2; tau < half; tau++) {
25
+ if (cmndf[tau] < YIN_THRESHOLD) {
26
+ while (tau + 1 < half && cmndf[tau + 1] < cmndf[tau]) tau++;
27
+ tauEst = tau;
28
+ break;
29
+ }
30
+ }
31
+ if (tauEst < 0) return -1;
32
+ let better = tauEst;
33
+ if (tauEst > 0 && tauEst < half - 1) {
34
+ const s0 = cmndf[tauEst - 1], s1 = cmndf[tauEst], s2 = cmndf[tauEst + 1];
35
+ better = tauEst + (s0 - s2) / (2 * (s0 - 2 * s1 + s2));
36
+ }
37
+ return sr / better;
38
+ }
39
+ function detectPitchContour(data, sr) {
40
+ const RMS_GATE = 0.015;
41
+ const numFrames = Math.floor((data.length - YIN_WINDOW) / YIN_HOP);
42
+ const raw = [];
43
+ for (let f = 0; f < numFrames; f++) {
44
+ const offset = f * YIN_HOP;
45
+ const frame = data.subarray(offset, offset + YIN_WINDOW);
46
+ let rms = 0;
47
+ for (let i = 0; i < frame.length; i++) rms += frame[i] * frame[i];
48
+ rms = Math.sqrt(rms / frame.length);
49
+ let freq = -1;
50
+ if (rms > RMS_GATE) {
51
+ freq = yinDetect(frame, sr);
52
+ if (freq < 70 || freq > 1100) freq = -1;
53
+ }
54
+ raw.push({ time: offset / sr, freq, rms, midi: freq > 0 ? 12 * Math.log2(freq / 440) + 69 : -1, frameIndex: f });
55
+ }
56
+ for (let i = 1; i < raw.length - 1; i++) {
57
+ if (raw[i].midi <= 0) continue;
58
+ const prev = raw[i - 1].midi > 0 ? raw[i - 1].midi : -1;
59
+ const next = raw[i + 1].midi > 0 ? raw[i + 1].midi : -1;
60
+ if (prev > 0 && next > 0) {
61
+ if (Math.abs(raw[i].midi - prev) > 5 && Math.abs(raw[i].midi - next) > 5) {
62
+ raw[i].freq = -1;
63
+ raw[i].midi = -1;
64
+ }
65
+ }
66
+ }
67
+ const MEDIAN_R = 2;
68
+ const contour = [];
69
+ for (let i = 0; i < raw.length; i++) {
70
+ if (raw[i].midi <= 0) {
71
+ contour.push(raw[i]);
72
+ continue;
73
+ }
74
+ const window = [];
75
+ for (let j = i - MEDIAN_R; j <= i + MEDIAN_R; j++) {
76
+ if (j >= 0 && j < raw.length && raw[j].midi > 0) window.push(raw[j].midi);
77
+ }
78
+ if (window.length < 2) {
79
+ contour.push(raw[i]);
80
+ continue;
81
+ }
82
+ window.sort((a, b) => a - b);
83
+ const medianMidi = window[Math.floor(window.length / 2)];
84
+ const medianFreq = 440 * Math.pow(2, (medianMidi - 69) / 12);
85
+ contour.push({ ...raw[i], midi: medianMidi, freq: medianFreq });
86
+ }
87
+ return contour;
88
+ }
89
+ function fft(buf, n) {
90
+ for (let i = 1, j = 0; i < n; i++) {
91
+ let bit = n >> 1;
92
+ for (; j & bit; bit >>= 1) j ^= bit;
93
+ j ^= bit;
94
+ if (i < j) {
95
+ let t = buf[2 * i];
96
+ buf[2 * i] = buf[2 * j];
97
+ buf[2 * j] = t;
98
+ t = buf[2 * i + 1];
99
+ buf[2 * i + 1] = buf[2 * j + 1];
100
+ buf[2 * j + 1] = t;
101
+ }
102
+ }
103
+ for (let len = 2; len <= n; len <<= 1) {
104
+ const ang = -2 * Math.PI / len;
105
+ const wRe = Math.cos(ang), wIm = Math.sin(ang);
106
+ for (let i = 0; i < n; i += len) {
107
+ let curRe = 1, curIm = 0;
108
+ for (let j = 0; j < len / 2; j++) {
109
+ const uRe = buf[2 * (i + j)], uIm = buf[2 * (i + j) + 1];
110
+ const vIdx = 2 * (i + j + len / 2);
111
+ const vRe = buf[vIdx] * curRe - buf[vIdx + 1] * curIm;
112
+ const vIm = buf[vIdx] * curIm + buf[vIdx + 1] * curRe;
113
+ buf[2 * (i + j)] = uRe + vRe;
114
+ buf[2 * (i + j) + 1] = uIm + vIm;
115
+ buf[vIdx] = uRe - vRe;
116
+ buf[vIdx + 1] = uIm - vIm;
117
+ const tmpRe = curRe * wRe - curIm * wIm;
118
+ curIm = curRe * wIm + curIm * wRe;
119
+ curRe = tmpRe;
120
+ }
121
+ }
122
+ }
123
+ }
124
+ var CHROMA_HOP = 4096;
125
+ var CHROMA_WINDOW = 2048;
126
+ var NOTE_NAMES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
127
+ var KK_MAJOR = [6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88];
128
+ var KK_MINOR = [6.33, 2.68, 3.52, 5.38, 2.6, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17];
129
+ function computeChroma(data, sr) {
130
+ const numFrames = Math.floor((data.length - CHROMA_WINDOW) / CHROMA_HOP);
131
+ const frames = [];
132
+ const hann = new Float32Array(CHROMA_WINDOW);
133
+ for (let i = 0; i < CHROMA_WINDOW; i++) hann[i] = 0.5 * (1 - Math.cos(2 * Math.PI * i / (CHROMA_WINDOW - 1)));
134
+ const minBin = Math.ceil(50 * CHROMA_WINDOW / sr);
135
+ const maxBin = Math.min(Math.floor(2e3 * CHROMA_WINDOW / sr), CHROMA_WINDOW / 2 - 1);
136
+ const binPC = new Int8Array(maxBin + 1);
137
+ for (let bin = minBin; bin <= maxBin; bin++) {
138
+ const freq = bin * sr / CHROMA_WINDOW;
139
+ if (freq > 30) {
140
+ const midi = 12 * Math.log2(freq / 440) + 69;
141
+ binPC[bin] = (Math.round(midi) % 12 + 12) % 12;
142
+ } else binPC[bin] = -1;
143
+ }
144
+ const fftBuf = new Float64Array(CHROMA_WINDOW * 2);
145
+ for (let f = 0; f < numFrames; f++) {
146
+ const offset = f * CHROMA_HOP;
147
+ const chroma = new Array(12).fill(0);
148
+ let rmsSum = 0;
149
+ for (let i = 0; i < CHROMA_WINDOW; i++) {
150
+ const s = data[offset + i];
151
+ fftBuf[2 * i] = s * hann[i];
152
+ fftBuf[2 * i + 1] = 0;
153
+ rmsSum += s * s;
154
+ }
155
+ const rms = Math.sqrt(rmsSum / CHROMA_WINDOW);
156
+ if (rms < 5e-3) {
157
+ frames.push({ time: offset / sr, chroma, rms });
158
+ continue;
159
+ }
160
+ fft(fftBuf, CHROMA_WINDOW);
161
+ for (let bin = minBin; bin <= maxBin; bin++) {
162
+ const pc = binPC[bin];
163
+ if (pc < 0) continue;
164
+ const re = fftBuf[2 * bin], im = fftBuf[2 * bin + 1];
165
+ chroma[pc] += re * re + im * im;
166
+ }
167
+ let maxVal = 0;
168
+ for (let i = 0; i < 12; i++) if (chroma[i] > maxVal) maxVal = chroma[i];
169
+ if (maxVal > 0) for (let i = 0; i < 12; i++) chroma[i] /= maxVal;
170
+ frames.push({ time: offset / sr, chroma, rms });
171
+ }
172
+ return frames;
173
+ }
174
+ function estimateKey(avgChroma) {
175
+ let bestKey = "C", bestTonality = "major", bestCorr = -Infinity;
176
+ for (let root = 0; root < 12; root++) {
177
+ for (const [profile, tonality] of [[KK_MAJOR, "major"], [KK_MINOR, "minor"]]) {
178
+ const rotated = new Array(12);
179
+ for (let i = 0; i < 12; i++) rotated[i] = avgChroma[(i + root) % 12];
180
+ const corr = pearson(rotated, profile);
181
+ if (corr > bestCorr) {
182
+ bestCorr = corr;
183
+ bestKey = NOTE_NAMES[root];
184
+ bestTonality = tonality;
185
+ }
186
+ }
187
+ }
188
+ return { key: bestKey, tonality: bestTonality, confidence: bestCorr };
189
+ }
190
+ function pearson(x, y) {
191
+ const n = x.length;
192
+ let sx = 0, sy = 0, sxy = 0, sx2 = 0, sy2 = 0;
193
+ for (let i = 0; i < n; i++) {
194
+ sx += x[i];
195
+ sy += y[i];
196
+ sxy += x[i] * y[i];
197
+ sx2 += x[i] * x[i];
198
+ sy2 += y[i] * y[i];
199
+ }
200
+ const num = n * sxy - sx * sy;
201
+ const den = Math.sqrt((n * sx2 - sx * sx) * (n * sy2 - sy * sy));
202
+ return den === 0 ? 0 : num / den;
203
+ }
204
+ var KEY_TO_SEMI = { C: 0, "C#": 1, Db: 1, D: 2, "D#": 3, Eb: 3, E: 4, F: 5, "F#": 6, Gb: 6, G: 7, "G#": 8, Ab: 8, A: 9, "A#": 10, Bb: 10, B: 11 };
205
+ function computeCorrections(contour, key, tonality, mode) {
206
+ const keyRoot = KEY_TO_SEMI[key] ?? 0;
207
+ const intervals = tonality === "major" ? [0, 2, 4, 5, 7, 9, 11] : [0, 2, 3, 5, 7, 8, 10];
208
+ const scaleNotes = intervals.map((i) => (keyRoot + i) % 12);
209
+ return contour.map((frame) => {
210
+ if (frame.midi < 0) return { ...frame, targetMidi: -1, centsOff: 0, corrSemitones: 0 };
211
+ const midi = frame.midi, noteNum = Math.round(midi);
212
+ let targetMidi;
213
+ if (mode === "nearest") {
214
+ targetMidi = noteNum;
215
+ } else {
216
+ let bestDist = 999, bestNote = noteNum;
217
+ for (let off = -2; off <= 2; off++) {
218
+ const cand = noteNum + off;
219
+ if (scaleNotes.includes((cand % 12 + 12) % 12)) {
220
+ const dist = Math.abs(midi - cand);
221
+ if (dist < bestDist) {
222
+ bestDist = dist;
223
+ bestNote = cand;
224
+ }
225
+ }
226
+ }
227
+ targetMidi = bestNote;
228
+ }
229
+ return { ...frame, targetMidi, centsOff: (midi - targetMidi) * 100, corrSemitones: targetMidi - midi };
230
+ });
231
+ }
232
+ function buildSmoothRegions(corrections, corrSpeed, sr) {
233
+ const speed = corrSpeed / 100, SMOOTH_FRAMES = 24, MIN_CENTS = 10;
234
+ const regions = [];
235
+ const numRegions = Math.ceil(corrections.length / SMOOTH_FRAMES);
236
+ for (let r = 0; r < numRegions; r++) {
237
+ const start = r * SMOOTH_FRAMES, end = Math.min(start + SMOOTH_FRAMES, corrections.length);
238
+ let sumCorr = 0, voicedCount = 0;
239
+ for (let i = start; i < end; i++) {
240
+ const c = corrections[i];
241
+ if (c.midi > 0 && c.corrSemitones !== 0) {
242
+ sumCorr += c.corrSemitones;
243
+ voicedCount++;
244
+ }
245
+ }
246
+ if (voicedCount < SMOOTH_FRAMES * 0.3) continue;
247
+ const avgCorr = sumCorr / voicedCount, avgCents = avgCorr * 100;
248
+ if (Math.abs(avgCents) < MIN_CENTS) continue;
249
+ const startSample = start * YIN_HOP, endSample = end * YIN_HOP;
250
+ regions.push({ startSample, endSample, semitones: avgCorr * speed, avgCents, startTime: startSample / sr, endTime: endSample / sr, frameStart: start, frameEnd: end });
251
+ }
252
+ return regions;
253
+ }
254
+ function computeBarMetrics(corrections, barMapping, barSpeeds, sr) {
255
+ return barMapping.map((bar, b) => {
256
+ const barStartSec = bar.sampleStart / sr, barEndSec = (bar.sampleStart + bar.duration) / sr;
257
+ let sumFreq = 0, sumMidi = 0, sumCentsOff = 0, sumAbsCorr = 0, voicedCount = 0, totalCount = 0;
258
+ const pcCounts = new Float32Array(12);
259
+ for (const frame of corrections) {
260
+ if (frame.time >= barStartSec && frame.time < barEndSec) {
261
+ totalCount++;
262
+ if (frame.midi > 0) {
263
+ voicedCount++;
264
+ sumFreq += frame.freq;
265
+ sumMidi += frame.midi;
266
+ sumCentsOff += frame.centsOff;
267
+ sumAbsCorr += Math.abs(frame.corrSemitones);
268
+ pcCounts[(Math.round(frame.midi) % 12 + 12) % 12]++;
269
+ }
270
+ }
271
+ }
272
+ const barSpeed = barSpeeds[b]?.speed ?? 1;
273
+ let maxPC = 0;
274
+ for (let i = 1; i < 12; i++) if (pcCounts[i] > pcCounts[maxPC]) maxPC = i;
275
+ return {
276
+ barIndex: b,
277
+ avgFreq: voicedCount > 0 ? sumFreq / voicedCount : 0,
278
+ avgMidi: voicedCount > 0 ? sumMidi / voicedCount : 0,
279
+ voicedRatio: totalCount > 0 ? voicedCount / totalCount : 0,
280
+ avgCentsOff: voicedCount > 0 ? sumCentsOff / voicedCount : 0,
281
+ avgAbsCorrection: voicedCount > 0 ? sumAbsCorr / voicedCount : 0,
282
+ dominantNote: NOTE_NAMES[maxPC],
283
+ barSpeed,
284
+ barPitchCompensation: -12 * Math.log2(barSpeed)
285
+ };
286
+ });
287
+ }
288
+ function computeBarChroma(chromaFrames, barMapping, sr) {
289
+ return barMapping.map((bar, b) => {
290
+ const barStartSec = bar.sampleStart / sr, barEndSec = (bar.sampleStart + bar.duration) / sr;
291
+ const bc = new Array(12).fill(0);
292
+ let count = 0;
293
+ for (const f of chromaFrames) {
294
+ if (f.time >= barStartSec && f.time < barEndSec && f.rms > 5e-3) {
295
+ for (let i = 0; i < 12; i++) bc[i] += f.chroma[i];
296
+ count++;
297
+ }
298
+ }
299
+ if (count > 0) for (let i = 0; i < 12; i++) bc[i] /= count;
300
+ let maxIdx = 0;
301
+ for (let i = 1; i < 12; i++) if (bc[i] > bc[maxIdx]) maxIdx = i;
302
+ return { barIndex: b, chroma: bc, dominantNote: NOTE_NAMES[maxIdx] };
303
+ });
304
+ }
305
+ function progress(step, totalSteps, text, detail) {
306
+ self.postMessage({ type: "progress", step, totalSteps, pct: Math.round(step / totalSteps * 100), text, detail });
307
+ }
308
+ self.onmessage = (e) => {
309
+ const { type, payload } = e.data;
310
+ if (type === "analyze") {
311
+ const { vocalData, precomputedContour, sampleRate, key, tonality, corrMode, corrSpeed, barMapping, barSpeeds } = payload;
312
+ const t0 = performance.now();
313
+ const hasPrecomputed = precomputedContour && precomputedContour.length > 0;
314
+ const vocalSamples = vocalData ? new Float32Array(vocalData).length : hasPrecomputed ? precomputedContour.length * YIN_HOP : 0;
315
+ const durationSec = vocalSamples / sampleRate;
316
+ const STEPS = 5;
317
+ let vocalChromaFrames = [];
318
+ let vocalAvgChroma = new Array(12).fill(0);
319
+ let vocalKeyEst = { key, tonality, confidence: 0 };
320
+ let vocalBarChroma = [];
321
+ if (vocalData) {
322
+ progress(0, STEPS, "Computing vocal chroma (FFT)", `2048-sample window \xB7 hop ${CHROMA_HOP} (~${Math.round(sampleRate / CHROMA_HOP)}fps) \xB7 ${Math.ceil(vocalSamples / CHROMA_HOP)} frames`);
323
+ vocalChromaFrames = computeChroma(new Float32Array(vocalData), sampleRate);
324
+ let totalW = 0;
325
+ for (const f of vocalChromaFrames) {
326
+ if (f.rms > 5e-3) {
327
+ for (let i = 0; i < 12; i++) vocalAvgChroma[i] += f.chroma[i] * f.rms;
328
+ totalW += f.rms;
329
+ }
330
+ }
331
+ if (totalW > 0) for (let i = 0; i < 12; i++) vocalAvgChroma[i] /= totalW;
332
+ vocalKeyEst = estimateKey(vocalAvgChroma);
333
+ vocalBarChroma = computeBarChroma(vocalChromaFrames, barMapping, sampleRate);
334
+ } else if (hasPrecomputed) {
335
+ progress(0, STEPS, "Estimating key from Basic Pitch notes", `${precomputedContour.length} frames`);
336
+ const pcCounts = new Array(12).fill(0);
337
+ for (const f of precomputedContour) {
338
+ if (f.midi > 0) pcCounts[(Math.round(f.midi) % 12 + 12) % 12]++;
339
+ }
340
+ const total = pcCounts.reduce((s, v) => s + v, 0);
341
+ if (total > 0) {
342
+ for (let i = 0; i < 12; i++) vocalAvgChroma[i] = pcCounts[i] / total;
343
+ }
344
+ vocalKeyEst = estimateKey(vocalAvgChroma);
345
+ }
346
+ const CHROMA_KEY_THRESHOLD = 0.5;
347
+ const effectiveKey = vocalKeyEst.confidence >= CHROMA_KEY_THRESHOLD ? vocalKeyEst.key : key;
348
+ const effectiveTonality = vocalKeyEst.confidence >= CHROMA_KEY_THRESHOLD ? vocalKeyEst.tonality : tonality;
349
+ let pitchContour;
350
+ if (hasPrecomputed) {
351
+ progress(1, STEPS, "Using Basic Pitch contour", `${precomputedContour.length} frames from ML model \xB7 key: ${effectiveKey}${effectiveTonality === "minor" ? "m" : ""}`);
352
+ pitchContour = precomputedContour;
353
+ } else {
354
+ progress(1, STEPS, "Detecting pitch (YIN F0)", `${vocalSamples.toLocaleString()} samples \xB7 ${durationSec.toFixed(1)}s audio \xB7 key: ${effectiveKey}${effectiveTonality === "minor" ? "m" : ""} (${vocalKeyEst.confidence >= CHROMA_KEY_THRESHOLD ? "chroma" : "API"})`);
355
+ pitchContour = vocalData ? detectPitchContour(new Float32Array(vocalData), sampleRate) : [];
356
+ }
357
+ const voicedCount = pitchContour.filter((f) => f.midi > 0).length;
358
+ progress(2, STEPS, "Computing corrections", `${pitchContour.length} frames \xB7 ${voicedCount} voiced (${pitchContour.length > 0 ? Math.round(voicedCount / pitchContour.length * 100) : 0}%) \xB7 key: ${effectiveKey}${effectiveTonality === "minor" ? "m" : ""}`);
359
+ const corrections = computeCorrections(pitchContour, effectiveKey, effectiveTonality, corrMode);
360
+ const correctionRegions = buildSmoothRegions(corrections, corrSpeed, sampleRate);
361
+ progress(3, STEPS, "Computing per-bar metrics", `${barMapping.length} bars \xB7 ${correctionRegions.length} correction regions`);
362
+ const barMetrics = computeBarMetrics(corrections, barMapping, barSpeeds, sampleRate);
363
+ const elapsed = performance.now() - t0;
364
+ progress(4, STEPS, "Packaging results", `Completed in ${(elapsed / 1e3).toFixed(1)}s`);
365
+ self.postMessage({
366
+ type: "result",
367
+ elapsed,
368
+ result: {
369
+ pitchContour,
370
+ corrections,
371
+ correctionRegions,
372
+ chromaVocals: { frames: vocalChromaFrames, averageChroma: vocalAvgChroma, estimatedKey: vocalKeyEst.key, estimatedTonality: vocalKeyEst.tonality, keyConfidence: vocalKeyEst.confidence, barChroma: vocalBarChroma },
373
+ effectiveKey,
374
+ effectiveTonality,
375
+ barMetrics
376
+ }
377
+ });
378
+ }
379
+ };
@@ -0,0 +1 @@
1
+ const P=!1,R=!1;let g=!1;const _=.01;class M extends AudioWorkletProcessor{bufferQueue=[];currentBuffer=null;currentBufferPos=0;playing=!1;globalPlaybackRate=1;speedRatio_SeedMixMatching_Resolved=1;speedRatio_ManualScheduling=1;startTime=void 0;stopTimeTriggeredFromBufferClearing=void 0;fadeOutStartTime=void 0;bufferAlmostEndEventFired=!1;bufferPlayedProgress_1_4_EventFired=!1;bufferPlayedProgress_2_4_EventFired=!1;bufferPlayedProgress_3_4_EventFired=!1;playQuantisedSpeedAs="quantised";constructor(){super(),this.port.onmessage=e=>{if(e.data.type==="to-buffer-processor-event-add-buffer")this.bufferQueue.push(e.data.detail),this.port.postMessage({type:"from-buffer-processor-event-logOnSafari",detail:{message:`added Buffer to processor: T${e.data.detail.trackIndex}S${e.data.detail.sequenceIdx}C${e.data.detail.chunkIdx} currentTime[${currentTime}]`},signature:"to-buffer-processor-event-add-buffer-cb"});else if(e.data.type==="to-buffer-processor-event-set-start-time")this.port.postMessage({type:"from-buffer-processor-event-logOnSafari",detail:{message:`processor[x] receive setStateTime: currentTime[${currentTime}] at ${this.startTime}`},signature:"to-buffer-processor-event-set-start-time-cb"}),this.startTime=e.data.startTime;else if(e.data.type==="to-buffer-processor-event-setPlaybackRate")this.globalPlaybackRate=e.data.playbackRate;else if(e.data.type==="to-buffer-processor-event-update-manual-schedule-speed"){this.currentBuffer?.sequenceIdx===e.data.sequenceIdx&&(this.speedRatio_ManualScheduling=e.data.speedRatio_ManualScheduling);const r=this.bufferQueue.find(s=>s.chunkIdx===e.data.chunkIdx&&s.sequenceIdx===e.data.sequenceIdx);r&&(r.speedRatio_ManualScheduling=e.data.speedRatio_ManualScheduling)}else e.data.type==="to-buffer-processor-event-next-buffer-is-not-ready-for-exhausted-queue"?this.bufferAlmostEndEventFired=!1:e.data.type==="to-buffer-processor-event-remove-pending-buffer"?(this.bufferQueue=[],this.bufferAlmostEndEventFired=!1):e.data.type==="to-buffer-processor-event-cleanAllBuffersAndStop"?this.cleanUpBuffers():e.data.type==="to-buffer-processor-event-fade-out-and-clean-all-buffers"&&(this.fadeOutStartTime=currentTime,this.stopTimeTriggeredFromBufferClearing=currentTime+_)}}cleanUpBuffers(){this.stopTimeTriggeredFromBufferClearing=void 0,this.fadeOutStartTime=void 0,this.bufferQueue=[],this.playing=!1,this.currentBuffer=null,this.currentBufferPos=0,this.speedRatio_SeedMixMatching_Resolved=1,this.speedRatio_ManualScheduling=1,this.startTime=void 0,this.fadeOutStartTime=void 0,this.bufferAlmostEndEventFired=!1,this.bufferPlayedProgress_1_4_EventFired=!1,this.bufferPlayedProgress_2_4_EventFired=!1,this.bufferPlayedProgress_3_4_EventFired=!1,this.port.postMessage({type:"from-buffer-processor-event-logOnSafari",detail:{message:`processor[x] just cleanAllBuffersAndStop currentTime[${currentTime}]`},signature:"CleanupBuffers"})}calculateFadeOutGain(){if(!this.fadeOutStartTime||!this.stopTimeTriggeredFromBufferClearing)return 1;const e=currentTime-this.fadeOutStartTime;return 1-Math.min(e/_,1)}loadNextBuffer(e,r=0){const s=this.currentBuffer;try{if(this.bufferQueue.length>0?this.currentBuffer=this.bufferQueue.shift():this.currentBuffer=null,this.currentBuffer&&this.currentBuffer.buffer&&this.currentBuffer.rampToZeroBeforeEnd)for(let a=0;a<this.currentBuffer.buffer.length;a++){const i=this.currentBuffer.buffer[a];if(i&&i.length>0){const n=Math.max(0,i.length-192),u=i.length-n;for(let f=0;f<u;f++){const o=1-f/u;i[n+f]*=o}}}if(this.currentBuffer&&this.currentBuffer.buffer&&this.currentBuffer.rampFromZeroAtStart)for(let a=0;a<this.currentBuffer.buffer.length;a++){const i=this.currentBuffer.buffer[a];if(i&&i.length>0){const n=Math.min(192,i.length);for(let u=0;u<n;u++){const f=u/n;i[u]*=f}}}this.currentBufferPos=this.currentBuffer?.skipSamplesAtStart>0?this.currentBuffer?.skipSamplesAtStart:r,this.bufferAlmostEndEventFired=!1,this.bufferPlayedProgress_1_4_EventFired=!1,this.bufferPlayedProgress_2_4_EventFired=!1,this.bufferPlayedProgress_3_4_EventFired=!1,this.currentBuffer?this.port.postMessage({type:"from-buffer-processor-event-bufferStarted",detail:{trackIndex:this.currentBuffer.trackIndex,sequenceIdx:this.currentBuffer.sequenceIdx,chunkIdx:this.currentBuffer.chunkIdx,chunkId:this.currentBuffer.chunkId,timeStamp:currentTime,_internalSpeed:{speedRatio_SeedMixMatching_Resolved:this.currentBuffer.playQuantisedSpeedAs==="quantised"?this.currentBuffer.speedRatio_SeedMixMatching:this.currentBuffer.playQuantisedSpeedAs==="seed"?this.currentBuffer.speedRatio_SeedMixMatching_SeedIsPlayingAsUnquantised:this.currentBuffer.playQuantisedSpeedAs==="mix"?this.currentBuffer.speedRatio_SeedMixMatching_MixIsPlayingAsUnquantised:void 0,isPlayingQuantisedAs:this.currentBuffer.playQuantisedSpeedAs,playbackRate:this.globalPlaybackRate,speedRatio_ManualScheduling:this.currentBuffer.speedRatio_ManualScheduling},trackId:this.currentBuffer.trackId,stemId:this.currentBuffer.stemId,signature:e,barSequenceUUID:this.currentBuffer.barSequenceUUID}}):this.port.postMessage({type:"from-buffer-processor-event-nextBufferNotReady",detail:{trackIndex:s?.trackIndex,sequenceIdx:s?.sequenceIdx,chunkIdx:s?.chunkIdx,chunkId:s?.chunkId,timeStamp:currentTime,_internalSpeed:{speedRatio_SeedMixMatching_Resolved:void 0,isPlayingQuantisedAs:void 0,playbackRate:void 0,speedRatio_ManualScheduling:void 0},trackId:s?.trackId,stemId:s?.stemId,signature:e,barSequenceUUID:s?.barSequenceUUID}});let d=!1;this.currentBuffer&&this.playQuantisedSpeedAs!==this.currentBuffer.playQuantisedSpeedAs&&(this.playQuantisedSpeedAs=this.currentBuffer.playQuantisedSpeedAs,d=!0),(this.currentBuffer&&(this.speedRatio_SeedMixMatching_Resolved!==this.currentBuffer?.speedRatio_SeedMixMatching&&this.currentBuffer?.playQuantisedSpeedAs==="quantised"||this.speedRatio_SeedMixMatching_Resolved!==this.currentBuffer?.speedRatio_SeedMixMatching_SeedIsPlayingAsUnquantised&&this.currentBuffer?.playQuantisedSpeedAs==="seed"||this.speedRatio_SeedMixMatching_Resolved!==this.currentBuffer?.speedRatio_SeedMixMatching_MixIsPlayingAsUnquantised&&this.currentBuffer?.playQuantisedSpeedAs==="mix"||this.speedRatio_ManualScheduling!==this.currentBuffer?.speedRatio_ManualScheduling)||d)&&(this.playQuantisedSpeedAs==="quantised"?(this.speedRatio_SeedMixMatching_Resolved=this.currentBuffer.speedRatio_SeedMixMatching,this.currentBuffer.speedRatio_ManualScheduling!==void 0&&this.currentBuffer.speedRatio_ManualScheduling!==null?this.speedRatio_ManualScheduling=this.currentBuffer.speedRatio_ManualScheduling:console.log(this.currentBuffer)):this.playQuantisedSpeedAs==="seed"?(this.speedRatio_SeedMixMatching_Resolved=this.currentBuffer.speedRatio_SeedMixMatching_SeedIsPlayingAsUnquantised,this.currentBuffer.speedRatio_ManualScheduling!==void 0&&this.currentBuffer.speedRatio_ManualScheduling!==null?this.speedRatio_ManualScheduling=this.currentBuffer.speedRatio_ManualScheduling:console.log(this.currentBuffer)):this.playQuantisedSpeedAs==="mix"?(this.speedRatio_SeedMixMatching_Resolved=this.currentBuffer.speedRatio_SeedMixMatching_MixIsPlayingAsUnquantised,this.currentBuffer.speedRatio_ManualScheduling!==void 0&&this.currentBuffer.speedRatio_ManualScheduling!==null?this.speedRatio_ManualScheduling=this.currentBuffer.speedRatio_ManualScheduling:console.log(this.currentBuffer)):(this.speedRatio_SeedMixMatching_Resolved=1,this.currentBuffer.speedRatio_ManualScheduling!==void 0&&this.currentBuffer.speedRatio_ManualScheduling!==null?this.speedRatio_ManualScheduling=this.currentBuffer.speedRatio_ManualScheduling:console.log(this.currentBuffer)))}catch(d){console.log("signature, ",e),console.error(d)}}postMessage_BlockProcessEvent(e,r){this.port.postMessage({type:e,detail:{trackIndex:r.trackIndex,sequenceIdx:r.sequenceIdx,chunkIdx:r.chunkIdx,chunkId:r.chunkId,timeStamp:currentTime,_internalSpeed:{speedRatio_SeedMixMatching_Resolved:this.speedRatio_SeedMixMatching_Resolved,isPlayingQuantisedAs:this.playQuantisedSpeedAs,playbackRate:this.globalPlaybackRate,speedRatio_ManualScheduling:this.speedRatio_ManualScheduling},trackId:r.trackId,stemId:r.stemId,signature:"BLOCK Process",barSequenceUUID:r.barSequenceUUID}})}process(e,r){const s=r[0];!this.playing&&this.startTime!==void 0&&currentTime>=this.startTime&&this.bufferQueue.length>0&&(this.playing=!0,this.port.postMessage({type:"from-buffer-processor-event-logOnSafari",detail:{message:`startTime triggered: currentTime:${currentTime}, startTime:${this.startTime}`}})),this.stopTimeTriggeredFromBufferClearing&&this.stopTimeTriggeredFromBufferClearing<currentTime&&this.cleanUpBuffers();const d=this.calculateFadeOutGain();if(this.playing&&(this.currentBuffer||this.bufferQueue.length>0)&&(!this.currentBuffer&&this.bufferQueue.length>0&&this.loadNextBuffer("currentBuffer is undefined/null",0),this.currentBuffer&&this.currentBuffer.buffer)){const l=s[0].length,a=s.length;for(let i=0;i<l;i++)for(let n=0;n<a;n++){const u=s[n],f=this.currentBufferPos,o=Math.floor(f),m=f-o,p=o+1,t=this.currentBuffer?.buffer?.[n];if(t&&o<t.length){const c=t[o],b=p<t.length?t[p]:c,S=c+m*(b-c);if(u[i]=S*d,n===s.length-1){const h=this.globalPlaybackRate*this.speedRatio_SeedMixMatching_Resolved*this.speedRatio_ManualScheduling;this.currentBufferPos+=h}const B=1024*6*(this.globalPlaybackRate*this.speedRatio_SeedMixMatching_Resolved*this.speedRatio_ManualScheduling);if(t&&this.currentBufferPos>=t.length-B&&!this.bufferAlmostEndEventFired&&this.currentBuffer.chunkIdx!==-1&&(g&&(g=!1,console.log(`audit: fire from-buffer-processor-event-bufferAlmostEnd retry with ${this.currentBuffer?.chunkIdx}`)),this.bufferAlmostEndEventFired=!0,this.postMessage_BlockProcessEvent("from-buffer-processor-event-bufferAlmostEnd",this.currentBuffer)),this.bufferQueue.length===0&&!this.bufferAlmostEndEventFired&&this.currentBuffer.chunkIdx!==-1&&(this.bufferAlmostEndEventFired=!0,this.postMessage_BlockProcessEvent("from-buffer-processor-event-buffer-queue-is-emptied",this.currentBuffer)),t&&this.currentBufferPos>=t.length*.75&&!this.bufferPlayedProgress_3_4_EventFired&&this.currentBuffer.chunkIdx!==-1?(this.bufferPlayedProgress_3_4_EventFired=!0,this.bufferPlayedProgress_2_4_EventFired=!0,this.bufferPlayedProgress_1_4_EventFired=!0,this.postMessage_BlockProcessEvent("from-buffer-processor-event-bufferPlayed_3/4",this.currentBuffer)):t&&this.currentBufferPos>=t.length*.5&&!this.bufferPlayedProgress_2_4_EventFired&&this.currentBuffer.chunkIdx!==-1?(this.bufferPlayedProgress_2_4_EventFired=!0,this.bufferPlayedProgress_1_4_EventFired=!0,this.postMessage_BlockProcessEvent("from-buffer-processor-event-bufferPlayed_2/4",this.currentBuffer)):t&&this.currentBufferPos>=t.length*.25&&!this.bufferPlayedProgress_1_4_EventFired&&this.currentBuffer.chunkIdx!==-1&&(this.bufferPlayedProgress_1_4_EventFired=!0,this.postMessage_BlockProcessEvent("from-buffer-processor-event-bufferPlayed_1/4",this.currentBuffer)),t&&this.currentBufferPos>=t.length&&n===a-1){this.postMessage_BlockProcessEvent("from-buffer-processor-event-bufferEnded",this.currentBuffer);const h=this.currentBufferPos-t.length;this.loadNextBuffer("currentBufferPos > buffer length",h)}}else u[i]=0}}return!0}}registerProcessor("buffer-player-processor",M);