@waveform-playlist/ui-components 9.5.0 → 9.5.2
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.d.mts +4 -24
- package/dist/index.d.ts +4 -24
- package/dist/index.js +3 -126
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +8 -131
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import react__default, { FunctionComponent, ReactNode, Dispatch, SetStateAction } from 'react';
|
|
3
|
-
import { Peaks, Bits, Fade, FadeType, MidiNoteData,
|
|
3
|
+
import { Peaks, Bits, Fade, FadeType, MidiNoteData, RenderMode } from '@waveform-playlist/core';
|
|
4
4
|
import * as styled_components_dist_utils_hoist from 'styled-components/dist/utils/hoist';
|
|
5
5
|
import * as styled_components from 'styled-components';
|
|
6
6
|
import { DefaultTheme } from 'styled-components';
|
|
@@ -476,8 +476,6 @@ interface SpectrogramChannelProps {
|
|
|
476
476
|
index: number;
|
|
477
477
|
/** Audio channel index for canvas ID construction. Defaults to `index` when omitted. */
|
|
478
478
|
channelIndex?: number;
|
|
479
|
-
/** Computed spectrogram data (not needed when workerApi is provided) */
|
|
480
|
-
data?: SpectrogramData;
|
|
481
479
|
/** Width in CSS pixels */
|
|
482
480
|
length: number;
|
|
483
481
|
/** Height in CSS pixels */
|
|
@@ -486,18 +484,10 @@ interface SpectrogramChannelProps {
|
|
|
486
484
|
devicePixelRatio?: number;
|
|
487
485
|
/** Samples per pixel at current zoom level */
|
|
488
486
|
samplesPerPixel: number;
|
|
489
|
-
/**
|
|
490
|
-
|
|
491
|
-
/** Frequency scale function: (freqHz, minF, maxF) => [0,1] */
|
|
492
|
-
frequencyScaleFn?: (f: number, minF: number, maxF: number) => number;
|
|
493
|
-
/** Min frequency in Hz */
|
|
494
|
-
minFrequency?: number;
|
|
495
|
-
/** Max frequency in Hz (defaults to sampleRate/2) */
|
|
496
|
-
maxFrequency?: number;
|
|
497
|
-
/** Worker API for transferring canvas ownership. When provided, rendering is done in the worker. */
|
|
498
|
-
workerApi?: SpectrogramWorkerCanvasApi;
|
|
487
|
+
/** Worker API for transferring canvas ownership. Rendering is done in the worker. */
|
|
488
|
+
workerApi: SpectrogramWorkerCanvasApi;
|
|
499
489
|
/** Clip ID used to construct unique canvas IDs for worker registration */
|
|
500
|
-
clipId
|
|
490
|
+
clipId: string;
|
|
501
491
|
/** Callback when canvases are registered with the worker, providing canvas IDs and widths */
|
|
502
492
|
onCanvasesReady?: (canvasIds: string[], canvasWidths: number[]) => void;
|
|
503
493
|
}
|
|
@@ -514,18 +504,8 @@ interface SmartChannelProps {
|
|
|
514
504
|
transparentBackground?: boolean;
|
|
515
505
|
/** Render mode: waveform, spectrogram, or both */
|
|
516
506
|
renderMode?: RenderMode;
|
|
517
|
-
/** Spectrogram data for this channel */
|
|
518
|
-
spectrogramData?: SpectrogramData;
|
|
519
|
-
/** 256-entry RGB LUT from getColorMap() */
|
|
520
|
-
spectrogramColorLUT?: Uint8Array;
|
|
521
507
|
/** Samples per pixel at current zoom level */
|
|
522
508
|
samplesPerPixel?: number;
|
|
523
|
-
/** Frequency scale function */
|
|
524
|
-
spectrogramFrequencyScaleFn?: (f: number, minF: number, maxF: number) => number;
|
|
525
|
-
/** Min frequency in Hz */
|
|
526
|
-
spectrogramMinFrequency?: number;
|
|
527
|
-
/** Max frequency in Hz */
|
|
528
|
-
spectrogramMaxFrequency?: number;
|
|
529
509
|
/** Worker API for OffscreenCanvas transfer */
|
|
530
510
|
spectrogramWorkerApi?: SpectrogramWorkerCanvasApi;
|
|
531
511
|
/** Clip ID for worker canvas registration */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import react__default, { FunctionComponent, ReactNode, Dispatch, SetStateAction } from 'react';
|
|
3
|
-
import { Peaks, Bits, Fade, FadeType, MidiNoteData,
|
|
3
|
+
import { Peaks, Bits, Fade, FadeType, MidiNoteData, RenderMode } from '@waveform-playlist/core';
|
|
4
4
|
import * as styled_components_dist_utils_hoist from 'styled-components/dist/utils/hoist';
|
|
5
5
|
import * as styled_components from 'styled-components';
|
|
6
6
|
import { DefaultTheme } from 'styled-components';
|
|
@@ -476,8 +476,6 @@ interface SpectrogramChannelProps {
|
|
|
476
476
|
index: number;
|
|
477
477
|
/** Audio channel index for canvas ID construction. Defaults to `index` when omitted. */
|
|
478
478
|
channelIndex?: number;
|
|
479
|
-
/** Computed spectrogram data (not needed when workerApi is provided) */
|
|
480
|
-
data?: SpectrogramData;
|
|
481
479
|
/** Width in CSS pixels */
|
|
482
480
|
length: number;
|
|
483
481
|
/** Height in CSS pixels */
|
|
@@ -486,18 +484,10 @@ interface SpectrogramChannelProps {
|
|
|
486
484
|
devicePixelRatio?: number;
|
|
487
485
|
/** Samples per pixel at current zoom level */
|
|
488
486
|
samplesPerPixel: number;
|
|
489
|
-
/**
|
|
490
|
-
|
|
491
|
-
/** Frequency scale function: (freqHz, minF, maxF) => [0,1] */
|
|
492
|
-
frequencyScaleFn?: (f: number, minF: number, maxF: number) => number;
|
|
493
|
-
/** Min frequency in Hz */
|
|
494
|
-
minFrequency?: number;
|
|
495
|
-
/** Max frequency in Hz (defaults to sampleRate/2) */
|
|
496
|
-
maxFrequency?: number;
|
|
497
|
-
/** Worker API for transferring canvas ownership. When provided, rendering is done in the worker. */
|
|
498
|
-
workerApi?: SpectrogramWorkerCanvasApi;
|
|
487
|
+
/** Worker API for transferring canvas ownership. Rendering is done in the worker. */
|
|
488
|
+
workerApi: SpectrogramWorkerCanvasApi;
|
|
499
489
|
/** Clip ID used to construct unique canvas IDs for worker registration */
|
|
500
|
-
clipId
|
|
490
|
+
clipId: string;
|
|
501
491
|
/** Callback when canvases are registered with the worker, providing canvas IDs and widths */
|
|
502
492
|
onCanvasesReady?: (canvasIds: string[], canvasWidths: number[]) => void;
|
|
503
493
|
}
|
|
@@ -514,18 +504,8 @@ interface SmartChannelProps {
|
|
|
514
504
|
transparentBackground?: boolean;
|
|
515
505
|
/** Render mode: waveform, spectrogram, or both */
|
|
516
506
|
renderMode?: RenderMode;
|
|
517
|
-
/** Spectrogram data for this channel */
|
|
518
|
-
spectrogramData?: SpectrogramData;
|
|
519
|
-
/** 256-entry RGB LUT from getColorMap() */
|
|
520
|
-
spectrogramColorLUT?: Uint8Array;
|
|
521
507
|
/** Samples per pixel at current zoom level */
|
|
522
508
|
samplesPerPixel?: number;
|
|
523
|
-
/** Frequency scale function */
|
|
524
|
-
spectrogramFrequencyScaleFn?: (f: number, minF: number, maxF: number) => number;
|
|
525
|
-
/** Min frequency in Hz */
|
|
526
|
-
spectrogramMinFrequency?: number;
|
|
527
|
-
/** Max frequency in Hz */
|
|
528
|
-
spectrogramMaxFrequency?: number;
|
|
529
509
|
/** Worker API for OffscreenCanvas transfer */
|
|
530
510
|
spectrogramWorkerApi?: SpectrogramWorkerCanvasApi;
|
|
531
511
|
/** Clip ID for worker canvas registration */
|
package/dist/index.js
CHANGED
|
@@ -2411,7 +2411,6 @@ var import_react20 = require("react");
|
|
|
2411
2411
|
var import_styled_components21 = __toESM(require("styled-components"));
|
|
2412
2412
|
var import_core5 = require("@waveform-playlist/core");
|
|
2413
2413
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2414
|
-
var LINEAR_FREQUENCY_SCALE = (f, minF, maxF) => (f - minF) / (maxF - minF);
|
|
2415
2414
|
var Wrapper4 = import_styled_components21.default.div.attrs((props) => ({
|
|
2416
2415
|
style: {
|
|
2417
2416
|
top: `${props.$waveHeight * props.$index}px`,
|
|
@@ -2436,26 +2435,13 @@ var SpectrogramCanvas = import_styled_components21.default.canvas.attrs((props)
|
|
|
2436
2435
|
image-rendering: pixelated;
|
|
2437
2436
|
image-rendering: crisp-edges;
|
|
2438
2437
|
`;
|
|
2439
|
-
function defaultGetColorMap() {
|
|
2440
|
-
const lut = new Uint8Array(256 * 3);
|
|
2441
|
-
for (let i = 0; i < 256; i++) {
|
|
2442
|
-
lut[i * 3] = lut[i * 3 + 1] = lut[i * 3 + 2] = i;
|
|
2443
|
-
}
|
|
2444
|
-
return lut;
|
|
2445
|
-
}
|
|
2446
|
-
var DEFAULT_COLOR_LUT = defaultGetColorMap();
|
|
2447
2438
|
var SpectrogramChannel = ({
|
|
2448
2439
|
index,
|
|
2449
2440
|
channelIndex: channelIndexProp,
|
|
2450
|
-
data,
|
|
2451
2441
|
length,
|
|
2452
2442
|
waveHeight,
|
|
2453
2443
|
devicePixelRatio = 1,
|
|
2454
|
-
samplesPerPixel,
|
|
2455
|
-
colorLUT,
|
|
2456
|
-
frequencyScaleFn,
|
|
2457
|
-
minFrequency = 0,
|
|
2458
|
-
maxFrequency,
|
|
2444
|
+
samplesPerPixel: _samplesPerPixel,
|
|
2459
2445
|
workerApi,
|
|
2460
2446
|
clipId,
|
|
2461
2447
|
onCanvasesReady
|
|
@@ -2466,13 +2452,8 @@ var SpectrogramChannel = ({
|
|
|
2466
2452
|
const transferredCanvasesRef = (0, import_react20.useRef)(/* @__PURE__ */ new WeakSet());
|
|
2467
2453
|
const workerApiRef = (0, import_react20.useRef)(workerApi);
|
|
2468
2454
|
const onCanvasesReadyRef = (0, import_react20.useRef)(onCanvasesReady);
|
|
2469
|
-
const isWorkerMode = !!(workerApi && clipId);
|
|
2470
2455
|
const clipOriginX = useClipViewportOrigin();
|
|
2471
2456
|
const visibleChunkIndices = useVisibleChunkIndices(length, import_core5.MAX_CANVAS_WIDTH, clipOriginX);
|
|
2472
|
-
const lut = colorLUT ?? DEFAULT_COLOR_LUT;
|
|
2473
|
-
const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
|
|
2474
|
-
const scaleFn = frequencyScaleFn ?? LINEAR_FREQUENCY_SCALE;
|
|
2475
|
-
const hasCustomFrequencyScale = Boolean(frequencyScaleFn);
|
|
2476
2457
|
(0, import_react20.useEffect)(() => {
|
|
2477
2458
|
workerApiRef.current = workerApi;
|
|
2478
2459
|
}, [workerApi]);
|
|
@@ -2480,7 +2461,6 @@ var SpectrogramChannel = ({
|
|
|
2480
2461
|
onCanvasesReadyRef.current = onCanvasesReady;
|
|
2481
2462
|
}, [onCanvasesReady]);
|
|
2482
2463
|
(0, import_react20.useEffect)(() => {
|
|
2483
|
-
if (!isWorkerMode) return;
|
|
2484
2464
|
const currentWorkerApi = workerApiRef.current;
|
|
2485
2465
|
if (!currentWorkerApi || !clipId) return;
|
|
2486
2466
|
const previousCount = registeredIdsRef.current.length;
|
|
@@ -2541,7 +2521,7 @@ var SpectrogramChannel = ({
|
|
|
2541
2521
|
});
|
|
2542
2522
|
onCanvasesReadyRef.current?.(allIds, allWidths);
|
|
2543
2523
|
}
|
|
2544
|
-
}, [canvasMapRef,
|
|
2524
|
+
}, [canvasMapRef, clipId, channelIndex, length, visibleChunkIndices]);
|
|
2545
2525
|
(0, import_react20.useEffect)(() => {
|
|
2546
2526
|
return () => {
|
|
2547
2527
|
const api = workerApiRef.current;
|
|
@@ -2556,94 +2536,6 @@ var SpectrogramChannel = ({
|
|
|
2556
2536
|
registeredIdsRef.current = [];
|
|
2557
2537
|
};
|
|
2558
2538
|
}, []);
|
|
2559
|
-
(0, import_react20.useLayoutEffect)(() => {
|
|
2560
|
-
if (isWorkerMode || !data) return;
|
|
2561
|
-
const {
|
|
2562
|
-
frequencyBinCount,
|
|
2563
|
-
frameCount,
|
|
2564
|
-
hopSize,
|
|
2565
|
-
sampleRate,
|
|
2566
|
-
gainDb,
|
|
2567
|
-
rangeDb: rawRangeDb
|
|
2568
|
-
} = data;
|
|
2569
|
-
const rangeDb = rawRangeDb === 0 ? 1 : rawRangeDb;
|
|
2570
|
-
const binToFreq = (bin) => bin / frequencyBinCount * (sampleRate / 2);
|
|
2571
|
-
for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
|
|
2572
|
-
const globalPixelOffset = canvasIdx * import_core5.MAX_CANVAS_WIDTH;
|
|
2573
|
-
const ctx = canvas.getContext("2d");
|
|
2574
|
-
if (!ctx) continue;
|
|
2575
|
-
const canvasWidth = canvas.width / devicePixelRatio;
|
|
2576
|
-
const canvasHeight = waveHeight;
|
|
2577
|
-
ctx.resetTransform();
|
|
2578
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2579
|
-
ctx.imageSmoothingEnabled = false;
|
|
2580
|
-
ctx.scale(devicePixelRatio, devicePixelRatio);
|
|
2581
|
-
const imgData = ctx.createImageData(canvasWidth, canvasHeight);
|
|
2582
|
-
const pixels = imgData.data;
|
|
2583
|
-
for (let x = 0; x < canvasWidth; x++) {
|
|
2584
|
-
const globalX = globalPixelOffset + x;
|
|
2585
|
-
const samplePos = globalX * samplesPerPixel;
|
|
2586
|
-
const frame = Math.floor(samplePos / hopSize);
|
|
2587
|
-
if (frame < 0 || frame >= frameCount) continue;
|
|
2588
|
-
const frameOffset = frame * frequencyBinCount;
|
|
2589
|
-
for (let y = 0; y < canvasHeight; y++) {
|
|
2590
|
-
const normalizedY = 1 - y / canvasHeight;
|
|
2591
|
-
let bin = Math.floor(normalizedY * frequencyBinCount);
|
|
2592
|
-
if (hasCustomFrequencyScale) {
|
|
2593
|
-
let lo = 0;
|
|
2594
|
-
let hi = frequencyBinCount - 1;
|
|
2595
|
-
while (lo < hi) {
|
|
2596
|
-
const mid = lo + hi >> 1;
|
|
2597
|
-
const freq = binToFreq(mid);
|
|
2598
|
-
const scaled = scaleFn(freq, minFrequency, maxF);
|
|
2599
|
-
if (scaled < normalizedY) {
|
|
2600
|
-
lo = mid + 1;
|
|
2601
|
-
} else {
|
|
2602
|
-
hi = mid;
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
bin = lo;
|
|
2606
|
-
}
|
|
2607
|
-
if (bin < 0 || bin >= frequencyBinCount) continue;
|
|
2608
|
-
const db = data.data[frameOffset + bin];
|
|
2609
|
-
const normalized = Math.max(0, Math.min(1, (db + rangeDb + gainDb) / rangeDb));
|
|
2610
|
-
const colorIdx = Math.floor(normalized * 255);
|
|
2611
|
-
const pixelIdx = (y * canvasWidth + x) * 4;
|
|
2612
|
-
pixels[pixelIdx] = lut[colorIdx * 3];
|
|
2613
|
-
pixels[pixelIdx + 1] = lut[colorIdx * 3 + 1];
|
|
2614
|
-
pixels[pixelIdx + 2] = lut[colorIdx * 3 + 2];
|
|
2615
|
-
pixels[pixelIdx + 3] = 255;
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
ctx.resetTransform();
|
|
2619
|
-
ctx.putImageData(imgData, 0, 0);
|
|
2620
|
-
if (devicePixelRatio !== 1) {
|
|
2621
|
-
const tmpCanvas = document.createElement("canvas");
|
|
2622
|
-
tmpCanvas.width = canvasWidth;
|
|
2623
|
-
tmpCanvas.height = canvasHeight;
|
|
2624
|
-
const tmpCtx = tmpCanvas.getContext("2d");
|
|
2625
|
-
if (!tmpCtx) continue;
|
|
2626
|
-
tmpCtx.putImageData(imgData, 0, 0);
|
|
2627
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2628
|
-
ctx.imageSmoothingEnabled = false;
|
|
2629
|
-
ctx.drawImage(tmpCanvas, 0, 0, canvas.width, canvas.height);
|
|
2630
|
-
}
|
|
2631
|
-
}
|
|
2632
|
-
}, [
|
|
2633
|
-
canvasMapRef,
|
|
2634
|
-
isWorkerMode,
|
|
2635
|
-
data,
|
|
2636
|
-
length,
|
|
2637
|
-
waveHeight,
|
|
2638
|
-
devicePixelRatio,
|
|
2639
|
-
samplesPerPixel,
|
|
2640
|
-
lut,
|
|
2641
|
-
minFrequency,
|
|
2642
|
-
maxF,
|
|
2643
|
-
scaleFn,
|
|
2644
|
-
hasCustomFrequencyScale,
|
|
2645
|
-
visibleChunkIndices
|
|
2646
|
-
]);
|
|
2647
2539
|
const canvases = visibleChunkIndices.map((i) => {
|
|
2648
2540
|
const chunkLeft = i * import_core5.MAX_CANVAS_WIDTH;
|
|
2649
2541
|
const currentWidth = Math.min(length - chunkLeft, import_core5.MAX_CANVAS_WIDTH);
|
|
@@ -2670,12 +2562,7 @@ var SmartChannel = ({
|
|
|
2670
2562
|
isSelected,
|
|
2671
2563
|
transparentBackground,
|
|
2672
2564
|
renderMode = "waveform",
|
|
2673
|
-
spectrogramData,
|
|
2674
|
-
spectrogramColorLUT,
|
|
2675
2565
|
samplesPerPixel: sppProp,
|
|
2676
|
-
spectrogramFrequencyScaleFn,
|
|
2677
|
-
spectrogramMinFrequency,
|
|
2678
|
-
spectrogramMaxFrequency,
|
|
2679
2566
|
spectrogramWorkerApi,
|
|
2680
2567
|
spectrogramClipId,
|
|
2681
2568
|
spectrogramOnCanvasesReady,
|
|
@@ -2697,21 +2584,16 @@ var SmartChannel = ({
|
|
|
2697
2584
|
const waveOutlineColor = isSelected && theme ? theme.selectedWaveOutlineColor : theme?.waveOutlineColor;
|
|
2698
2585
|
const waveFillColor = isSelected && theme ? theme.selectedWaveFillColor : theme?.waveFillColor;
|
|
2699
2586
|
const drawMode = theme?.waveformDrawMode || "inverted";
|
|
2700
|
-
const hasSpectrogram =
|
|
2587
|
+
const hasSpectrogram = spectrogramWorkerApi && spectrogramClipId;
|
|
2701
2588
|
if (renderMode === "spectrogram" && hasSpectrogram) {
|
|
2702
2589
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2703
2590
|
SpectrogramChannel,
|
|
2704
2591
|
{
|
|
2705
2592
|
index: props.index,
|
|
2706
|
-
data: spectrogramData,
|
|
2707
2593
|
length: props.length,
|
|
2708
2594
|
waveHeight,
|
|
2709
2595
|
devicePixelRatio,
|
|
2710
2596
|
samplesPerPixel,
|
|
2711
|
-
colorLUT: spectrogramColorLUT,
|
|
2712
|
-
frequencyScaleFn: spectrogramFrequencyScaleFn,
|
|
2713
|
-
minFrequency: spectrogramMinFrequency,
|
|
2714
|
-
maxFrequency: spectrogramMaxFrequency,
|
|
2715
2597
|
workerApi: spectrogramWorkerApi,
|
|
2716
2598
|
clipId: spectrogramClipId,
|
|
2717
2599
|
onCanvasesReady: spectrogramOnCanvasesReady
|
|
@@ -2726,15 +2608,10 @@ var SmartChannel = ({
|
|
|
2726
2608
|
{
|
|
2727
2609
|
index: props.index * 2,
|
|
2728
2610
|
channelIndex: props.index,
|
|
2729
|
-
data: spectrogramData,
|
|
2730
2611
|
length: props.length,
|
|
2731
2612
|
waveHeight: halfHeight,
|
|
2732
2613
|
devicePixelRatio,
|
|
2733
2614
|
samplesPerPixel,
|
|
2734
|
-
colorLUT: spectrogramColorLUT,
|
|
2735
|
-
frequencyScaleFn: spectrogramFrequencyScaleFn,
|
|
2736
|
-
minFrequency: spectrogramMinFrequency,
|
|
2737
|
-
maxFrequency: spectrogramMaxFrequency,
|
|
2738
2615
|
workerApi: spectrogramWorkerApi,
|
|
2739
2616
|
clipId: spectrogramClipId,
|
|
2740
2617
|
onCanvasesReady: spectrogramOnCanvasesReady
|