@waveform-playlist/spectrogram 7.1.2 → 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 +161 -85
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +167 -87
- 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 });
|
|
@@ -3968,16 +4002,11 @@ var SpectrogramProvider = ({
|
|
|
3968
4002
|
colorMap: spectrogramColorMap,
|
|
3969
4003
|
children
|
|
3970
4004
|
}) => {
|
|
3971
|
-
const {
|
|
3972
|
-
tracks,
|
|
3973
|
-
waveHeight,
|
|
3974
|
-
samplesPerPixel,
|
|
3975
|
-
isReady,
|
|
3976
|
-
mono,
|
|
3977
|
-
controls
|
|
3978
|
-
} = (0, import_browser2.usePlaylistData)();
|
|
4005
|
+
const { tracks, waveHeight, samplesPerPixel, isReady, mono, controls } = (0, import_browser2.usePlaylistData)();
|
|
3979
4006
|
const { scrollContainerRef } = (0, import_browser2.usePlaylistControls)();
|
|
3980
|
-
const [spectrogramDataMap, setSpectrogramDataMap] = (0, import_react2.useState)(
|
|
4007
|
+
const [spectrogramDataMap, setSpectrogramDataMap] = (0, import_react2.useState)(
|
|
4008
|
+
/* @__PURE__ */ new Map()
|
|
4009
|
+
);
|
|
3981
4010
|
const [trackSpectrogramOverrides, setTrackSpectrogramOverrides] = (0, import_react2.useState)(/* @__PURE__ */ new Map());
|
|
3982
4011
|
const spectrogramCanvasRegistryRef = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
|
|
3983
4012
|
const [spectrogramCanvasVersion, setSpectrogramCanvasVersion] = (0, import_react2.useState)(0);
|
|
@@ -4126,9 +4155,7 @@ var SpectrogramProvider = ({
|
|
|
4126
4155
|
if (mode === "waveform") return;
|
|
4127
4156
|
const trackConfigChanged = configChanged && currentKeys.get(track.id) !== prevKeys.get(track.id);
|
|
4128
4157
|
const trackFFTChanged = fftKeyChanged && currentFFTKeys.get(track.id) !== prevFFTKeys.get(track.id);
|
|
4129
|
-
const hasRegisteredCanvases = canvasVersionChanged && track.clips.some(
|
|
4130
|
-
(clip) => spectrogramCanvasRegistryRef.current.has(clip.id)
|
|
4131
|
-
);
|
|
4158
|
+
const hasRegisteredCanvases = canvasVersionChanged && track.clips.some((clip) => spectrogramCanvasRegistryRef.current.has(clip.id));
|
|
4132
4159
|
if (!trackConfigChanged && !hasRegisteredCanvases) return;
|
|
4133
4160
|
const cfg = trackSpectrogramOverrides.get(track.id)?.config ?? track.spectrogramConfig ?? spectrogramConfig ?? {};
|
|
4134
4161
|
const cm = trackSpectrogramOverrides.get(track.id)?.colorMap ?? track.spectrogramColorMap ?? spectrogramColorMap ?? "viridis";
|
|
@@ -4186,7 +4213,13 @@ var SpectrogramProvider = ({
|
|
|
4186
4213
|
} else {
|
|
4187
4214
|
for (let ch = 0; ch < clip.audioBuffer.numberOfChannels; ch++) {
|
|
4188
4215
|
channelSpectrograms.push(
|
|
4189
|
-
computeSpectrogram(
|
|
4216
|
+
computeSpectrogram(
|
|
4217
|
+
clip.audioBuffer,
|
|
4218
|
+
item.config,
|
|
4219
|
+
item.offsetSamples,
|
|
4220
|
+
item.durationSamples,
|
|
4221
|
+
ch
|
|
4222
|
+
)
|
|
4190
4223
|
);
|
|
4191
4224
|
}
|
|
4192
4225
|
}
|
|
@@ -4299,7 +4332,10 @@ var SpectrogramProvider = ({
|
|
|
4299
4332
|
item.offsetSamples + Math.ceil(localEndPx * samplesPerPixel)
|
|
4300
4333
|
);
|
|
4301
4334
|
const paddedStart = Math.max(item.offsetSamples, visStartSample - windowSize);
|
|
4302
|
-
const paddedEnd = Math.min(
|
|
4335
|
+
const paddedEnd = Math.min(
|
|
4336
|
+
item.offsetSamples + item.durationSamples,
|
|
4337
|
+
visEndSample + windowSize
|
|
4338
|
+
);
|
|
4303
4339
|
if (paddedEnd - paddedStart < item.durationSamples * 0.8) {
|
|
4304
4340
|
visibleRange = { start: paddedStart, end: paddedEnd };
|
|
4305
4341
|
}
|
|
@@ -4322,7 +4358,14 @@ var SpectrogramProvider = ({
|
|
|
4322
4358
|
const channelInfo = clipCanvasInfo.get(ch);
|
|
4323
4359
|
if (!channelInfo) continue;
|
|
4324
4360
|
const { visibleIndices } = getVisibleChunkRange(channelInfo, clipPixelOffset);
|
|
4325
|
-
await renderChunkSubset(
|
|
4361
|
+
await renderChunkSubset(
|
|
4362
|
+
workerApi,
|
|
4363
|
+
visibleCacheKey,
|
|
4364
|
+
channelInfo,
|
|
4365
|
+
visibleIndices,
|
|
4366
|
+
item,
|
|
4367
|
+
ch
|
|
4368
|
+
);
|
|
4326
4369
|
}
|
|
4327
4370
|
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4328
4371
|
}
|
|
@@ -4343,7 +4386,14 @@ var SpectrogramProvider = ({
|
|
|
4343
4386
|
if (!channelInfo) continue;
|
|
4344
4387
|
const range = getVisibleChunkRange(channelInfo, clipPixelOffset);
|
|
4345
4388
|
channelRanges.push({ ch, channelInfo, ...range });
|
|
4346
|
-
await renderChunkSubset(
|
|
4389
|
+
await renderChunkSubset(
|
|
4390
|
+
workerApi,
|
|
4391
|
+
cacheKey,
|
|
4392
|
+
channelInfo,
|
|
4393
|
+
range.visibleIndices,
|
|
4394
|
+
item,
|
|
4395
|
+
ch
|
|
4396
|
+
);
|
|
4347
4397
|
}
|
|
4348
4398
|
if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
|
|
4349
4399
|
if (await renderBackgroundBatches(channelRanges, cacheKey, item)) return;
|
|
@@ -4379,7 +4429,10 @@ var SpectrogramProvider = ({
|
|
|
4379
4429
|
for (let ch = 0; ch < item.numChannels; ch++) {
|
|
4380
4430
|
const channelInfo = clipCanvasInfo.get(ch);
|
|
4381
4431
|
if (!channelInfo) continue;
|
|
4382
|
-
const { visibleIndices, remainingIndices } = getVisibleChunkRange(
|
|
4432
|
+
const { visibleIndices, remainingIndices } = getVisibleChunkRange(
|
|
4433
|
+
channelInfo,
|
|
4434
|
+
clipPixelOffset
|
|
4435
|
+
);
|
|
4383
4436
|
channelRanges.push({ ch, channelInfo, remainingIndices });
|
|
4384
4437
|
await renderChunkSubset(workerApi, cacheKey, channelInfo, visibleIndices, item, ch);
|
|
4385
4438
|
}
|
|
@@ -4393,7 +4446,18 @@ var SpectrogramProvider = ({
|
|
|
4393
4446
|
computeAsync().catch((err) => {
|
|
4394
4447
|
console.error("[waveform-playlist] Spectrogram computation failed:", err);
|
|
4395
4448
|
});
|
|
4396
|
-
}, [
|
|
4449
|
+
}, [
|
|
4450
|
+
tracks,
|
|
4451
|
+
mono,
|
|
4452
|
+
spectrogramConfig,
|
|
4453
|
+
spectrogramColorMap,
|
|
4454
|
+
trackSpectrogramOverrides,
|
|
4455
|
+
waveHeight,
|
|
4456
|
+
samplesPerPixel,
|
|
4457
|
+
spectrogramCanvasVersion,
|
|
4458
|
+
controls,
|
|
4459
|
+
scrollContainerRef
|
|
4460
|
+
]);
|
|
4397
4461
|
const setTrackRenderMode = (0, import_react2.useCallback)((trackId, mode) => {
|
|
4398
4462
|
setTrackSpectrogramOverrides((prev) => {
|
|
4399
4463
|
const next = new Map(prev);
|
|
@@ -4402,26 +4466,32 @@ var SpectrogramProvider = ({
|
|
|
4402
4466
|
return next;
|
|
4403
4467
|
});
|
|
4404
4468
|
}, []);
|
|
4405
|
-
const setTrackSpectrogramConfig = (0, import_react2.useCallback)(
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
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;
|
|
4413
4480
|
});
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
const registerSpectrogramCanvases = (0, import_react2.useCallback)(
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
registry.
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
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
|
+
);
|
|
4425
4495
|
const unregisterSpectrogramCanvases = (0, import_react2.useCallback)((clipId, channelIndex) => {
|
|
4426
4496
|
const registry = spectrogramCanvasRegistryRef.current;
|
|
4427
4497
|
const clipChannels = registry.get(clipId);
|
|
@@ -4432,40 +4502,46 @@ var SpectrogramProvider = ({
|
|
|
4432
4502
|
}
|
|
4433
4503
|
}
|
|
4434
4504
|
}, []);
|
|
4435
|
-
const renderMenuItems = (0, import_react2.useCallback)(
|
|
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
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
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
|
+
);
|
|
4469
4545
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_browser.SpectrogramIntegrationProvider, { value, children });
|
|
4470
4546
|
};
|
|
4471
4547
|
// Annotate the CommonJS export names for ESM import in node:
|