@dawcore/components 0.0.9 → 0.0.11
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/README.md +18 -20
- package/dist/index.d.mts +129 -3
- package/dist/index.d.ts +129 -3
- package/dist/index.js +816 -182
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +799 -166
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -14
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ npm install @waveform-playlist/core @waveform-playlist/engine @dawcore/transport
|
|
|
31
31
|
|
|
32
32
|
Optional (for recording):
|
|
33
33
|
```bash
|
|
34
|
-
npm install @waveform-playlist/
|
|
34
|
+
npm install @waveform-playlist/worklets
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
## Quick Start
|
|
@@ -97,30 +97,28 @@ Access the native transport for tempo, metronome, count-in, meter, and effects:
|
|
|
97
97
|
```javascript
|
|
98
98
|
const editor = document.getElementById('editor');
|
|
99
99
|
|
|
100
|
-
//
|
|
101
|
-
editor.
|
|
102
|
-
|
|
103
|
-
if (!transport) return;
|
|
100
|
+
// Build engine eagerly so transport is available immediately
|
|
101
|
+
await editor._ensureEngine();
|
|
102
|
+
const transport = editor.transport;
|
|
104
103
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
// Tempo & meter
|
|
105
|
+
transport.setTempo(140);
|
|
106
|
+
transport.setMeter(3, 4);
|
|
108
107
|
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
// Metronome (default click sounds built in)
|
|
109
|
+
transport.setMetronomeEnabled(true);
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
// Count-in
|
|
112
|
+
transport.setCountIn(true);
|
|
113
|
+
transport.setCountInBars(1);
|
|
114
|
+
transport.setCountInMode('always');
|
|
116
115
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// Effects hook — insert any AudioNode chain
|
|
122
|
-
transport.connectTrackOutput('track-id', reverbNode);
|
|
116
|
+
transport.on('countIn', ({ beat, totalBeats }) => {
|
|
117
|
+
console.log(beat + '/' + totalBeats);
|
|
123
118
|
});
|
|
119
|
+
|
|
120
|
+
// Effects hook — insert any AudioNode chain
|
|
121
|
+
transport.connectTrackOutput('track-id', reverbNode);
|
|
124
122
|
```
|
|
125
123
|
|
|
126
124
|
## Programmatic File Loading
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as lit from 'lit';
|
|
2
2
|
import { LitElement, PropertyValues, ReactiveController, ReactiveControllerHost } from 'lit';
|
|
3
|
-
import { Peaks, Bits, FadeType, PeakData, ClipTrack, KeyboardShortcut } from '@waveform-playlist/core';
|
|
3
|
+
import { Peaks, Bits, FadeType, PeakData, MeterEntry, SnapTo, ClipTrack, KeyboardShortcut } from '@waveform-playlist/core';
|
|
4
4
|
import WaveformData from 'waveform-data';
|
|
5
5
|
import { PlaylistEngine } from '@waveform-playlist/engine';
|
|
6
|
+
import { Transport } from '@dawcore/transport';
|
|
6
7
|
|
|
7
8
|
declare class DawClipElement extends LitElement {
|
|
8
9
|
src: string;
|
|
@@ -44,6 +45,17 @@ declare global {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
/** A segment mapping a peak-index range to a pixel range within the waveform. */
|
|
49
|
+
interface WaveformSegment {
|
|
50
|
+
/** Start position in the peaks array (fractional index). */
|
|
51
|
+
peakStart: number;
|
|
52
|
+
/** End position in the peaks array (fractional index). */
|
|
53
|
+
peakEnd: number;
|
|
54
|
+
/** Start pixel position within the waveform. */
|
|
55
|
+
pixelStart: number;
|
|
56
|
+
/** End pixel position within the waveform. */
|
|
57
|
+
pixelEnd: number;
|
|
58
|
+
}
|
|
47
59
|
declare class DawWaveformElement extends LitElement {
|
|
48
60
|
private _peaks;
|
|
49
61
|
private _dirtyPixels;
|
|
@@ -70,6 +82,8 @@ declare class DawWaveformElement extends LitElement {
|
|
|
70
82
|
visibleEnd: number;
|
|
71
83
|
/** This element's left offset on the timeline (for viewport intersection). */
|
|
72
84
|
originX: number;
|
|
85
|
+
/** When set, draws per-segment with independent samples-per-pixel ratios. */
|
|
86
|
+
segments?: WaveformSegment[];
|
|
73
87
|
static styles: lit.CSSResult;
|
|
74
88
|
private _getVisibleChunkIndices;
|
|
75
89
|
/**
|
|
@@ -82,6 +96,7 @@ declare class DawWaveformElement extends LitElement {
|
|
|
82
96
|
private _scheduleDraw;
|
|
83
97
|
private _drawDirty;
|
|
84
98
|
private _drawChunk;
|
|
99
|
+
private _drawSegments;
|
|
85
100
|
connectedCallback(): void;
|
|
86
101
|
disconnectedCallback(): void;
|
|
87
102
|
render(): lit.TemplateResult<1>;
|
|
@@ -103,6 +118,10 @@ declare class DawPlayheadElement extends LitElement {
|
|
|
103
118
|
firstUpdated(): void;
|
|
104
119
|
startAnimation(getTime: () => number, sampleRate: number, samplesPerPixel: number): void;
|
|
105
120
|
stopAnimation(time: number, sampleRate: number, samplesPerPixel: number): void;
|
|
121
|
+
startBeatsAnimation(getTime: () => number, bpm: number, ppqn: number, ticksPerPixel: number): void;
|
|
122
|
+
stopBeatsAnimation(time: number, bpm: number, ppqn: number, ticksPerPixel: number): void;
|
|
123
|
+
startBeatsAnimationWithMap(getTime: () => number, secondsToTicks: (s: number) => number, ticksPerPixel: number): void;
|
|
124
|
+
stopBeatsAnimationWithMap(time: number, secondsToTicks: (s: number) => number, ticksPerPixel: number): void;
|
|
106
125
|
}
|
|
107
126
|
declare global {
|
|
108
127
|
interface HTMLElementTagNameMap {
|
|
@@ -243,6 +262,15 @@ declare class PeakPipeline {
|
|
|
243
262
|
* (default); reextractPeaks passes false and logs a single summary instead.
|
|
244
263
|
*/
|
|
245
264
|
private _clampScale;
|
|
265
|
+
/**
|
|
266
|
+
* Extract peaks at the base scale from cached WaveformData.
|
|
267
|
+
* Returns null if no cached data exists for this buffer.
|
|
268
|
+
* Used by variable-tempo segments which handle stretching themselves.
|
|
269
|
+
*/
|
|
270
|
+
getBaseScalePeaks(audioBuffer: AudioBuffer, isMono: boolean, offsetSamples?: number, durationSamples?: number): {
|
|
271
|
+
peaks: PeakData;
|
|
272
|
+
scale: number;
|
|
273
|
+
} | null;
|
|
246
274
|
/**
|
|
247
275
|
* Return the coarsest (largest) scale among cached WaveformData entries
|
|
248
276
|
* that correspond to the given clip buffers. Returns 0 if none are cached.
|
|
@@ -275,6 +303,43 @@ declare global {
|
|
|
275
303
|
}
|
|
276
304
|
}
|
|
277
305
|
|
|
306
|
+
/**
|
|
307
|
+
* `<daw-grid>` renders a musical grid overlay behind waveforms using the
|
|
308
|
+
* Audacity three-tier model:
|
|
309
|
+
*
|
|
310
|
+
* - **Zebra stripes**: Alternating bar backgrounds at 2% white opacity.
|
|
311
|
+
* - **Major lines** (bars): 10% white opacity, full height.
|
|
312
|
+
* - **Minor lines** (beats): 6% white opacity, full height.
|
|
313
|
+
* - **MinorMinor** (subdivisions): Ruler ticks only — no grid lines.
|
|
314
|
+
*
|
|
315
|
+
* Uses chunked 1000px canvases with virtual scrolling (same as daw-waveform).
|
|
316
|
+
*
|
|
317
|
+
* CSS custom properties:
|
|
318
|
+
* --daw-grid-bar-highlight Alternating bar fill (default: rgba(255,255,255,0.02))
|
|
319
|
+
* --daw-grid-major-line Bar line color (default: rgba(255,255,255,0.1))
|
|
320
|
+
* --daw-grid-minor-line Beat line color (default: rgba(255,255,255,0.06))
|
|
321
|
+
*/
|
|
322
|
+
declare class DawGridElement extends LitElement {
|
|
323
|
+
ticksPerPixel: number;
|
|
324
|
+
meterEntries: MeterEntry[];
|
|
325
|
+
ppqn: number;
|
|
326
|
+
visibleStart: number;
|
|
327
|
+
visibleEnd: number;
|
|
328
|
+
length: number;
|
|
329
|
+
height: number;
|
|
330
|
+
private _tickData;
|
|
331
|
+
static styles: lit.CSSResult;
|
|
332
|
+
willUpdate(): void;
|
|
333
|
+
render(): lit.TemplateResult<1>;
|
|
334
|
+
updated(): void;
|
|
335
|
+
private _drawGrid;
|
|
336
|
+
}
|
|
337
|
+
declare global {
|
|
338
|
+
interface HTMLElementTagNameMap {
|
|
339
|
+
'daw-grid': DawGridElement;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
278
343
|
interface RecordingOptions {
|
|
279
344
|
trackId?: string;
|
|
280
345
|
bits?: 8 | 16;
|
|
@@ -379,10 +444,20 @@ interface ClipPeakSlice {
|
|
|
379
444
|
/** Host interface required by ClipPointerHandler. */
|
|
380
445
|
interface ClipPointerHost {
|
|
381
446
|
readonly samplesPerPixel: number;
|
|
447
|
+
/** In beats mode, the tick-derived SPP used for rendering. */
|
|
448
|
+
readonly renderSamplesPerPixel: number;
|
|
382
449
|
readonly effectiveSampleRate: number;
|
|
383
450
|
readonly interactiveClips: boolean;
|
|
384
451
|
readonly engine: ClipEngineContract | null;
|
|
385
452
|
readonly shadowRoot: ShadowRoot | null;
|
|
453
|
+
readonly scaleMode: 'temporal' | 'beats';
|
|
454
|
+
readonly ticksPerPixel: number;
|
|
455
|
+
readonly bpm: number;
|
|
456
|
+
readonly ppqn: number;
|
|
457
|
+
readonly _meterEntries: MeterEntry[];
|
|
458
|
+
readonly snapTo: SnapTo;
|
|
459
|
+
readonly _secondsToTicks: (seconds: number) => number;
|
|
460
|
+
readonly _ticksToSeconds: (ticks: number) => number;
|
|
386
461
|
dispatchEvent(event: Event): boolean;
|
|
387
462
|
/** Re-extract peaks for a clip at new offset/duration from cached WaveformData. */
|
|
388
463
|
reextractClipPeaks(clipId: string, offsetSamples: number, durationSamples: number): ClipPeakSlice | null;
|
|
@@ -404,7 +479,6 @@ declare class ClipPointerHandler {
|
|
|
404
479
|
private _trackId;
|
|
405
480
|
private _startPx;
|
|
406
481
|
private _isDragging;
|
|
407
|
-
private _lastDeltaPx;
|
|
408
482
|
private _cumulativeDeltaSamples;
|
|
409
483
|
private _clipContainer;
|
|
410
484
|
private _boundaryEl;
|
|
@@ -412,7 +486,17 @@ declare class ClipPointerHandler {
|
|
|
412
486
|
private _originalWidth;
|
|
413
487
|
private _originalOffsetSamples;
|
|
414
488
|
private _originalDurationSamples;
|
|
489
|
+
private _originalStartSample;
|
|
415
490
|
constructor(host: ClipPointerHost);
|
|
491
|
+
/**
|
|
492
|
+
* Convert a pixel delta to samples, snapping in tick space when in beats mode.
|
|
493
|
+
*
|
|
494
|
+
* The anchor is the absolute sample position being moved (e.g., clip start
|
|
495
|
+
* for move/left-trim, clip end for right-trim). Snapping the absolute
|
|
496
|
+
* position — not just the delta — ensures clips land exactly on grid lines
|
|
497
|
+
* even if they started off-grid.
|
|
498
|
+
*/
|
|
499
|
+
private _snapDeltaToSamples;
|
|
416
500
|
/** Returns true if a drag interaction is currently in progress. */
|
|
417
501
|
get isActive(): boolean;
|
|
418
502
|
/**
|
|
@@ -550,6 +634,25 @@ declare class DawEditorElement extends LitElement {
|
|
|
550
634
|
clipHeaders: boolean;
|
|
551
635
|
clipHeaderHeight: number;
|
|
552
636
|
interactiveClips: boolean;
|
|
637
|
+
scaleMode: 'temporal' | 'beats';
|
|
638
|
+
get ticksPerPixel(): number;
|
|
639
|
+
set ticksPerPixel(value: number);
|
|
640
|
+
private _ticksPerPixel;
|
|
641
|
+
get bpm(): number;
|
|
642
|
+
set bpm(value: number);
|
|
643
|
+
private _bpm;
|
|
644
|
+
timeSignature: [number, number];
|
|
645
|
+
meterEntries?: MeterEntry[];
|
|
646
|
+
/** MeterEntries for grid/ruler: explicit meterEntries if set, otherwise derived from timeSignature. */
|
|
647
|
+
get _meterEntries(): MeterEntry[];
|
|
648
|
+
get ppqn(): number;
|
|
649
|
+
set ppqn(value: number);
|
|
650
|
+
private _ppqn;
|
|
651
|
+
snapTo: SnapTo;
|
|
652
|
+
/** Optional tempo-aware conversion: seconds → PPQN ticks. When provided, enables variable tempo. */
|
|
653
|
+
secondsToTicks?: (seconds: number) => number;
|
|
654
|
+
/** Optional tempo-aware conversion: PPQN ticks → seconds. Required alongside secondsToTicks. */
|
|
655
|
+
ticksToSeconds?: (ticks: number) => number;
|
|
553
656
|
/** Desired sample rate. Creates a cross-browser AudioContext at this rate.
|
|
554
657
|
* Pre-computed .dat peaks render instantly when they match. */
|
|
555
658
|
sampleRate: number;
|
|
@@ -572,6 +675,9 @@ declare class DawEditorElement extends LitElement {
|
|
|
572
675
|
set audioContext(ctx: AudioContext | null);
|
|
573
676
|
get audioContext(): AudioContext;
|
|
574
677
|
_engine: PlaylistEngine | null;
|
|
678
|
+
private _adapter;
|
|
679
|
+
private _warnedMissingTicksToSeconds;
|
|
680
|
+
private _warnedMissingSecondsToTicks;
|
|
575
681
|
private _enginePromise;
|
|
576
682
|
_audioCache: Map<string, Promise<AudioBuffer>>;
|
|
577
683
|
private _peaksCache;
|
|
@@ -591,6 +697,9 @@ declare class DawEditorElement extends LitElement {
|
|
|
591
697
|
private _clipPointer;
|
|
592
698
|
get _clipHandler(): ClipPointerHandler | null;
|
|
593
699
|
get engine(): PlaylistEngine | null;
|
|
700
|
+
/** The adapter's Transport — use for tempo, metronome, and effects. */
|
|
701
|
+
get transport(): Transport | null;
|
|
702
|
+
get renderSamplesPerPixel(): number;
|
|
594
703
|
/** Re-extract peaks for a clip at new offset/duration from cached WaveformData. */
|
|
595
704
|
reextractClipPeaks(clipId: string, offsetSamples: number, durationSamples: number): {
|
|
596
705
|
data: Peaks[];
|
|
@@ -601,7 +710,18 @@ declare class DawEditorElement extends LitElement {
|
|
|
601
710
|
static styles: lit.CSSResult[];
|
|
602
711
|
get effectiveSampleRate(): number;
|
|
603
712
|
resolveAudioContextSampleRate(rate: number): void;
|
|
713
|
+
/**
|
|
714
|
+
* In beats mode, derive samplesPerPixel from ticksPerPixel so that
|
|
715
|
+
* clip positions, waveforms, and the tick-space grid all align.
|
|
716
|
+
*/
|
|
717
|
+
private get _renderSpp();
|
|
718
|
+
/** Convert seconds to ticks — uses callback if provided, otherwise single-BPM fallback. */
|
|
719
|
+
_secondsToTicks(seconds: number): number;
|
|
720
|
+
/** Convert ticks to seconds — uses callback if provided, otherwise single-BPM fallback. */
|
|
721
|
+
_ticksToSeconds(ticks: number): number;
|
|
604
722
|
private get _totalWidth();
|
|
723
|
+
/** Grid height when no tracks exist — matches scroll area's rendered height. */
|
|
724
|
+
private get _emptyGridHeight();
|
|
605
725
|
_setSelectedTrackId(trackId: string | null): void;
|
|
606
726
|
get tracks(): TrackDescriptor[];
|
|
607
727
|
get selectedTrackId(): string | null;
|
|
@@ -673,7 +793,13 @@ declare class DawRulerElement extends LitElement {
|
|
|
673
793
|
sampleRate: number;
|
|
674
794
|
duration: number;
|
|
675
795
|
rulerHeight: number;
|
|
796
|
+
scaleMode: 'temporal' | 'beats';
|
|
797
|
+
ticksPerPixel: number;
|
|
798
|
+
meterEntries: MeterEntry[];
|
|
799
|
+
ppqn: number;
|
|
800
|
+
totalWidth: number;
|
|
676
801
|
private _tickData;
|
|
802
|
+
private _musicalTickData;
|
|
677
803
|
static styles: lit.CSSResult;
|
|
678
804
|
willUpdate(): void;
|
|
679
805
|
render(): lit.TemplateResult<1>;
|
|
@@ -827,4 +953,4 @@ interface SplitHost {
|
|
|
827
953
|
*/
|
|
828
954
|
declare function splitAtPlayhead(host: SplitHost): boolean;
|
|
829
955
|
|
|
830
|
-
export { AudioResumeController, type ClipDescriptor, type ClipEngineContract, ClipPointerHandler, type ClipPointerHost, DawClipElement, type DawClipMoveDetail, type DawClipSplitDetail, type DawClipTrimDetail, DawEditorElement, type DawErrorDetail, type DawEvent, type DawEventMap, type DawFilesLoadErrorDetail, DawKeyboardShortcutsElement, DawPauseButtonElement, DawPlayButtonElement, DawPlayheadElement, DawRecordButtonElement, type DawRecordingCompleteDetail, type DawRecordingErrorDetail, type DawRecordingStartDetail, DawRulerElement, type DawSeekDetail, type DawSelectionDetail, DawSelectionElement, DawStopButtonElement, type DawTrackConnectedDetail, type DawTrackControlDetail, DawTrackControlsElement, DawTrackElement, type DawTrackErrorDetail, type DawTrackIdDetail, type DawTrackRemoveDetail, type DawTrackSelectDetail, DawTransportButton, DawTransportElement, DawWaveformElement, type KeyBinding, type LoadFilesResult, type PlaybackShortcutMap, type PointerEngineContract, RecordingController, type RecordingOptions, type RecordingSession, type SplitEngineContract, type SplitHost, type SplittingShortcutMap, type TrackDescriptor, type UndoShortcutMap, splitAtPlayhead };
|
|
956
|
+
export { AudioResumeController, type ClipDescriptor, type ClipEngineContract, ClipPointerHandler, type ClipPointerHost, DawClipElement, type DawClipMoveDetail, type DawClipSplitDetail, type DawClipTrimDetail, DawEditorElement, type DawErrorDetail, type DawEvent, type DawEventMap, type DawFilesLoadErrorDetail, DawGridElement, DawKeyboardShortcutsElement, DawPauseButtonElement, DawPlayButtonElement, DawPlayheadElement, DawRecordButtonElement, type DawRecordingCompleteDetail, type DawRecordingErrorDetail, type DawRecordingStartDetail, DawRulerElement, type DawSeekDetail, type DawSelectionDetail, DawSelectionElement, DawStopButtonElement, type DawTrackConnectedDetail, type DawTrackControlDetail, DawTrackControlsElement, DawTrackElement, type DawTrackErrorDetail, type DawTrackIdDetail, type DawTrackRemoveDetail, type DawTrackSelectDetail, DawTransportButton, DawTransportElement, DawWaveformElement, type KeyBinding, type LoadFilesResult, type PlaybackShortcutMap, type PointerEngineContract, RecordingController, type RecordingOptions, type RecordingSession, type SplitEngineContract, type SplitHost, type SplittingShortcutMap, type TrackDescriptor, type UndoShortcutMap, type WaveformSegment, splitAtPlayhead };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as lit from 'lit';
|
|
2
2
|
import { LitElement, PropertyValues, ReactiveController, ReactiveControllerHost } from 'lit';
|
|
3
|
-
import { Peaks, Bits, FadeType, PeakData, ClipTrack, KeyboardShortcut } from '@waveform-playlist/core';
|
|
3
|
+
import { Peaks, Bits, FadeType, PeakData, MeterEntry, SnapTo, ClipTrack, KeyboardShortcut } from '@waveform-playlist/core';
|
|
4
4
|
import WaveformData from 'waveform-data';
|
|
5
5
|
import { PlaylistEngine } from '@waveform-playlist/engine';
|
|
6
|
+
import { Transport } from '@dawcore/transport';
|
|
6
7
|
|
|
7
8
|
declare class DawClipElement extends LitElement {
|
|
8
9
|
src: string;
|
|
@@ -44,6 +45,17 @@ declare global {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
/** A segment mapping a peak-index range to a pixel range within the waveform. */
|
|
49
|
+
interface WaveformSegment {
|
|
50
|
+
/** Start position in the peaks array (fractional index). */
|
|
51
|
+
peakStart: number;
|
|
52
|
+
/** End position in the peaks array (fractional index). */
|
|
53
|
+
peakEnd: number;
|
|
54
|
+
/** Start pixel position within the waveform. */
|
|
55
|
+
pixelStart: number;
|
|
56
|
+
/** End pixel position within the waveform. */
|
|
57
|
+
pixelEnd: number;
|
|
58
|
+
}
|
|
47
59
|
declare class DawWaveformElement extends LitElement {
|
|
48
60
|
private _peaks;
|
|
49
61
|
private _dirtyPixels;
|
|
@@ -70,6 +82,8 @@ declare class DawWaveformElement extends LitElement {
|
|
|
70
82
|
visibleEnd: number;
|
|
71
83
|
/** This element's left offset on the timeline (for viewport intersection). */
|
|
72
84
|
originX: number;
|
|
85
|
+
/** When set, draws per-segment with independent samples-per-pixel ratios. */
|
|
86
|
+
segments?: WaveformSegment[];
|
|
73
87
|
static styles: lit.CSSResult;
|
|
74
88
|
private _getVisibleChunkIndices;
|
|
75
89
|
/**
|
|
@@ -82,6 +96,7 @@ declare class DawWaveformElement extends LitElement {
|
|
|
82
96
|
private _scheduleDraw;
|
|
83
97
|
private _drawDirty;
|
|
84
98
|
private _drawChunk;
|
|
99
|
+
private _drawSegments;
|
|
85
100
|
connectedCallback(): void;
|
|
86
101
|
disconnectedCallback(): void;
|
|
87
102
|
render(): lit.TemplateResult<1>;
|
|
@@ -103,6 +118,10 @@ declare class DawPlayheadElement extends LitElement {
|
|
|
103
118
|
firstUpdated(): void;
|
|
104
119
|
startAnimation(getTime: () => number, sampleRate: number, samplesPerPixel: number): void;
|
|
105
120
|
stopAnimation(time: number, sampleRate: number, samplesPerPixel: number): void;
|
|
121
|
+
startBeatsAnimation(getTime: () => number, bpm: number, ppqn: number, ticksPerPixel: number): void;
|
|
122
|
+
stopBeatsAnimation(time: number, bpm: number, ppqn: number, ticksPerPixel: number): void;
|
|
123
|
+
startBeatsAnimationWithMap(getTime: () => number, secondsToTicks: (s: number) => number, ticksPerPixel: number): void;
|
|
124
|
+
stopBeatsAnimationWithMap(time: number, secondsToTicks: (s: number) => number, ticksPerPixel: number): void;
|
|
106
125
|
}
|
|
107
126
|
declare global {
|
|
108
127
|
interface HTMLElementTagNameMap {
|
|
@@ -243,6 +262,15 @@ declare class PeakPipeline {
|
|
|
243
262
|
* (default); reextractPeaks passes false and logs a single summary instead.
|
|
244
263
|
*/
|
|
245
264
|
private _clampScale;
|
|
265
|
+
/**
|
|
266
|
+
* Extract peaks at the base scale from cached WaveformData.
|
|
267
|
+
* Returns null if no cached data exists for this buffer.
|
|
268
|
+
* Used by variable-tempo segments which handle stretching themselves.
|
|
269
|
+
*/
|
|
270
|
+
getBaseScalePeaks(audioBuffer: AudioBuffer, isMono: boolean, offsetSamples?: number, durationSamples?: number): {
|
|
271
|
+
peaks: PeakData;
|
|
272
|
+
scale: number;
|
|
273
|
+
} | null;
|
|
246
274
|
/**
|
|
247
275
|
* Return the coarsest (largest) scale among cached WaveformData entries
|
|
248
276
|
* that correspond to the given clip buffers. Returns 0 if none are cached.
|
|
@@ -275,6 +303,43 @@ declare global {
|
|
|
275
303
|
}
|
|
276
304
|
}
|
|
277
305
|
|
|
306
|
+
/**
|
|
307
|
+
* `<daw-grid>` renders a musical grid overlay behind waveforms using the
|
|
308
|
+
* Audacity three-tier model:
|
|
309
|
+
*
|
|
310
|
+
* - **Zebra stripes**: Alternating bar backgrounds at 2% white opacity.
|
|
311
|
+
* - **Major lines** (bars): 10% white opacity, full height.
|
|
312
|
+
* - **Minor lines** (beats): 6% white opacity, full height.
|
|
313
|
+
* - **MinorMinor** (subdivisions): Ruler ticks only — no grid lines.
|
|
314
|
+
*
|
|
315
|
+
* Uses chunked 1000px canvases with virtual scrolling (same as daw-waveform).
|
|
316
|
+
*
|
|
317
|
+
* CSS custom properties:
|
|
318
|
+
* --daw-grid-bar-highlight Alternating bar fill (default: rgba(255,255,255,0.02))
|
|
319
|
+
* --daw-grid-major-line Bar line color (default: rgba(255,255,255,0.1))
|
|
320
|
+
* --daw-grid-minor-line Beat line color (default: rgba(255,255,255,0.06))
|
|
321
|
+
*/
|
|
322
|
+
declare class DawGridElement extends LitElement {
|
|
323
|
+
ticksPerPixel: number;
|
|
324
|
+
meterEntries: MeterEntry[];
|
|
325
|
+
ppqn: number;
|
|
326
|
+
visibleStart: number;
|
|
327
|
+
visibleEnd: number;
|
|
328
|
+
length: number;
|
|
329
|
+
height: number;
|
|
330
|
+
private _tickData;
|
|
331
|
+
static styles: lit.CSSResult;
|
|
332
|
+
willUpdate(): void;
|
|
333
|
+
render(): lit.TemplateResult<1>;
|
|
334
|
+
updated(): void;
|
|
335
|
+
private _drawGrid;
|
|
336
|
+
}
|
|
337
|
+
declare global {
|
|
338
|
+
interface HTMLElementTagNameMap {
|
|
339
|
+
'daw-grid': DawGridElement;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
278
343
|
interface RecordingOptions {
|
|
279
344
|
trackId?: string;
|
|
280
345
|
bits?: 8 | 16;
|
|
@@ -379,10 +444,20 @@ interface ClipPeakSlice {
|
|
|
379
444
|
/** Host interface required by ClipPointerHandler. */
|
|
380
445
|
interface ClipPointerHost {
|
|
381
446
|
readonly samplesPerPixel: number;
|
|
447
|
+
/** In beats mode, the tick-derived SPP used for rendering. */
|
|
448
|
+
readonly renderSamplesPerPixel: number;
|
|
382
449
|
readonly effectiveSampleRate: number;
|
|
383
450
|
readonly interactiveClips: boolean;
|
|
384
451
|
readonly engine: ClipEngineContract | null;
|
|
385
452
|
readonly shadowRoot: ShadowRoot | null;
|
|
453
|
+
readonly scaleMode: 'temporal' | 'beats';
|
|
454
|
+
readonly ticksPerPixel: number;
|
|
455
|
+
readonly bpm: number;
|
|
456
|
+
readonly ppqn: number;
|
|
457
|
+
readonly _meterEntries: MeterEntry[];
|
|
458
|
+
readonly snapTo: SnapTo;
|
|
459
|
+
readonly _secondsToTicks: (seconds: number) => number;
|
|
460
|
+
readonly _ticksToSeconds: (ticks: number) => number;
|
|
386
461
|
dispatchEvent(event: Event): boolean;
|
|
387
462
|
/** Re-extract peaks for a clip at new offset/duration from cached WaveformData. */
|
|
388
463
|
reextractClipPeaks(clipId: string, offsetSamples: number, durationSamples: number): ClipPeakSlice | null;
|
|
@@ -404,7 +479,6 @@ declare class ClipPointerHandler {
|
|
|
404
479
|
private _trackId;
|
|
405
480
|
private _startPx;
|
|
406
481
|
private _isDragging;
|
|
407
|
-
private _lastDeltaPx;
|
|
408
482
|
private _cumulativeDeltaSamples;
|
|
409
483
|
private _clipContainer;
|
|
410
484
|
private _boundaryEl;
|
|
@@ -412,7 +486,17 @@ declare class ClipPointerHandler {
|
|
|
412
486
|
private _originalWidth;
|
|
413
487
|
private _originalOffsetSamples;
|
|
414
488
|
private _originalDurationSamples;
|
|
489
|
+
private _originalStartSample;
|
|
415
490
|
constructor(host: ClipPointerHost);
|
|
491
|
+
/**
|
|
492
|
+
* Convert a pixel delta to samples, snapping in tick space when in beats mode.
|
|
493
|
+
*
|
|
494
|
+
* The anchor is the absolute sample position being moved (e.g., clip start
|
|
495
|
+
* for move/left-trim, clip end for right-trim). Snapping the absolute
|
|
496
|
+
* position — not just the delta — ensures clips land exactly on grid lines
|
|
497
|
+
* even if they started off-grid.
|
|
498
|
+
*/
|
|
499
|
+
private _snapDeltaToSamples;
|
|
416
500
|
/** Returns true if a drag interaction is currently in progress. */
|
|
417
501
|
get isActive(): boolean;
|
|
418
502
|
/**
|
|
@@ -550,6 +634,25 @@ declare class DawEditorElement extends LitElement {
|
|
|
550
634
|
clipHeaders: boolean;
|
|
551
635
|
clipHeaderHeight: number;
|
|
552
636
|
interactiveClips: boolean;
|
|
637
|
+
scaleMode: 'temporal' | 'beats';
|
|
638
|
+
get ticksPerPixel(): number;
|
|
639
|
+
set ticksPerPixel(value: number);
|
|
640
|
+
private _ticksPerPixel;
|
|
641
|
+
get bpm(): number;
|
|
642
|
+
set bpm(value: number);
|
|
643
|
+
private _bpm;
|
|
644
|
+
timeSignature: [number, number];
|
|
645
|
+
meterEntries?: MeterEntry[];
|
|
646
|
+
/** MeterEntries for grid/ruler: explicit meterEntries if set, otherwise derived from timeSignature. */
|
|
647
|
+
get _meterEntries(): MeterEntry[];
|
|
648
|
+
get ppqn(): number;
|
|
649
|
+
set ppqn(value: number);
|
|
650
|
+
private _ppqn;
|
|
651
|
+
snapTo: SnapTo;
|
|
652
|
+
/** Optional tempo-aware conversion: seconds → PPQN ticks. When provided, enables variable tempo. */
|
|
653
|
+
secondsToTicks?: (seconds: number) => number;
|
|
654
|
+
/** Optional tempo-aware conversion: PPQN ticks → seconds. Required alongside secondsToTicks. */
|
|
655
|
+
ticksToSeconds?: (ticks: number) => number;
|
|
553
656
|
/** Desired sample rate. Creates a cross-browser AudioContext at this rate.
|
|
554
657
|
* Pre-computed .dat peaks render instantly when they match. */
|
|
555
658
|
sampleRate: number;
|
|
@@ -572,6 +675,9 @@ declare class DawEditorElement extends LitElement {
|
|
|
572
675
|
set audioContext(ctx: AudioContext | null);
|
|
573
676
|
get audioContext(): AudioContext;
|
|
574
677
|
_engine: PlaylistEngine | null;
|
|
678
|
+
private _adapter;
|
|
679
|
+
private _warnedMissingTicksToSeconds;
|
|
680
|
+
private _warnedMissingSecondsToTicks;
|
|
575
681
|
private _enginePromise;
|
|
576
682
|
_audioCache: Map<string, Promise<AudioBuffer>>;
|
|
577
683
|
private _peaksCache;
|
|
@@ -591,6 +697,9 @@ declare class DawEditorElement extends LitElement {
|
|
|
591
697
|
private _clipPointer;
|
|
592
698
|
get _clipHandler(): ClipPointerHandler | null;
|
|
593
699
|
get engine(): PlaylistEngine | null;
|
|
700
|
+
/** The adapter's Transport — use for tempo, metronome, and effects. */
|
|
701
|
+
get transport(): Transport | null;
|
|
702
|
+
get renderSamplesPerPixel(): number;
|
|
594
703
|
/** Re-extract peaks for a clip at new offset/duration from cached WaveformData. */
|
|
595
704
|
reextractClipPeaks(clipId: string, offsetSamples: number, durationSamples: number): {
|
|
596
705
|
data: Peaks[];
|
|
@@ -601,7 +710,18 @@ declare class DawEditorElement extends LitElement {
|
|
|
601
710
|
static styles: lit.CSSResult[];
|
|
602
711
|
get effectiveSampleRate(): number;
|
|
603
712
|
resolveAudioContextSampleRate(rate: number): void;
|
|
713
|
+
/**
|
|
714
|
+
* In beats mode, derive samplesPerPixel from ticksPerPixel so that
|
|
715
|
+
* clip positions, waveforms, and the tick-space grid all align.
|
|
716
|
+
*/
|
|
717
|
+
private get _renderSpp();
|
|
718
|
+
/** Convert seconds to ticks — uses callback if provided, otherwise single-BPM fallback. */
|
|
719
|
+
_secondsToTicks(seconds: number): number;
|
|
720
|
+
/** Convert ticks to seconds — uses callback if provided, otherwise single-BPM fallback. */
|
|
721
|
+
_ticksToSeconds(ticks: number): number;
|
|
604
722
|
private get _totalWidth();
|
|
723
|
+
/** Grid height when no tracks exist — matches scroll area's rendered height. */
|
|
724
|
+
private get _emptyGridHeight();
|
|
605
725
|
_setSelectedTrackId(trackId: string | null): void;
|
|
606
726
|
get tracks(): TrackDescriptor[];
|
|
607
727
|
get selectedTrackId(): string | null;
|
|
@@ -673,7 +793,13 @@ declare class DawRulerElement extends LitElement {
|
|
|
673
793
|
sampleRate: number;
|
|
674
794
|
duration: number;
|
|
675
795
|
rulerHeight: number;
|
|
796
|
+
scaleMode: 'temporal' | 'beats';
|
|
797
|
+
ticksPerPixel: number;
|
|
798
|
+
meterEntries: MeterEntry[];
|
|
799
|
+
ppqn: number;
|
|
800
|
+
totalWidth: number;
|
|
676
801
|
private _tickData;
|
|
802
|
+
private _musicalTickData;
|
|
677
803
|
static styles: lit.CSSResult;
|
|
678
804
|
willUpdate(): void;
|
|
679
805
|
render(): lit.TemplateResult<1>;
|
|
@@ -827,4 +953,4 @@ interface SplitHost {
|
|
|
827
953
|
*/
|
|
828
954
|
declare function splitAtPlayhead(host: SplitHost): boolean;
|
|
829
955
|
|
|
830
|
-
export { AudioResumeController, type ClipDescriptor, type ClipEngineContract, ClipPointerHandler, type ClipPointerHost, DawClipElement, type DawClipMoveDetail, type DawClipSplitDetail, type DawClipTrimDetail, DawEditorElement, type DawErrorDetail, type DawEvent, type DawEventMap, type DawFilesLoadErrorDetail, DawKeyboardShortcutsElement, DawPauseButtonElement, DawPlayButtonElement, DawPlayheadElement, DawRecordButtonElement, type DawRecordingCompleteDetail, type DawRecordingErrorDetail, type DawRecordingStartDetail, DawRulerElement, type DawSeekDetail, type DawSelectionDetail, DawSelectionElement, DawStopButtonElement, type DawTrackConnectedDetail, type DawTrackControlDetail, DawTrackControlsElement, DawTrackElement, type DawTrackErrorDetail, type DawTrackIdDetail, type DawTrackRemoveDetail, type DawTrackSelectDetail, DawTransportButton, DawTransportElement, DawWaveformElement, type KeyBinding, type LoadFilesResult, type PlaybackShortcutMap, type PointerEngineContract, RecordingController, type RecordingOptions, type RecordingSession, type SplitEngineContract, type SplitHost, type SplittingShortcutMap, type TrackDescriptor, type UndoShortcutMap, splitAtPlayhead };
|
|
956
|
+
export { AudioResumeController, type ClipDescriptor, type ClipEngineContract, ClipPointerHandler, type ClipPointerHost, DawClipElement, type DawClipMoveDetail, type DawClipSplitDetail, type DawClipTrimDetail, DawEditorElement, type DawErrorDetail, type DawEvent, type DawEventMap, type DawFilesLoadErrorDetail, DawGridElement, DawKeyboardShortcutsElement, DawPauseButtonElement, DawPlayButtonElement, DawPlayheadElement, DawRecordButtonElement, type DawRecordingCompleteDetail, type DawRecordingErrorDetail, type DawRecordingStartDetail, DawRulerElement, type DawSeekDetail, type DawSelectionDetail, DawSelectionElement, DawStopButtonElement, type DawTrackConnectedDetail, type DawTrackControlDetail, DawTrackControlsElement, DawTrackElement, type DawTrackErrorDetail, type DawTrackIdDetail, type DawTrackRemoveDetail, type DawTrackSelectDetail, DawTransportButton, DawTransportElement, DawWaveformElement, type KeyBinding, type LoadFilesResult, type PlaybackShortcutMap, type PointerEngineContract, RecordingController, type RecordingOptions, type RecordingSession, type SplitEngineContract, type SplitHost, type SplittingShortcutMap, type TrackDescriptor, type UndoShortcutMap, type WaveformSegment, splitAtPlayhead };
|