@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.mjs CHANGED
@@ -3563,7 +3563,14 @@ var ModalButton = styled2.button`
3563
3563
  }
3564
3564
  `;
3565
3565
  var FFT_SIZES = [256, 512, 1024, 2048, 4096, 8192];
3566
- var WINDOW_FUNCTIONS = ["hann", "hamming", "blackman", "blackman-harris", "bartlett", "rectangular"];
3566
+ var WINDOW_FUNCTIONS = [
3567
+ "hann",
3568
+ "hamming",
3569
+ "blackman",
3570
+ "blackman-harris",
3571
+ "bartlett",
3572
+ "rectangular"
3573
+ ];
3567
3574
  var FREQ_SCALES = ["linear", "logarithmic", "mel", "bark", "erb"];
3568
3575
  var COLOR_MAPS = ["viridis", "magma", "inferno", "grayscale", "igray", "roseus"];
3569
3576
  var SpectrogramSettingsModal = ({
@@ -3585,7 +3592,9 @@ var SpectrogramSettingsModal = ({
3585
3592
  const [gainDb, setGainDb] = useState(config.gainDb ?? 20);
3586
3593
  const [rangeDb, setRangeDb] = useState(config.rangeDb ?? 80);
3587
3594
  const [zeroPadding, setZeroPadding] = useState(config.zeroPaddingFactor ?? 2);
3588
- const [hopSize, setHopSize] = useState(config.hopSize ?? Math.floor((config.fftSize ?? 2048) / 4));
3595
+ const [hopSize, setHopSize] = useState(
3596
+ config.hopSize ?? Math.floor((config.fftSize ?? 2048) / 4)
3597
+ );
3589
3598
  const [showLabels, setShowLabels] = useState(config.labels ?? false);
3590
3599
  useEffect(() => {
3591
3600
  setFftSize(config.fftSize ?? 2048);
@@ -3639,11 +3648,18 @@ var SpectrogramSettingsModal = ({
3639
3648
  /* @__PURE__ */ jsxs2(FormGrid, { children: [
3640
3649
  /* @__PURE__ */ jsxs2(Field, { children: [
3641
3650
  /* @__PURE__ */ jsx2(Label, { children: "FFT Size" }),
3642
- /* @__PURE__ */ jsx2(Select, { value: fftSize, onChange: (e) => {
3643
- const v = Number(e.target.value);
3644
- setFftSize(v);
3645
- setHopSize(Math.floor(v / 4));
3646
- }, children: FFT_SIZES.map((s) => /* @__PURE__ */ jsx2("option", { value: s, children: s }, s)) })
3651
+ /* @__PURE__ */ jsx2(
3652
+ Select,
3653
+ {
3654
+ value: fftSize,
3655
+ onChange: (e) => {
3656
+ const v = Number(e.target.value);
3657
+ setFftSize(v);
3658
+ setHopSize(Math.floor(v / 4));
3659
+ },
3660
+ children: FFT_SIZES.map((s) => /* @__PURE__ */ jsx2("option", { value: s, children: s }, s))
3661
+ }
3662
+ )
3647
3663
  ] }),
3648
3664
  /* @__PURE__ */ jsxs2(Field, { children: [
3649
3665
  /* @__PURE__ */ jsx2(Label, { children: "Hop Size" }),
@@ -3664,11 +3680,25 @@ var SpectrogramSettingsModal = ({
3664
3680
  ] }),
3665
3681
  /* @__PURE__ */ jsxs2(Field, { children: [
3666
3682
  /* @__PURE__ */ jsx2(Label, { children: "Frequency Scale" }),
3667
- /* @__PURE__ */ jsx2(Select, { value: freqScale, onChange: (e) => setFreqScale(e.target.value), children: FREQ_SCALES.map((s) => /* @__PURE__ */ jsx2("option", { value: s, children: s }, s)) })
3683
+ /* @__PURE__ */ jsx2(
3684
+ Select,
3685
+ {
3686
+ value: freqScale,
3687
+ onChange: (e) => setFreqScale(e.target.value),
3688
+ children: FREQ_SCALES.map((s) => /* @__PURE__ */ jsx2("option", { value: s, children: s }, s))
3689
+ }
3690
+ )
3668
3691
  ] }),
3669
3692
  /* @__PURE__ */ jsxs2(Field, { children: [
3670
3693
  /* @__PURE__ */ jsx2(Label, { children: "Color Map" }),
3671
- /* @__PURE__ */ jsx2(Select, { value: localColorMap, onChange: (e) => setLocalColorMap(e.target.value), children: COLOR_MAPS.map((c) => /* @__PURE__ */ jsx2("option", { value: c, children: c }, c)) })
3694
+ /* @__PURE__ */ jsx2(
3695
+ Select,
3696
+ {
3697
+ value: localColorMap,
3698
+ onChange: (e) => setLocalColorMap(e.target.value),
3699
+ children: COLOR_MAPS.map((c) => /* @__PURE__ */ jsx2("option", { value: c, children: c }, c))
3700
+ }
3701
+ )
3672
3702
  ] }),
3673
3703
  /* @__PURE__ */ jsxs2(Field, { children: [
3674
3704
  /* @__PURE__ */ jsx2(Label, { children: "Min Frequency (Hz)" }),
@@ -3727,7 +3757,14 @@ var SpectrogramSettingsModal = ({
3727
3757
  )
3728
3758
  ] }),
3729
3759
  /* @__PURE__ */ jsx2(Field, { $span: true, children: /* @__PURE__ */ jsxs2(CheckboxLabel, { children: [
3730
- /* @__PURE__ */ jsx2("input", { type: "checkbox", checked: showLabels, onChange: (e) => setShowLabels(e.target.checked) }),
3760
+ /* @__PURE__ */ jsx2(
3761
+ "input",
3762
+ {
3763
+ type: "checkbox",
3764
+ checked: showLabels,
3765
+ onChange: (e) => setShowLabels(e.target.checked)
3766
+ }
3767
+ ),
3731
3768
  "Show Frequency Labels"
3732
3769
  ] }) })
3733
3770
  ] }),
@@ -3850,10 +3887,7 @@ function createSpectrogramWorker(worker) {
3850
3887
  });
3851
3888
  },
3852
3889
  registerCanvas(canvasId, canvas) {
3853
- worker.postMessage(
3854
- { type: "register-canvas", canvasId, canvas },
3855
- [canvas]
3856
- );
3890
+ worker.postMessage({ type: "register-canvas", canvasId, canvas }, [canvas]);
3857
3891
  },
3858
3892
  unregisterCanvas(canvasId) {
3859
3893
  worker.postMessage({ type: "unregister-canvas", canvasId });
@@ -3907,24 +3941,32 @@ function createSpectrogramWorker(worker) {
3907
3941
 
3908
3942
  // src/SpectrogramProvider.tsx
3909
3943
  import { useState as useState2, useEffect as useEffect2, useRef as useRef2, useCallback, useMemo } from "react";
3910
- import { SpectrogramIntegrationProvider } from "@waveform-playlist/browser";
3944
+ import {
3945
+ MAX_CANVAS_WIDTH
3946
+ } from "@waveform-playlist/core";
3947
+ import {
3948
+ SpectrogramIntegrationProvider
3949
+ } from "@waveform-playlist/browser";
3911
3950
  import { usePlaylistData, usePlaylistControls } from "@waveform-playlist/browser";
3912
3951
  import { jsx as jsx3 } from "react/jsx-runtime";
3952
+ function extractChunkNumber(canvasId) {
3953
+ const match = canvasId.match(/chunk(\d+)$/);
3954
+ if (!match) {
3955
+ console.warn(`[spectrogram] Unexpected canvas ID format: ${canvasId}`);
3956
+ return 0;
3957
+ }
3958
+ return parseInt(match[1], 10);
3959
+ }
3913
3960
  var SpectrogramProvider = ({
3914
3961
  config: spectrogramConfig,
3915
3962
  colorMap: spectrogramColorMap,
3916
3963
  children
3917
3964
  }) => {
3918
- const {
3919
- tracks,
3920
- waveHeight,
3921
- samplesPerPixel,
3922
- isReady,
3923
- mono,
3924
- controls
3925
- } = usePlaylistData();
3965
+ const { tracks, waveHeight, samplesPerPixel, isReady, mono, controls } = usePlaylistData();
3926
3966
  const { scrollContainerRef } = usePlaylistControls();
3927
- const [spectrogramDataMap, setSpectrogramDataMap] = useState2(/* @__PURE__ */ new Map());
3967
+ const [spectrogramDataMap, setSpectrogramDataMap] = useState2(
3968
+ /* @__PURE__ */ new Map()
3969
+ );
3928
3970
  const [trackSpectrogramOverrides, setTrackSpectrogramOverrides] = useState2(/* @__PURE__ */ new Map());
3929
3971
  const spectrogramCanvasRegistryRef = useRef2(/* @__PURE__ */ new Map());
3930
3972
  const [spectrogramCanvasVersion, setSpectrogramCanvasVersion] = useState2(0);
@@ -4073,9 +4115,7 @@ var SpectrogramProvider = ({
4073
4115
  if (mode === "waveform") return;
4074
4116
  const trackConfigChanged = configChanged && currentKeys.get(track.id) !== prevKeys.get(track.id);
4075
4117
  const trackFFTChanged = fftKeyChanged && currentFFTKeys.get(track.id) !== prevFFTKeys.get(track.id);
4076
- const hasRegisteredCanvases = canvasVersionChanged && track.clips.some(
4077
- (clip) => spectrogramCanvasRegistryRef.current.has(clip.id)
4078
- );
4118
+ const hasRegisteredCanvases = canvasVersionChanged && track.clips.some((clip) => spectrogramCanvasRegistryRef.current.has(clip.id));
4079
4119
  if (!trackConfigChanged && !hasRegisteredCanvases) return;
4080
4120
  const cfg = trackSpectrogramOverrides.get(track.id)?.config ?? track.spectrogramConfig ?? spectrogramConfig ?? {};
4081
4121
  const cm = trackSpectrogramOverrides.get(track.id)?.colorMap ?? track.spectrogramColorMap ?? spectrogramColorMap ?? "viridis";
@@ -4133,7 +4173,13 @@ var SpectrogramProvider = ({
4133
4173
  } else {
4134
4174
  for (let ch = 0; ch < clip.audioBuffer.numberOfChannels; ch++) {
4135
4175
  channelSpectrograms.push(
4136
- computeSpectrogram(clip.audioBuffer, item.config, item.offsetSamples, item.durationSamples, ch)
4176
+ computeSpectrogram(
4177
+ clip.audioBuffer,
4178
+ item.config,
4179
+ item.offsetSamples,
4180
+ item.durationSamples,
4181
+ ch
4182
+ )
4137
4183
  );
4138
4184
  }
4139
4185
  }
@@ -4146,26 +4192,25 @@ var SpectrogramProvider = ({
4146
4192
  }
4147
4193
  return;
4148
4194
  }
4149
- const getVisibleChunkRange = (canvasWidths, clipPixelOffset = 0) => {
4195
+ const getVisibleChunkRange = (channelInfo, clipPixelOffset = 0) => {
4150
4196
  const container = scrollContainerRef.current;
4151
4197
  if (!container) {
4152
- return { visibleIndices: canvasWidths.map((_, i) => i), remainingIndices: [] };
4198
+ return { visibleIndices: channelInfo.canvasWidths.map((_, i) => i), remainingIndices: [] };
4153
4199
  }
4154
4200
  const scrollLeft = container.scrollLeft;
4155
4201
  const viewportWidth = container.clientWidth;
4156
4202
  const controlWidth = controls.show ? controls.width : 0;
4157
4203
  const visibleIndices = [];
4158
4204
  const remainingIndices = [];
4159
- let offset = 0;
4160
- for (let i = 0; i < canvasWidths.length; i++) {
4161
- const chunkLeft = offset + controlWidth + clipPixelOffset;
4162
- const chunkRight = chunkLeft + canvasWidths[i];
4205
+ for (let i = 0; i < channelInfo.canvasWidths.length; i++) {
4206
+ const chunkNumber = extractChunkNumber(channelInfo.canvasIds[i]);
4207
+ const chunkLeft = chunkNumber * MAX_CANVAS_WIDTH + controlWidth + clipPixelOffset;
4208
+ const chunkRight = chunkLeft + channelInfo.canvasWidths[i];
4163
4209
  if (chunkRight > scrollLeft && chunkLeft < scrollLeft + viewportWidth) {
4164
4210
  visibleIndices.push(i);
4165
4211
  } else {
4166
4212
  remainingIndices.push(i);
4167
4213
  }
4168
- offset += canvasWidths[i];
4169
4214
  }
4170
4215
  return { visibleIndices, remainingIndices };
4171
4216
  };
@@ -4175,11 +4220,8 @@ var SpectrogramProvider = ({
4175
4220
  const canvasWidths = indices.map((i) => channelInfo.canvasWidths[i]);
4176
4221
  const globalPixelOffsets = [];
4177
4222
  for (const idx of indices) {
4178
- let offset = 0;
4179
- for (let j = 0; j < idx; j++) {
4180
- offset += channelInfo.canvasWidths[j];
4181
- }
4182
- globalPixelOffsets.push(offset);
4223
+ const chunkNumber = extractChunkNumber(channelInfo.canvasIds[idx]);
4224
+ globalPixelOffsets.push(chunkNumber * MAX_CANVAS_WIDTH);
4183
4225
  }
4184
4226
  const colorLUT = getColorMap(item.colorMap);
4185
4227
  await api.renderChunks({
@@ -4202,6 +4244,25 @@ var SpectrogramProvider = ({
4202
4244
  const computeAsync = async () => {
4203
4245
  const abortToken = { aborted: false };
4204
4246
  backgroundRenderAbortRef.current = abortToken;
4247
+ const renderBackgroundBatches = async (channelRanges, cacheKey, item) => {
4248
+ const BATCH_SIZE = 4;
4249
+ for (const { ch, channelInfo, remainingIndices } of channelRanges) {
4250
+ for (let batchStart = 0; batchStart < remainingIndices.length; batchStart += BATCH_SIZE) {
4251
+ if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return true;
4252
+ const batch = remainingIndices.slice(batchStart, batchStart + BATCH_SIZE);
4253
+ await new Promise((resolve) => {
4254
+ if (typeof requestIdleCallback === "function") {
4255
+ requestIdleCallback(() => resolve());
4256
+ } else {
4257
+ setTimeout(resolve, 0);
4258
+ }
4259
+ });
4260
+ if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return true;
4261
+ await renderChunkSubset(workerApi, cacheKey, channelInfo, batch, item, ch);
4262
+ }
4263
+ }
4264
+ return false;
4265
+ };
4205
4266
  for (const item of clipsNeedingFFT) {
4206
4267
  if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4207
4268
  try {
@@ -4231,7 +4292,10 @@ var SpectrogramProvider = ({
4231
4292
  item.offsetSamples + Math.ceil(localEndPx * samplesPerPixel)
4232
4293
  );
4233
4294
  const paddedStart = Math.max(item.offsetSamples, visStartSample - windowSize);
4234
- const paddedEnd = Math.min(item.offsetSamples + item.durationSamples, visEndSample + windowSize);
4295
+ const paddedEnd = Math.min(
4296
+ item.offsetSamples + item.durationSamples,
4297
+ visEndSample + windowSize
4298
+ );
4235
4299
  if (paddedEnd - paddedStart < item.durationSamples * 0.8) {
4236
4300
  visibleRange = { start: paddedStart, end: paddedEnd };
4237
4301
  }
@@ -4253,8 +4317,15 @@ var SpectrogramProvider = ({
4253
4317
  for (let ch = 0; ch < numChannels; ch++) {
4254
4318
  const channelInfo = clipCanvasInfo.get(ch);
4255
4319
  if (!channelInfo) continue;
4256
- const { visibleIndices } = getVisibleChunkRange(channelInfo.canvasWidths, clipPixelOffset);
4257
- await renderChunkSubset(workerApi, visibleCacheKey, channelInfo, visibleIndices, item, ch);
4320
+ const { visibleIndices } = getVisibleChunkRange(channelInfo, clipPixelOffset);
4321
+ await renderChunkSubset(
4322
+ workerApi,
4323
+ visibleCacheKey,
4324
+ channelInfo,
4325
+ visibleIndices,
4326
+ item,
4327
+ ch
4328
+ );
4258
4329
  }
4259
4330
  if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4260
4331
  }
@@ -4269,27 +4340,23 @@ var SpectrogramProvider = ({
4269
4340
  });
4270
4341
  if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4271
4342
  clipCacheKeysRef.current.set(item.clipId, cacheKey);
4343
+ const channelRanges = [];
4272
4344
  for (let ch = 0; ch < numChannels; ch++) {
4273
4345
  const channelInfo = clipCanvasInfo.get(ch);
4274
4346
  if (!channelInfo) continue;
4275
- const { visibleIndices, remainingIndices } = getVisibleChunkRange(channelInfo.canvasWidths, clipPixelOffset);
4276
- await renderChunkSubset(workerApi, cacheKey, channelInfo, visibleIndices, item, ch);
4277
- if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4278
- const BATCH_SIZE = 4;
4279
- for (let batchStart = 0; batchStart < remainingIndices.length; batchStart += BATCH_SIZE) {
4280
- if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4281
- const batch = remainingIndices.slice(batchStart, batchStart + BATCH_SIZE);
4282
- await new Promise((resolve) => {
4283
- if (typeof requestIdleCallback === "function") {
4284
- requestIdleCallback(() => resolve());
4285
- } else {
4286
- setTimeout(resolve, 0);
4287
- }
4288
- });
4289
- if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4290
- await renderChunkSubset(workerApi, cacheKey, channelInfo, batch, item, ch);
4291
- }
4347
+ const range = getVisibleChunkRange(channelInfo, clipPixelOffset);
4348
+ channelRanges.push({ ch, channelInfo, ...range });
4349
+ await renderChunkSubset(
4350
+ workerApi,
4351
+ cacheKey,
4352
+ channelInfo,
4353
+ range.visibleIndices,
4354
+ item,
4355
+ ch
4356
+ );
4292
4357
  }
4358
+ if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4359
+ if (await renderBackgroundBatches(channelRanges, cacheKey, item)) return;
4293
4360
  } else {
4294
4361
  const spectrograms = await workerApi.compute({
4295
4362
  channelDataArrays: item.channelDataArrays,
@@ -4318,27 +4385,19 @@ var SpectrogramProvider = ({
4318
4385
  if (!clipCanvasInfo || clipCanvasInfo.size === 0) continue;
4319
4386
  try {
4320
4387
  const clipPixelOffset = Math.floor(item.clipStartSample / samplesPerPixel);
4388
+ const channelRanges = [];
4321
4389
  for (let ch = 0; ch < item.numChannels; ch++) {
4322
4390
  const channelInfo = clipCanvasInfo.get(ch);
4323
4391
  if (!channelInfo) continue;
4324
- const { visibleIndices, remainingIndices } = getVisibleChunkRange(channelInfo.canvasWidths, clipPixelOffset);
4392
+ const { visibleIndices, remainingIndices } = getVisibleChunkRange(
4393
+ channelInfo,
4394
+ clipPixelOffset
4395
+ );
4396
+ channelRanges.push({ ch, channelInfo, remainingIndices });
4325
4397
  await renderChunkSubset(workerApi, cacheKey, channelInfo, visibleIndices, item, ch);
4326
- if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4327
- const BATCH_SIZE = 4;
4328
- for (let batchStart = 0; batchStart < remainingIndices.length; batchStart += BATCH_SIZE) {
4329
- if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4330
- const batch = remainingIndices.slice(batchStart, batchStart + BATCH_SIZE);
4331
- await new Promise((resolve) => {
4332
- if (typeof requestIdleCallback === "function") {
4333
- requestIdleCallback(() => resolve());
4334
- } else {
4335
- setTimeout(resolve, 0);
4336
- }
4337
- });
4338
- if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4339
- await renderChunkSubset(workerApi, cacheKey, channelInfo, batch, item, ch);
4340
- }
4341
4398
  }
4399
+ if (spectrogramGenerationRef.current !== generation || abortToken.aborted) return;
4400
+ if (await renderBackgroundBatches(channelRanges, cacheKey, item)) return;
4342
4401
  } catch (err) {
4343
4402
  console.warn("Spectrogram display re-render error for clip", item.clipId, err);
4344
4403
  }
@@ -4347,7 +4406,18 @@ var SpectrogramProvider = ({
4347
4406
  computeAsync().catch((err) => {
4348
4407
  console.error("[waveform-playlist] Spectrogram computation failed:", err);
4349
4408
  });
4350
- }, [tracks, mono, spectrogramConfig, spectrogramColorMap, trackSpectrogramOverrides, waveHeight, samplesPerPixel, spectrogramCanvasVersion, controls, scrollContainerRef]);
4409
+ }, [
4410
+ tracks,
4411
+ mono,
4412
+ spectrogramConfig,
4413
+ spectrogramColorMap,
4414
+ trackSpectrogramOverrides,
4415
+ waveHeight,
4416
+ samplesPerPixel,
4417
+ spectrogramCanvasVersion,
4418
+ controls,
4419
+ scrollContainerRef
4420
+ ]);
4351
4421
  const setTrackRenderMode = useCallback((trackId, mode) => {
4352
4422
  setTrackSpectrogramOverrides((prev) => {
4353
4423
  const next = new Map(prev);
@@ -4356,26 +4426,32 @@ var SpectrogramProvider = ({
4356
4426
  return next;
4357
4427
  });
4358
4428
  }, []);
4359
- const setTrackSpectrogramConfig = useCallback((trackId, config, colorMap) => {
4360
- setTrackSpectrogramOverrides((prev) => {
4361
- const next = new Map(prev);
4362
- const existing = next.get(trackId);
4363
- next.set(trackId, {
4364
- renderMode: existing?.renderMode ?? "waveform",
4365
- config,
4366
- ...colorMap !== void 0 ? { colorMap } : { colorMap: existing?.colorMap }
4429
+ const setTrackSpectrogramConfig = useCallback(
4430
+ (trackId, config, colorMap) => {
4431
+ setTrackSpectrogramOverrides((prev) => {
4432
+ const next = new Map(prev);
4433
+ const existing = next.get(trackId);
4434
+ next.set(trackId, {
4435
+ renderMode: existing?.renderMode ?? "waveform",
4436
+ config,
4437
+ ...colorMap !== void 0 ? { colorMap } : { colorMap: existing?.colorMap }
4438
+ });
4439
+ return next;
4367
4440
  });
4368
- return next;
4369
- });
4370
- }, []);
4371
- const registerSpectrogramCanvases = useCallback((clipId, channelIndex, canvasIds, canvasWidths) => {
4372
- const registry = spectrogramCanvasRegistryRef.current;
4373
- if (!registry.has(clipId)) {
4374
- registry.set(clipId, /* @__PURE__ */ new Map());
4375
- }
4376
- registry.get(clipId).set(channelIndex, { canvasIds, canvasWidths });
4377
- setSpectrogramCanvasVersion((v) => v + 1);
4378
- }, []);
4441
+ },
4442
+ []
4443
+ );
4444
+ const registerSpectrogramCanvases = useCallback(
4445
+ (clipId, channelIndex, canvasIds, canvasWidths) => {
4446
+ const registry = spectrogramCanvasRegistryRef.current;
4447
+ if (!registry.has(clipId)) {
4448
+ registry.set(clipId, /* @__PURE__ */ new Map());
4449
+ }
4450
+ registry.get(clipId).set(channelIndex, { canvasIds, canvasWidths });
4451
+ setSpectrogramCanvasVersion((v) => v + 1);
4452
+ },
4453
+ []
4454
+ );
4379
4455
  const unregisterSpectrogramCanvases = useCallback((clipId, channelIndex) => {
4380
4456
  const registry = spectrogramCanvasRegistryRef.current;
4381
4457
  const clipChannels = registry.get(clipId);
@@ -4386,40 +4462,46 @@ var SpectrogramProvider = ({
4386
4462
  }
4387
4463
  }
4388
4464
  }, []);
4389
- const renderMenuItems = useCallback((props) => {
4390
- return SpectrogramMenuItems({
4391
- renderMode: props.renderMode,
4392
- onRenderModeChange: props.onRenderModeChange,
4393
- onOpenSettings: props.onOpenSettings,
4394
- onClose: props.onClose
4395
- });
4396
- }, []);
4397
- const value = useMemo(() => ({
4398
- spectrogramDataMap,
4399
- trackSpectrogramOverrides,
4400
- spectrogramWorkerApi: spectrogramWorkerReady ? spectrogramWorkerRef.current : null,
4401
- spectrogramConfig,
4402
- spectrogramColorMap,
4403
- setTrackRenderMode,
4404
- setTrackSpectrogramConfig,
4405
- registerSpectrogramCanvases,
4406
- unregisterSpectrogramCanvases,
4407
- renderMenuItems,
4408
- SettingsModal: SpectrogramSettingsModal,
4409
- getColorMap,
4410
- getFrequencyScale
4411
- }), [
4412
- spectrogramDataMap,
4413
- trackSpectrogramOverrides,
4414
- spectrogramWorkerReady,
4415
- spectrogramConfig,
4416
- spectrogramColorMap,
4417
- setTrackRenderMode,
4418
- setTrackSpectrogramConfig,
4419
- registerSpectrogramCanvases,
4420
- unregisterSpectrogramCanvases,
4421
- renderMenuItems
4422
- ]);
4465
+ const renderMenuItems = useCallback(
4466
+ (props) => {
4467
+ return SpectrogramMenuItems({
4468
+ renderMode: props.renderMode,
4469
+ onRenderModeChange: props.onRenderModeChange,
4470
+ onOpenSettings: props.onOpenSettings,
4471
+ onClose: props.onClose
4472
+ });
4473
+ },
4474
+ []
4475
+ );
4476
+ const value = useMemo(
4477
+ () => ({
4478
+ spectrogramDataMap,
4479
+ trackSpectrogramOverrides,
4480
+ spectrogramWorkerApi: spectrogramWorkerReady ? spectrogramWorkerRef.current : null,
4481
+ spectrogramConfig,
4482
+ spectrogramColorMap,
4483
+ setTrackRenderMode,
4484
+ setTrackSpectrogramConfig,
4485
+ registerSpectrogramCanvases,
4486
+ unregisterSpectrogramCanvases,
4487
+ renderMenuItems,
4488
+ SettingsModal: SpectrogramSettingsModal,
4489
+ getColorMap,
4490
+ getFrequencyScale
4491
+ }),
4492
+ [
4493
+ spectrogramDataMap,
4494
+ trackSpectrogramOverrides,
4495
+ spectrogramWorkerReady,
4496
+ spectrogramConfig,
4497
+ spectrogramColorMap,
4498
+ setTrackRenderMode,
4499
+ setTrackSpectrogramConfig,
4500
+ registerSpectrogramCanvases,
4501
+ unregisterSpectrogramCanvases,
4502
+ renderMenuItems
4503
+ ]
4504
+ );
4423
4505
  return /* @__PURE__ */ jsx3(SpectrogramIntegrationProvider, { value, children });
4424
4506
  };
4425
4507
  export {