@waveform-playlist/spectrogram 7.1.1 → 7.1.3
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/index.js +207 -129
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +212 -130
- package/dist/index.mjs.map +1 -1
- package/dist/worker/spectrogram.worker.mjs +68 -8
- package/dist/worker/spectrogram.worker.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3606,7 +3606,14 @@ var ModalButton = import_styled_components2.default.button`
|
|
|
3606
3606
|
}
|
|
3607
3607
|
`;
|
|
3608
3608
|
var FFT_SIZES = [256, 512, 1024, 2048, 4096, 8192];
|
|
3609
|
-
var WINDOW_FUNCTIONS = [
|
|
3609
|
+
var WINDOW_FUNCTIONS = [
|
|
3610
|
+
"hann",
|
|
3611
|
+
"hamming",
|
|
3612
|
+
"blackman",
|
|
3613
|
+
"blackman-harris",
|
|
3614
|
+
"bartlett",
|
|
3615
|
+
"rectangular"
|
|
3616
|
+
];
|
|
3610
3617
|
var FREQ_SCALES = ["linear", "logarithmic", "mel", "bark", "erb"];
|
|
3611
3618
|
var COLOR_MAPS = ["viridis", "magma", "inferno", "grayscale", "igray", "roseus"];
|
|
3612
3619
|
var SpectrogramSettingsModal = ({
|
|
@@ -3628,7 +3635,9 @@ var SpectrogramSettingsModal = ({
|
|
|
3628
3635
|
const [gainDb, setGainDb] = (0, import_react.useState)(config.gainDb ?? 20);
|
|
3629
3636
|
const [rangeDb, setRangeDb] = (0, import_react.useState)(config.rangeDb ?? 80);
|
|
3630
3637
|
const [zeroPadding, setZeroPadding] = (0, import_react.useState)(config.zeroPaddingFactor ?? 2);
|
|
3631
|
-
const [hopSize, setHopSize] = (0, import_react.useState)(
|
|
3638
|
+
const [hopSize, setHopSize] = (0, import_react.useState)(
|
|
3639
|
+
config.hopSize ?? Math.floor((config.fftSize ?? 2048) / 4)
|
|
3640
|
+
);
|
|
3632
3641
|
const [showLabels, setShowLabels] = (0, import_react.useState)(config.labels ?? false);
|
|
3633
3642
|
(0, import_react.useEffect)(() => {
|
|
3634
3643
|
setFftSize(config.fftSize ?? 2048);
|
|
@@ -3682,11 +3691,18 @@ var SpectrogramSettingsModal = ({
|
|
|
3682
3691
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(FormGrid, { children: [
|
|
3683
3692
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Field, { children: [
|
|
3684
3693
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { children: "FFT Size" }),
|
|
3685
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3694
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3695
|
+
Select,
|
|
3696
|
+
{
|
|
3697
|
+
value: fftSize,
|
|
3698
|
+
onChange: (e) => {
|
|
3699
|
+
const v = Number(e.target.value);
|
|
3700
|
+
setFftSize(v);
|
|
3701
|
+
setHopSize(Math.floor(v / 4));
|
|
3702
|
+
},
|
|
3703
|
+
children: FFT_SIZES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: s, children: s }, s))
|
|
3704
|
+
}
|
|
3705
|
+
)
|
|
3690
3706
|
] }),
|
|
3691
3707
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Field, { children: [
|
|
3692
3708
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { children: "Hop Size" }),
|
|
@@ -3707,11 +3723,25 @@ var SpectrogramSettingsModal = ({
|
|
|
3707
3723
|
] }),
|
|
3708
3724
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Field, { children: [
|
|
3709
3725
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { children: "Frequency Scale" }),
|
|
3710
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3726
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3727
|
+
Select,
|
|
3728
|
+
{
|
|
3729
|
+
value: freqScale,
|
|
3730
|
+
onChange: (e) => setFreqScale(e.target.value),
|
|
3731
|
+
children: FREQ_SCALES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: s, children: s }, s))
|
|
3732
|
+
}
|
|
3733
|
+
)
|
|
3711
3734
|
] }),
|
|
3712
3735
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Field, { children: [
|
|
3713
3736
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { children: "Color Map" }),
|
|
3714
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3737
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3738
|
+
Select,
|
|
3739
|
+
{
|
|
3740
|
+
value: localColorMap,
|
|
3741
|
+
onChange: (e) => setLocalColorMap(e.target.value),
|
|
3742
|
+
children: COLOR_MAPS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: c, children: c }, c))
|
|
3743
|
+
}
|
|
3744
|
+
)
|
|
3715
3745
|
] }),
|
|
3716
3746
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Field, { children: [
|
|
3717
3747
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { children: "Min Frequency (Hz)" }),
|
|
@@ -3770,7 +3800,14 @@ var SpectrogramSettingsModal = ({
|
|
|
3770
3800
|
)
|
|
3771
3801
|
] }),
|
|
3772
3802
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Field, { $span: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(CheckboxLabel, { children: [
|
|
3773
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3803
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3804
|
+
"input",
|
|
3805
|
+
{
|
|
3806
|
+
type: "checkbox",
|
|
3807
|
+
checked: showLabels,
|
|
3808
|
+
onChange: (e) => setShowLabels(e.target.checked)
|
|
3809
|
+
}
|
|
3810
|
+
),
|
|
3774
3811
|
"Show Frequency Labels"
|
|
3775
3812
|
] }) })
|
|
3776
3813
|
] }),
|
|
@@ -3893,10 +3930,7 @@ function createSpectrogramWorker(worker) {
|
|
|
3893
3930
|
});
|
|
3894
3931
|
},
|
|
3895
3932
|
registerCanvas(canvasId, canvas) {
|
|
3896
|
-
worker.postMessage(
|
|
3897
|
-
{ type: "register-canvas", canvasId, canvas },
|
|
3898
|
-
[canvas]
|
|
3899
|
-
);
|
|
3933
|
+
worker.postMessage({ type: "register-canvas", canvasId, canvas }, [canvas]);
|
|
3900
3934
|
},
|
|
3901
3935
|
unregisterCanvas(canvasId) {
|
|
3902
3936
|
worker.postMessage({ type: "unregister-canvas", canvasId });
|
|
@@ -3950,25 +3984,29 @@ function createSpectrogramWorker(worker) {
|
|
|
3950
3984
|
|
|
3951
3985
|
// src/SpectrogramProvider.tsx
|
|
3952
3986
|
var import_react2 = require("react");
|
|
3987
|
+
var import_core = require("@waveform-playlist/core");
|
|
3953
3988
|
var import_browser = require("@waveform-playlist/browser");
|
|
3954
3989
|
var import_browser2 = require("@waveform-playlist/browser");
|
|
3955
3990
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
3956
3991
|
var import_meta = {};
|
|
3992
|
+
function extractChunkNumber(canvasId) {
|
|
3993
|
+
const match = canvasId.match(/chunk(\d+)$/);
|
|
3994
|
+
if (!match) {
|
|
3995
|
+
console.warn(`[spectrogram] Unexpected canvas ID format: ${canvasId}`);
|
|
3996
|
+
return 0;
|
|
3997
|
+
}
|
|
3998
|
+
return parseInt(match[1], 10);
|
|
3999
|
+
}
|
|
3957
4000
|
var SpectrogramProvider = ({
|
|
3958
4001
|
config: spectrogramConfig,
|
|
3959
4002
|
colorMap: spectrogramColorMap,
|
|
3960
4003
|
children
|
|
3961
4004
|
}) => {
|
|
3962
|
-
const {
|
|
3963
|
-
tracks,
|
|
3964
|
-
waveHeight,
|
|
3965
|
-
samplesPerPixel,
|
|
3966
|
-
isReady,
|
|
3967
|
-
mono,
|
|
3968
|
-
controls
|
|
3969
|
-
} = (0, import_browser2.usePlaylistData)();
|
|
4005
|
+
const { tracks, waveHeight, samplesPerPixel, isReady, mono, controls } = (0, import_browser2.usePlaylistData)();
|
|
3970
4006
|
const { scrollContainerRef } = (0, import_browser2.usePlaylistControls)();
|
|
3971
|
-
const [spectrogramDataMap, setSpectrogramDataMap] = (0, import_react2.useState)(
|
|
4007
|
+
const [spectrogramDataMap, setSpectrogramDataMap] = (0, import_react2.useState)(
|
|
4008
|
+
/* @__PURE__ */ new Map()
|
|
4009
|
+
);
|
|
3972
4010
|
const [trackSpectrogramOverrides, setTrackSpectrogramOverrides] = (0, import_react2.useState)(/* @__PURE__ */ new Map());
|
|
3973
4011
|
const spectrogramCanvasRegistryRef = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
|
|
3974
4012
|
const [spectrogramCanvasVersion, setSpectrogramCanvasVersion] = (0, import_react2.useState)(0);
|
|
@@ -4117,9 +4155,7 @@ var SpectrogramProvider = ({
|
|
|
4117
4155
|
if (mode === "waveform") return;
|
|
4118
4156
|
const trackConfigChanged = configChanged && currentKeys.get(track.id) !== prevKeys.get(track.id);
|
|
4119
4157
|
const trackFFTChanged = fftKeyChanged && currentFFTKeys.get(track.id) !== prevFFTKeys.get(track.id);
|
|
4120
|
-
const hasRegisteredCanvases = canvasVersionChanged && track.clips.some(
|
|
4121
|
-
(clip) => spectrogramCanvasRegistryRef.current.has(clip.id)
|
|
4122
|
-
);
|
|
4158
|
+
const hasRegisteredCanvases = canvasVersionChanged && track.clips.some((clip) => spectrogramCanvasRegistryRef.current.has(clip.id));
|
|
4123
4159
|
if (!trackConfigChanged && !hasRegisteredCanvases) return;
|
|
4124
4160
|
const cfg = trackSpectrogramOverrides.get(track.id)?.config ?? track.spectrogramConfig ?? spectrogramConfig ?? {};
|
|
4125
4161
|
const cm = trackSpectrogramOverrides.get(track.id)?.colorMap ?? track.spectrogramColorMap ?? spectrogramColorMap ?? "viridis";
|
|
@@ -4177,7 +4213,13 @@ var SpectrogramProvider = ({
|
|
|
4177
4213
|
} else {
|
|
4178
4214
|
for (let ch = 0; ch < clip.audioBuffer.numberOfChannels; ch++) {
|
|
4179
4215
|
channelSpectrograms.push(
|
|
4180
|
-
computeSpectrogram(
|
|
4216
|
+
computeSpectrogram(
|
|
4217
|
+
clip.audioBuffer,
|
|
4218
|
+
item.config,
|
|
4219
|
+
item.offsetSamples,
|
|
4220
|
+
item.durationSamples,
|
|
4221
|
+
ch
|
|
4222
|
+
)
|
|
4181
4223
|
);
|
|
4182
4224
|
}
|
|
4183
4225
|
}
|
|
@@ -4190,26 +4232,25 @@ var SpectrogramProvider = ({
|
|
|
4190
4232
|
}
|
|
4191
4233
|
return;
|
|
4192
4234
|
}
|
|
4193
|
-
const getVisibleChunkRange = (
|
|
4235
|
+
const getVisibleChunkRange = (channelInfo, clipPixelOffset = 0) => {
|
|
4194
4236
|
const container = scrollContainerRef.current;
|
|
4195
4237
|
if (!container) {
|
|
4196
|
-
return { visibleIndices: canvasWidths.map((_, i) => i), remainingIndices: [] };
|
|
4238
|
+
return { visibleIndices: channelInfo.canvasWidths.map((_, i) => i), remainingIndices: [] };
|
|
4197
4239
|
}
|
|
4198
4240
|
const scrollLeft = container.scrollLeft;
|
|
4199
4241
|
const viewportWidth = container.clientWidth;
|
|
4200
4242
|
const controlWidth = controls.show ? controls.width : 0;
|
|
4201
4243
|
const visibleIndices = [];
|
|
4202
4244
|
const remainingIndices = [];
|
|
4203
|
-
let
|
|
4204
|
-
|
|
4205
|
-
const chunkLeft =
|
|
4206
|
-
const chunkRight = chunkLeft + canvasWidths[i];
|
|
4245
|
+
for (let i = 0; i < channelInfo.canvasWidths.length; i++) {
|
|
4246
|
+
const chunkNumber = extractChunkNumber(channelInfo.canvasIds[i]);
|
|
4247
|
+
const chunkLeft = chunkNumber * import_core.MAX_CANVAS_WIDTH + controlWidth + clipPixelOffset;
|
|
4248
|
+
const chunkRight = chunkLeft + channelInfo.canvasWidths[i];
|
|
4207
4249
|
if (chunkRight > scrollLeft && chunkLeft < scrollLeft + viewportWidth) {
|
|
4208
4250
|
visibleIndices.push(i);
|
|
4209
4251
|
} else {
|
|
4210
4252
|
remainingIndices.push(i);
|
|
4211
4253
|
}
|
|
4212
|
-
offset += canvasWidths[i];
|
|
4213
4254
|
}
|
|
4214
4255
|
return { visibleIndices, remainingIndices };
|
|
4215
4256
|
};
|
|
@@ -4219,11 +4260,8 @@ var SpectrogramProvider = ({
|
|
|
4219
4260
|
const canvasWidths = indices.map((i) => channelInfo.canvasWidths[i]);
|
|
4220
4261
|
const globalPixelOffsets = [];
|
|
4221
4262
|
for (const idx of indices) {
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
offset += channelInfo.canvasWidths[j];
|
|
4225
|
-
}
|
|
4226
|
-
globalPixelOffsets.push(offset);
|
|
4263
|
+
const chunkNumber = extractChunkNumber(channelInfo.canvasIds[idx]);
|
|
4264
|
+
globalPixelOffsets.push(chunkNumber * import_core.MAX_CANVAS_WIDTH);
|
|
4227
4265
|
}
|
|
4228
4266
|
const colorLUT = getColorMap(item.colorMap);
|
|
4229
4267
|
await api.renderChunks({
|
|
@@ -4246,6 +4284,25 @@ var SpectrogramProvider = ({
|
|
|
4246
4284
|
const computeAsync = async () => {
|
|
4247
4285
|
const abortToken = { aborted: false };
|
|
4248
4286
|
backgroundRenderAbortRef.current = abortToken;
|
|
4287
|
+
const renderBackgroundBatches = async (channelRanges, cacheKey, item) => {
|
|
4288
|
+
const BATCH_SIZE = 4;
|
|
4289
|
+
for (const { ch, channelInfo, remainingIndices } of channelRanges) {
|
|
4290
|
+
for (let batchStart = 0; batchStart < remainingIndices.length; batchStart += BATCH_SIZE) {
|
|
4291
|
+
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return true;
|
|
4292
|
+
const batch = remainingIndices.slice(batchStart, batchStart + BATCH_SIZE);
|
|
4293
|
+
await new Promise((resolve) => {
|
|
4294
|
+
if (typeof requestIdleCallback === "function") {
|
|
4295
|
+
requestIdleCallback(() => resolve());
|
|
4296
|
+
} else {
|
|
4297
|
+
setTimeout(resolve, 0);
|
|
4298
|
+
}
|
|
4299
|
+
});
|
|
4300
|
+
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return true;
|
|
4301
|
+
await renderChunkSubset(workerApi, cacheKey, channelInfo, batch, item, ch);
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
return false;
|
|
4305
|
+
};
|
|
4249
4306
|
for (const item of clipsNeedingFFT) {
|
|
4250
4307
|
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4251
4308
|
try {
|
|
@@ -4275,7 +4332,10 @@ var SpectrogramProvider = ({
|
|
|
4275
4332
|
item.offsetSamples + Math.ceil(localEndPx * samplesPerPixel)
|
|
4276
4333
|
);
|
|
4277
4334
|
const paddedStart = Math.max(item.offsetSamples, visStartSample - windowSize);
|
|
4278
|
-
const paddedEnd = Math.min(
|
|
4335
|
+
const paddedEnd = Math.min(
|
|
4336
|
+
item.offsetSamples + item.durationSamples,
|
|
4337
|
+
visEndSample + windowSize
|
|
4338
|
+
);
|
|
4279
4339
|
if (paddedEnd - paddedStart < item.durationSamples * 0.8) {
|
|
4280
4340
|
visibleRange = { start: paddedStart, end: paddedEnd };
|
|
4281
4341
|
}
|
|
@@ -4297,8 +4357,15 @@ var SpectrogramProvider = ({
|
|
|
4297
4357
|
for (let ch = 0; ch < numChannels; ch++) {
|
|
4298
4358
|
const channelInfo = clipCanvasInfo.get(ch);
|
|
4299
4359
|
if (!channelInfo) continue;
|
|
4300
|
-
const { visibleIndices } = getVisibleChunkRange(channelInfo
|
|
4301
|
-
await renderChunkSubset(
|
|
4360
|
+
const { visibleIndices } = getVisibleChunkRange(channelInfo, clipPixelOffset);
|
|
4361
|
+
await renderChunkSubset(
|
|
4362
|
+
workerApi,
|
|
4363
|
+
visibleCacheKey,
|
|
4364
|
+
channelInfo,
|
|
4365
|
+
visibleIndices,
|
|
4366
|
+
item,
|
|
4367
|
+
ch
|
|
4368
|
+
);
|
|
4302
4369
|
}
|
|
4303
4370
|
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4304
4371
|
}
|
|
@@ -4313,27 +4380,23 @@ var SpectrogramProvider = ({
|
|
|
4313
4380
|
});
|
|
4314
4381
|
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4315
4382
|
clipCacheKeysRef.current.set(item.clipId, cacheKey);
|
|
4383
|
+
const channelRanges = [];
|
|
4316
4384
|
for (let ch = 0; ch < numChannels; ch++) {
|
|
4317
4385
|
const channelInfo = clipCanvasInfo.get(ch);
|
|
4318
4386
|
if (!channelInfo) continue;
|
|
4319
|
-
const
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
} else {
|
|
4330
|
-
setTimeout(resolve, 0);
|
|
4331
|
-
}
|
|
4332
|
-
});
|
|
4333
|
-
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4334
|
-
await renderChunkSubset(workerApi, cacheKey, channelInfo, batch, item, ch);
|
|
4335
|
-
}
|
|
4387
|
+
const range = getVisibleChunkRange(channelInfo, clipPixelOffset);
|
|
4388
|
+
channelRanges.push({ ch, channelInfo, ...range });
|
|
4389
|
+
await renderChunkSubset(
|
|
4390
|
+
workerApi,
|
|
4391
|
+
cacheKey,
|
|
4392
|
+
channelInfo,
|
|
4393
|
+
range.visibleIndices,
|
|
4394
|
+
item,
|
|
4395
|
+
ch
|
|
4396
|
+
);
|
|
4336
4397
|
}
|
|
4398
|
+
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4399
|
+
if (await renderBackgroundBatches(channelRanges, cacheKey, item)) return;
|
|
4337
4400
|
} else {
|
|
4338
4401
|
const spectrograms = await workerApi.compute({
|
|
4339
4402
|
channelDataArrays: item.channelDataArrays,
|
|
@@ -4362,27 +4425,19 @@ var SpectrogramProvider = ({
|
|
|
4362
4425
|
if (!clipCanvasInfo || clipCanvasInfo.size === 0) continue;
|
|
4363
4426
|
try {
|
|
4364
4427
|
const clipPixelOffset = Math.floor(item.clipStartSample / samplesPerPixel);
|
|
4428
|
+
const channelRanges = [];
|
|
4365
4429
|
for (let ch = 0; ch < item.numChannels; ch++) {
|
|
4366
4430
|
const channelInfo = clipCanvasInfo.get(ch);
|
|
4367
4431
|
if (!channelInfo) continue;
|
|
4368
|
-
const { visibleIndices, remainingIndices } = getVisibleChunkRange(
|
|
4432
|
+
const { visibleIndices, remainingIndices } = getVisibleChunkRange(
|
|
4433
|
+
channelInfo,
|
|
4434
|
+
clipPixelOffset
|
|
4435
|
+
);
|
|
4436
|
+
channelRanges.push({ ch, channelInfo, remainingIndices });
|
|
4369
4437
|
await renderChunkSubset(workerApi, cacheKey, channelInfo, visibleIndices, item, ch);
|
|
4370
|
-
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4371
|
-
const BATCH_SIZE = 4;
|
|
4372
|
-
for (let batchStart = 0; batchStart < remainingIndices.length; batchStart += BATCH_SIZE) {
|
|
4373
|
-
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4374
|
-
const batch = remainingIndices.slice(batchStart, batchStart + BATCH_SIZE);
|
|
4375
|
-
await new Promise((resolve) => {
|
|
4376
|
-
if (typeof requestIdleCallback === "function") {
|
|
4377
|
-
requestIdleCallback(() => resolve());
|
|
4378
|
-
} else {
|
|
4379
|
-
setTimeout(resolve, 0);
|
|
4380
|
-
}
|
|
4381
|
-
});
|
|
4382
|
-
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4383
|
-
await renderChunkSubset(workerApi, cacheKey, channelInfo, batch, item, ch);
|
|
4384
|
-
}
|
|
4385
4438
|
}
|
|
4439
|
+
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4440
|
+
if (await renderBackgroundBatches(channelRanges, cacheKey, item)) return;
|
|
4386
4441
|
} catch (err) {
|
|
4387
4442
|
console.warn("Spectrogram display re-render error for clip", item.clipId, err);
|
|
4388
4443
|
}
|
|
@@ -4391,7 +4446,18 @@ var SpectrogramProvider = ({
|
|
|
4391
4446
|
computeAsync().catch((err) => {
|
|
4392
4447
|
console.error("[waveform-playlist] Spectrogram computation failed:", err);
|
|
4393
4448
|
});
|
|
4394
|
-
}, [
|
|
4449
|
+
}, [
|
|
4450
|
+
tracks,
|
|
4451
|
+
mono,
|
|
4452
|
+
spectrogramConfig,
|
|
4453
|
+
spectrogramColorMap,
|
|
4454
|
+
trackSpectrogramOverrides,
|
|
4455
|
+
waveHeight,
|
|
4456
|
+
samplesPerPixel,
|
|
4457
|
+
spectrogramCanvasVersion,
|
|
4458
|
+
controls,
|
|
4459
|
+
scrollContainerRef
|
|
4460
|
+
]);
|
|
4395
4461
|
const setTrackRenderMode = (0, import_react2.useCallback)((trackId, mode) => {
|
|
4396
4462
|
setTrackSpectrogramOverrides((prev) => {
|
|
4397
4463
|
const next = new Map(prev);
|
|
@@ -4400,26 +4466,32 @@ var SpectrogramProvider = ({
|
|
|
4400
4466
|
return next;
|
|
4401
4467
|
});
|
|
4402
4468
|
}, []);
|
|
4403
|
-
const setTrackSpectrogramConfig = (0, import_react2.useCallback)(
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4469
|
+
const setTrackSpectrogramConfig = (0, import_react2.useCallback)(
|
|
4470
|
+
(trackId, config, colorMap) => {
|
|
4471
|
+
setTrackSpectrogramOverrides((prev) => {
|
|
4472
|
+
const next = new Map(prev);
|
|
4473
|
+
const existing = next.get(trackId);
|
|
4474
|
+
next.set(trackId, {
|
|
4475
|
+
renderMode: existing?.renderMode ?? "waveform",
|
|
4476
|
+
config,
|
|
4477
|
+
...colorMap !== void 0 ? { colorMap } : { colorMap: existing?.colorMap }
|
|
4478
|
+
});
|
|
4479
|
+
return next;
|
|
4411
4480
|
});
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
const registerSpectrogramCanvases = (0, import_react2.useCallback)(
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
registry.
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4481
|
+
},
|
|
4482
|
+
[]
|
|
4483
|
+
);
|
|
4484
|
+
const registerSpectrogramCanvases = (0, import_react2.useCallback)(
|
|
4485
|
+
(clipId, channelIndex, canvasIds, canvasWidths) => {
|
|
4486
|
+
const registry = spectrogramCanvasRegistryRef.current;
|
|
4487
|
+
if (!registry.has(clipId)) {
|
|
4488
|
+
registry.set(clipId, /* @__PURE__ */ new Map());
|
|
4489
|
+
}
|
|
4490
|
+
registry.get(clipId).set(channelIndex, { canvasIds, canvasWidths });
|
|
4491
|
+
setSpectrogramCanvasVersion((v) => v + 1);
|
|
4492
|
+
},
|
|
4493
|
+
[]
|
|
4494
|
+
);
|
|
4423
4495
|
const unregisterSpectrogramCanvases = (0, import_react2.useCallback)((clipId, channelIndex) => {
|
|
4424
4496
|
const registry = spectrogramCanvasRegistryRef.current;
|
|
4425
4497
|
const clipChannels = registry.get(clipId);
|
|
@@ -4430,40 +4502,46 @@ var SpectrogramProvider = ({
|
|
|
4430
4502
|
}
|
|
4431
4503
|
}
|
|
4432
4504
|
}, []);
|
|
4433
|
-
const renderMenuItems = (0, import_react2.useCallback)(
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4505
|
+
const renderMenuItems = (0, import_react2.useCallback)(
|
|
4506
|
+
(props) => {
|
|
4507
|
+
return SpectrogramMenuItems({
|
|
4508
|
+
renderMode: props.renderMode,
|
|
4509
|
+
onRenderModeChange: props.onRenderModeChange,
|
|
4510
|
+
onOpenSettings: props.onOpenSettings,
|
|
4511
|
+
onClose: props.onClose
|
|
4512
|
+
});
|
|
4513
|
+
},
|
|
4514
|
+
[]
|
|
4515
|
+
);
|
|
4516
|
+
const value = (0, import_react2.useMemo)(
|
|
4517
|
+
() => ({
|
|
4518
|
+
spectrogramDataMap,
|
|
4519
|
+
trackSpectrogramOverrides,
|
|
4520
|
+
spectrogramWorkerApi: spectrogramWorkerReady ? spectrogramWorkerRef.current : null,
|
|
4521
|
+
spectrogramConfig,
|
|
4522
|
+
spectrogramColorMap,
|
|
4523
|
+
setTrackRenderMode,
|
|
4524
|
+
setTrackSpectrogramConfig,
|
|
4525
|
+
registerSpectrogramCanvases,
|
|
4526
|
+
unregisterSpectrogramCanvases,
|
|
4527
|
+
renderMenuItems,
|
|
4528
|
+
SettingsModal: SpectrogramSettingsModal,
|
|
4529
|
+
getColorMap,
|
|
4530
|
+
getFrequencyScale
|
|
4531
|
+
}),
|
|
4532
|
+
[
|
|
4533
|
+
spectrogramDataMap,
|
|
4534
|
+
trackSpectrogramOverrides,
|
|
4535
|
+
spectrogramWorkerReady,
|
|
4536
|
+
spectrogramConfig,
|
|
4537
|
+
spectrogramColorMap,
|
|
4538
|
+
setTrackRenderMode,
|
|
4539
|
+
setTrackSpectrogramConfig,
|
|
4540
|
+
registerSpectrogramCanvases,
|
|
4541
|
+
unregisterSpectrogramCanvases,
|
|
4542
|
+
renderMenuItems
|
|
4543
|
+
]
|
|
4544
|
+
);
|
|
4467
4545
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_browser.SpectrogramIntegrationProvider, { value, children });
|
|
4468
4546
|
};
|
|
4469
4547
|
// Annotate the CommonJS export names for ESM import in node:
|