wavegram 0.1.0 → 0.1.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/README.md CHANGED
@@ -2,18 +2,20 @@
2
2
 
3
3
  Lightweight Web Component for previewing audio with a synchronized waveform, spectrogram, and playback cursor. It is intended for research demos, paper companion pages, audio dataset previews, and source-separation result comparisons.
4
4
 
5
+ Wavegram aims to provide a minimal, academic, and scientific visualization surface rather than a general-purpose media player or audio editor.
6
+
5
7
  It is not an editor. It does not implement recording, effects, multitrack editing, annotation editing, ASR, or server-side processing.
6
8
 
7
9
  ## Design Focus
8
10
 
9
- Wavegram is closest in spirit to lightweight waveform players such as wavesurfer.js, but its primary view is not just a waveform. It always treats waveform and spectrogram as two synchronized views over the same audio timeline.
11
+ Wavegram is closest in spirit to lightweight waveform players, but its primary view is not just a waveform. It always treats waveform and spectrogram as two synchronized views over the same audio timeline.
10
12
 
11
13
  The core feature set is deliberately narrow:
12
14
 
13
15
  - Simultaneous waveform and spectrogram display.
14
16
  - One playback cursor rendered at the same time position in both views.
15
17
  - Click-to-seek from either waveform or spectrogram. By default, clicking a stopped player starts playback from that position, and clicking a playing player pauses after seeking.
16
- - Scientific, low-decoration presentation suitable for papers, demos, and dataset browsers.
18
+ - Minimal, low-decoration presentation suitable for academic papers, scientific demos, and dataset browsers.
17
19
  - No DAW-style editing, multitrack arrangement, effects, recording, or annotation workflow.
18
20
 
19
21
  ## Install
@@ -34,6 +36,8 @@ import "wavegram";
34
36
  ></wavegram-player>
35
37
  ```
36
38
 
39
+ ![Minimal wavegram-player example showing a waveform and spectrogram](docs/assets/minimal-example.png)
40
+
37
41
  The package is named `wavegram`. The custom element tag is `wavegram-player` because browser custom element names must contain a hyphen.
38
42
 
39
43
  The `src` value may be a relative URL such as `audio/example.wav` or an absolute URI such as the example above.
@@ -144,6 +148,12 @@ The older `<audio-preview-spectrogram>` tag is still registered as a compatibili
144
148
 
145
149
  The examples use WAV files from [`pdx-cs-sound/wavs`](https://github.com/pdx-cs-sound/wavs), a sample collection for Portland State University's Computers, Sound and Music course. The repository states that the files are Creative Commons CC0 unless otherwise indicated.
146
150
 
151
+ The 16 kHz keyword-spotting example uses a WAV file from [`fkuhne/KWS-Dataset`](https://github.com/fkuhne/KWS-Dataset). Its `wavs` directory is described by that project as WAV audio converted to 16 kHz and is distributed under CC0-1.0.
152
+
153
+ ## Acknowledgements
154
+
155
+ Wavegram is inspired by [`wavesurfer.js`](https://wavesurfer.xyz/), especially its lightweight browser-based waveform player model. Wavegram is an independent implementation focused on synchronized waveform and spectrogram previews for research demos and dataset browsing.
156
+
147
157
  ## Styling
148
158
 
149
159
  The component uses Shadow DOM and supports CSS custom properties:
@@ -182,16 +192,32 @@ npm run test:e2e
182
192
 
183
193
  ## Examples
184
194
 
185
- Run `npm run dev` and open:
195
+ Run the local dev server:
196
+
197
+ ```sh
198
+ npm run dev -- --port 4173
199
+ ```
186
200
 
187
- - `examples/basic.html`
188
- - `examples/multiple.html`
189
- - `examples/large-file.html`
190
- - `examples/profile.html`
191
- - `examples/multichannel.html`
192
- - `examples/waveform-only.html`
193
- - `examples/spectrogram-only.html`
194
- - `examples/styles.html`
201
+ Then open:
202
+
203
+ - `http://127.0.0.1:4173/examples/basic.html`
204
+ - `http://127.0.0.1:4173/examples/multiple.html`
205
+ - `http://127.0.0.1:4173/examples/large-file.html`
206
+ - `http://127.0.0.1:4173/examples/profile.html`
207
+ - `http://127.0.0.1:4173/examples/multichannel.html`
208
+ - `http://127.0.0.1:4173/examples/kws-16khz.html`
209
+ - `http://127.0.0.1:4173/examples/waveform-only.html`
210
+ - `http://127.0.0.1:4173/examples/spectrogram-only.html`
211
+ - `http://127.0.0.1:4173/examples/styles.html`
212
+
213
+ For automated local checks, run:
214
+
215
+ ```sh
216
+ npm run test
217
+ npm run typecheck
218
+ npm run build
219
+ npm run test:e2e
220
+ ```
195
221
 
196
222
  ## License
197
223
 
@@ -1 +1 @@
1
- (function(){"use strict";function g(t,o,n){return Math.min(n,Math.max(o,t))}const b=1e-10;function M(t){return Number.isInteger(t)&&t>0&&(t&t-1)===0}function x(t,o){const n=new Float32Array(t);if(t===1)return n[0]=1,n;for(let e=0;e<t;e+=1)o==="hann"?n[e]=.5-.5*Math.cos(2*Math.PI*e/(t-1)):o==="hamming"?n[e]=.54-.46*Math.cos(2*Math.PI*e/(t-1)):n[e]=1;return n}function S(t){let o=0;for(const n of t)o+=n;return o/t.length}function D(t){return 20*Math.log10(Math.abs(t)+b)}function I(t,o){const n=t.length;if(!M(n)||o.length!==n)throw new Error("FFT input length must be a radix-2 size.");for(let e=1,a=0;e<n;e+=1){let f=n>>1;for(;a&f;f>>=1)a^=f;if(a^=f,e<a){const h=t[e];t[e]=t[a],t[a]=h;const r=o[e];o[e]=o[a],o[a]=r}}for(let e=2;e<=n;e<<=1){const a=-2*Math.PI/e,f=Math.cos(a),h=Math.sin(a);for(let r=0;r<n;r+=e){let c=1,l=0;for(let s=0;s<e/2;s+=1){const d=t[r+s],p=o[r+s],m=t[r+s+e/2]*c-o[r+s+e/2]*l,u=t[r+s+e/2]*l+o[r+s+e/2]*c;t[r+s]=d+m,o[r+s]=p+u,t[r+s+e/2]=d-m,o[r+s+e/2]=p-u;const w=c*f-l*h;l=c*h+l*f,c=w}}}}function R(t,o,n){const{fftSize:e,hopSize:a,windowType:f,minDb:h,maxDb:r}=n;if(!M(e))throw new Error(`fftSize must be a power of two. Received ${e}.`);if(!Number.isInteger(a)||a<=0)throw new Error(`hopSize must be a positive integer. Received ${a}.`);if(r<=h)throw new Error("maxDb must be greater than minDb.");const c=e/2+1,l=Math.max(1,Math.floor(Math.max(0,t.length-e)/a)+1),s=new Float32Array(l*c),d=x(e,f),p=Math.max(b,e*S(d)/2),m=new Float32Array(e),u=new Float32Array(e);for(let w=0;w<l;w+=1){const y=w*a;m.fill(0),u.fill(0);for(let i=0;i<e;i+=1)m[i]=(t[y+i]??0)*d[i];I(m,u);for(let i=0;i<c;i+=1){const F=Math.hypot(m[i],u[i])/p;s[w*c+i]=g(D(F),h,r)}}return{values:s,freqBins:c,timeFrames:l,sampleRate:o,fftSize:e,hopSize:a,minDb:h,maxDb:r}}self.addEventListener("message",t=>{try{const o=R(t.data.samples,t.data.sampleRate,{fftSize:t.data.fftSize,hopSize:t.data.hopSize,windowType:t.data.windowType,minDb:t.data.minDb,maxDb:t.data.maxDb});self.postMessage(o,[o.values.buffer])}catch(o){self.postMessage({error:{message:o instanceof Error?o.message:"Failed to compute spectrogram."}})}})})();
1
+ (function(){"use strict";function g(t,o,n){return Math.min(n,Math.max(o,t))}const b=1e-10;function M(t){return Number.isInteger(t)&&t>0&&(t&t-1)===0}function x(t,o){const n=new Float32Array(t);if(t===1)return n[0]=1,n;for(let e=0;e<t;e+=1)o==="hann"?n[e]=.5-.5*Math.cos(2*Math.PI*e/(t-1)):o==="hamming"?n[e]=.54-.46*Math.cos(2*Math.PI*e/(t-1)):n[e]=1;return n}function S(t){let o=0;for(const n of t)o+=n;return o/t.length}function y(t){return 20*Math.log10(Math.abs(t)+b)}function D(t,o){const n=t.length;if(!M(n)||o.length!==n)throw new Error("FFT input length must be a radix-2 size.");for(let e=1,a=0;e<n;e+=1){let f=n>>1;for(;a&f;f>>=1)a^=f;if(a^=f,e<a){const h=t[e];t[e]=t[a],t[a]=h;const r=o[e];o[e]=o[a],o[a]=r}}for(let e=2;e<=n;e<<=1){const a=-2*Math.PI/e,f=Math.cos(a),h=Math.sin(a);for(let r=0;r<n;r+=e){let c=1,l=0;for(let s=0;s<e/2;s+=1){const d=t[r+s],p=o[r+s],m=t[r+s+e/2]*c-o[r+s+e/2]*l,u=t[r+s+e/2]*l+o[r+s+e/2]*c;t[r+s]=d+m,o[r+s]=p+u,t[r+s+e/2]=d-m,o[r+s+e/2]=p-u;const w=c*f-l*h;l=c*h+l*f,c=w}}}}function F(t,o,n){const{fftSize:e,hopSize:a,windowType:f,minDb:h,maxDb:r}=n;if(!M(e))throw new Error(`fftSize must be a power of two. Received ${e}.`);if(!Number.isInteger(a)||a<=0)throw new Error(`hopSize must be a positive integer. Received ${a}.`);if(r<=h)throw new Error("maxDb must be greater than minDb.");const c=e/2+1,l=Math.max(1,Math.floor(Math.max(0,t.length-e)/a)+1),s=new Float32Array(l*c),d=x(e,f),p=Math.max(b,e*S(d)/2),m=new Float32Array(e),u=new Float32Array(e);for(let w=0;w<l;w+=1){const I=w*a;m.fill(0),u.fill(0);for(let i=0;i<e;i+=1)m[i]=(t[I+i]??0)*d[i];D(m,u);for(let i=0;i<c;i+=1){const R=Math.hypot(m[i],u[i])/p;s[w*c+i]=g(y(R),h,r)}}return{values:s,freqBins:c,timeFrames:l,sampleRate:o,maxFrequencyHz:o/2,fftSize:e,hopSize:a,minDb:h,maxDb:r}}self.addEventListener("message",t=>{try{const o=F(t.data.samples,t.data.sampleRate,{fftSize:t.data.fftSize,hopSize:t.data.hopSize,windowType:t.data.windowType,minDb:t.data.minDb,maxDb:t.data.maxDb});self.postMessage(o,[o.values.buffer])}catch(o){self.postMessage({error:{message:o instanceof Error?o.message:"Failed to compute spectrogram."}})}})})();
@@ -1,2 +1,2 @@
1
- export declare function decodeAudioData(arrayBuffer: ArrayBuffer): Promise<AudioBuffer>;
1
+ export declare function decodeAudioData(arrayBuffer: ArrayBuffer, sampleRate?: number): Promise<AudioBuffer>;
2
2
  //# sourceMappingURL=decodeAudio.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decodeAudio.d.ts","sourceRoot":"","sources":["../../src/audio/decodeAudio.ts"],"names":[],"mappings":"AAOA,wBAAsB,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAGpF"}
1
+ {"version":3,"file":"decodeAudio.d.ts","sourceRoot":"","sources":["../../src/audio/decodeAudio.ts"],"names":[],"mappings":"AAYA,wBAAsB,eAAe,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAGzG"}
@@ -0,0 +1,2 @@
1
+ export declare function readAudioFileSampleRate(arrayBuffer: ArrayBuffer): number | undefined;
2
+ //# sourceMappingURL=readAudioSampleRate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readAudioSampleRate.d.ts","sourceRoot":"","sources":["../../src/audio/readAudioSampleRate.ts"],"names":[],"mappings":"AAAA,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAGpF"}
@@ -3,12 +3,14 @@ export declare class Wavegram extends HTMLElement {
3
3
  static observedAttributes: string[];
4
4
  private audio?;
5
5
  private audioBuffer?;
6
+ private sourceSampleRate?;
6
7
  private waveformPeaks?;
7
8
  private spectrogram?;
8
9
  private worker?;
9
10
  private resizeObserver?;
10
11
  private animationFrame;
11
12
  private loadingToken;
13
+ private waveformPeaksWidth;
12
14
  private blobUrl?;
13
15
  private playRequestedAt?;
14
16
  private readonly root;
@@ -73,6 +75,7 @@ export declare class Wavegram extends HTMLElement {
73
75
  private computeSpectrogramForCurrentBuffer;
74
76
  private computeSpectrogramInWorker;
75
77
  private bindAudio;
78
+ private handleResize;
76
79
  private layoutAndRender;
77
80
  private drawCursors;
78
81
  private clearCursor;
@@ -1 +1 @@
1
- {"version":3,"file":"Wavegram.d.ts","sourceRoot":"","sources":["../../src/component/Wavegram.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Wavegram.d.ts","sourceRoot":"","sources":["../../src/component/Wavegram.ts"],"names":[],"mappings":"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"}
package/dist/index.es.js CHANGED
@@ -1,115 +1,196 @@
1
- var D = Object.defineProperty;
2
- var N = (e, s, t) => s in e ? D(e, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[s] = t;
3
- var c = (e, s, t) => N(e, typeof s != "symbol" ? s + "" : s, t);
4
- let x;
5
- function q() {
6
- return x ?? (x = new AudioContext()), x;
1
+ var q = Object.defineProperty;
2
+ var I = (e, o, t) => o in e ? q(e, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[o] = t;
3
+ var c = (e, o, t) => I(e, typeof o != "symbol" ? o + "" : o, t);
4
+ let v, P;
5
+ function V(e) {
6
+ return (!v || P !== e) && (v == null || v.close(), v = new AudioContext(e ? { sampleRate: e } : void 0), P = e), v;
7
7
  }
8
- async function z(e) {
9
- return q().decodeAudioData(e.slice(0));
8
+ async function $(e, o) {
9
+ return V(o).decodeAudioData(e.slice(0));
10
10
  }
11
- async function I(e) {
12
- const s = await fetch(e);
13
- if (!s.ok)
14
- throw new Error(`Failed to load audio: ${s.status} ${s.statusText}`);
15
- return s.arrayBuffer();
11
+ async function j(e) {
12
+ const o = await fetch(e);
13
+ if (!o.ok)
14
+ throw new Error(`Failed to load audio: ${o.status} ${o.statusText}`);
15
+ return o.arrayBuffer();
16
16
  }
17
- function O(e, s) {
17
+ function Y(e, o) {
18
18
  const t = new Audio(e);
19
- return t.preload = "auto", t.autoplay = s, t.crossOrigin = "anonymous", t;
19
+ return t.preload = "auto", t.autoplay = o, t.crossOrigin = "anonymous", t;
20
20
  }
21
- function S(e, s, t) {
22
- return Math.min(t, Math.max(s, e));
21
+ function X(e) {
22
+ const o = new DataView(e);
23
+ return K(o) ?? G(o) ?? J(o) ?? _(o);
23
24
  }
24
- const H = 1e-10;
25
- function W(e) {
25
+ function K(e) {
26
+ if (e.byteLength < 28 || !A(e, 0, "RIFF") && !A(e, 0, "RF64") || !A(e, 8, "WAVE")) return;
27
+ let o = 12;
28
+ for (; o + 8 <= e.byteLength; ) {
29
+ const t = U(e, o, 4), r = e.getUint32(o + 4, !0), i = o + 8;
30
+ if (i + r > e.byteLength) return;
31
+ if (t === "fmt ") {
32
+ if (r < 8) return;
33
+ const s = e.getUint32(i + 4, !0);
34
+ return Number.isFinite(s) && s > 0 ? s : void 0;
35
+ }
36
+ o = i + r + r % 2;
37
+ }
38
+ }
39
+ function G(e) {
40
+ if (!A(e, 0, "fLaC")) return;
41
+ let o = 4;
42
+ for (; o + 4 <= e.byteLength; ) {
43
+ const r = e.getUint8(o) & 127, i = e.getUint8(o + 1) << 16 | e.getUint8(o + 2) << 8 | e.getUint8(o + 3), s = o + 4;
44
+ if (s + i > e.byteLength) return;
45
+ if (r === 0) {
46
+ if (i < 13) return;
47
+ const a = e.getUint8(s + 10) << 12 | e.getUint8(s + 11) << 4 | e.getUint8(s + 12) >> 4;
48
+ return a > 0 ? a : void 0;
49
+ }
50
+ o = s + i;
51
+ }
52
+ }
53
+ function J(e) {
54
+ const o = R(e, [1, 118, 111, 114, 98, 105, 115]);
55
+ if (o !== -1 && o + 16 <= e.byteLength) {
56
+ const r = e.getUint32(o + 12, !0);
57
+ return r > 0 ? r : void 0;
58
+ }
59
+ const t = R(e, [79, 112, 117, 115, 72, 101, 97, 100]);
60
+ if (t !== -1 && t + 16 <= e.byteLength) {
61
+ const r = e.getUint32(t + 12, !0);
62
+ return r > 0 ? r : 48e3;
63
+ }
64
+ }
65
+ function _(e) {
66
+ let o = 0;
67
+ A(e, 0, "ID3") && e.byteLength >= 10 && (o = 10 + Q(e, 6));
68
+ const t = [44100, 48e3, 32e3], r = [22050, 24e3, 16e3], i = [11025, 12e3, 8e3];
69
+ for (; o + 4 <= e.byteLength; o += 1) {
70
+ const s = e.getUint8(o), a = e.getUint8(o + 1);
71
+ if (s !== 255 || (a & 224) !== 224) continue;
72
+ const n = a >> 3 & 3, h = a >> 1 & 3, l = e.getUint8(o + 2) >> 2 & 3;
73
+ if (n === 1 || h === 0 || l === 3) continue;
74
+ return (n === 3 ? t : n === 2 ? r : i)[l];
75
+ }
76
+ }
77
+ function R(e, o) {
78
+ const t = e.byteLength - o.length;
79
+ for (let r = 0; r <= t; r += 1) {
80
+ let i = !0;
81
+ for (let s = 0; s < o.length; s += 1)
82
+ if (e.getUint8(r + s) !== o[s]) {
83
+ i = !1;
84
+ break;
85
+ }
86
+ if (i) return r;
87
+ }
88
+ return -1;
89
+ }
90
+ function Q(e, o) {
91
+ return e.getUint8(o) << 21 | e.getUint8(o + 1) << 14 | e.getUint8(o + 2) << 7 | e.getUint8(o + 3);
92
+ }
93
+ function A(e, o, t) {
94
+ return o + t.length > e.byteLength ? !1 : U(e, o, t.length) === t;
95
+ }
96
+ function U(e, o, t) {
97
+ let r = "";
98
+ for (let i = 0; i < t; i += 1)
99
+ r += String.fromCharCode(e.getUint8(o + i));
100
+ return r;
101
+ }
102
+ function M(e, o, t) {
103
+ return Math.min(t, Math.max(o, e));
104
+ }
105
+ const D = 1e-10;
106
+ function z(e) {
26
107
  return Number.isInteger(e) && e > 0 && (e & e - 1) === 0;
27
108
  }
28
- function U(e, s) {
109
+ function Z(e, o) {
29
110
  const t = new Float32Array(e);
30
111
  if (e === 1)
31
112
  return t[0] = 1, t;
32
113
  for (let r = 0; r < e; r += 1)
33
- s === "hann" ? t[r] = 0.5 - 0.5 * Math.cos(2 * Math.PI * r / (e - 1)) : s === "hamming" ? t[r] = 0.54 - 0.46 * Math.cos(2 * Math.PI * r / (e - 1)) : t[r] = 1;
114
+ o === "hann" ? t[r] = 0.5 - 0.5 * Math.cos(2 * Math.PI * r / (e - 1)) : o === "hamming" ? t[r] = 0.54 - 0.46 * Math.cos(2 * Math.PI * r / (e - 1)) : t[r] = 1;
34
115
  return t;
35
116
  }
36
- function V(e) {
37
- let s = 0;
117
+ function tt(e) {
118
+ let o = 0;
38
119
  for (const t of e)
39
- s += t;
40
- return s / e.length;
120
+ o += t;
121
+ return o / e.length;
41
122
  }
42
- function $(e) {
43
- return 20 * Math.log10(Math.abs(e) + H);
123
+ function et(e) {
124
+ return 20 * Math.log10(Math.abs(e) + D);
44
125
  }
45
- function j(e, s) {
126
+ function rt(e, o) {
46
127
  const t = e.length;
47
- if (!W(t) || s.length !== t)
128
+ if (!z(t) || o.length !== t)
48
129
  throw new Error("FFT input length must be a radix-2 size.");
49
130
  for (let r = 1, i = 0; r < t; r += 1) {
50
- let o = t >> 1;
51
- for (; i & o; o >>= 1)
52
- i ^= o;
53
- if (i ^= o, r < i) {
131
+ let s = t >> 1;
132
+ for (; i & s; s >>= 1)
133
+ i ^= s;
134
+ if (i ^= s, r < i) {
54
135
  const a = e[r];
55
136
  e[r] = e[i], e[i] = a;
56
- const n = s[r];
57
- s[r] = s[i], s[i] = n;
137
+ const n = o[r];
138
+ o[r] = o[i], o[i] = n;
58
139
  }
59
140
  }
60
141
  for (let r = 2; r <= t; r <<= 1) {
61
- const i = -2 * Math.PI / r, o = Math.cos(i), a = Math.sin(i);
142
+ const i = -2 * Math.PI / r, s = Math.cos(i), a = Math.sin(i);
62
143
  for (let n = 0; n < t; n += r) {
63
144
  let h = 1, l = 0;
64
145
  for (let u = 0; u < r / 2; u += 1) {
65
- const d = e[n + u], m = s[n + u], p = e[n + u + r / 2] * h - s[n + u + r / 2] * l, g = e[n + u + r / 2] * l + s[n + u + r / 2] * h;
66
- e[n + u] = d + p, s[n + u] = m + g, e[n + u + r / 2] = d - p, s[n + u + r / 2] = m - g;
67
- const b = h * o - l * a;
68
- l = h * a + l * o, h = b;
146
+ const d = e[n + u], m = o[n + u], g = e[n + u + r / 2] * h - o[n + u + r / 2] * l, p = e[n + u + r / 2] * l + o[n + u + r / 2] * h;
147
+ e[n + u] = d + g, o[n + u] = m + p, e[n + u + r / 2] = d - g, o[n + u + r / 2] = m - p;
148
+ const b = h * s - l * a;
149
+ l = h * a + l * s, h = b;
69
150
  }
70
151
  }
71
152
  }
72
153
  }
73
- function Y(e, s, t) {
74
- const { fftSize: r, hopSize: i, windowType: o, minDb: a, maxDb: n } = t;
75
- if (!W(r))
154
+ function ot(e, o, t) {
155
+ const { fftSize: r, hopSize: i, windowType: s, minDb: a, maxDb: n } = t;
156
+ if (!z(r))
76
157
  throw new Error(`fftSize must be a power of two. Received ${r}.`);
77
158
  if (!Number.isInteger(i) || i <= 0)
78
159
  throw new Error(`hopSize must be a positive integer. Received ${i}.`);
79
160
  if (n <= a)
80
161
  throw new Error("maxDb must be greater than minDb.");
81
- const h = r / 2 + 1, l = Math.max(1, Math.floor(Math.max(0, e.length - r) / i) + 1), u = new Float32Array(l * h), d = U(r, o), m = Math.max(H, r * V(d) / 2), p = new Float32Array(r), g = new Float32Array(r);
162
+ const h = r / 2 + 1, l = Math.max(1, Math.floor(Math.max(0, e.length - r) / i) + 1), u = new Float32Array(l * h), d = Z(r, s), m = Math.max(D, r * tt(d) / 2), g = new Float32Array(r), p = new Float32Array(r);
82
163
  for (let b = 0; b < l; b += 1) {
83
164
  const w = b * i;
84
- p.fill(0), g.fill(0);
165
+ g.fill(0), p.fill(0);
85
166
  for (let f = 0; f < r; f += 1)
86
- p[f] = (e[w + f] ?? 0) * d[f];
87
- j(p, g);
167
+ g[f] = (e[w + f] ?? 0) * d[f];
168
+ rt(g, p);
88
169
  for (let f = 0; f < h; f += 1) {
89
- const k = Math.hypot(p[f], g[f]) / m;
90
- u[b * h + f] = S($(k), a, n);
170
+ const x = Math.hypot(g[f], p[f]) / m;
171
+ u[b * h + f] = M(et(x), a, n);
91
172
  }
92
173
  }
93
- return { values: u, freqBins: h, timeFrames: l, sampleRate: s, fftSize: r, hopSize: i, minDb: a, maxDb: n };
174
+ return { values: u, freqBins: h, timeFrames: l, sampleRate: o, maxFrequencyHz: o / 2, fftSize: r, hopSize: i, minDb: a, maxDb: n };
94
175
  }
95
- function F(e, s) {
96
- if (s === "mix") {
176
+ function N(e, o) {
177
+ if (o === "mix") {
97
178
  const t = new Float32Array(e.length);
98
179
  for (let r = 0; r < e.numberOfChannels; r += 1) {
99
180
  const i = e.getChannelData(r);
100
- for (let o = 0; o < t.length; o += 1)
101
- t[o] += i[o] / e.numberOfChannels;
181
+ for (let s = 0; s < t.length; s += 1)
182
+ t[s] += i[s] / e.numberOfChannels;
102
183
  }
103
184
  return t;
104
185
  }
105
- if (!Number.isInteger(s) || s < 0 || s >= e.numberOfChannels)
106
- throw new Error(`Invalid channel ${s}. Audio has ${e.numberOfChannels} channel(s).`);
107
- return new Float32Array(e.getChannelData(s));
186
+ if (!Number.isInteger(o) || o < 0 || o >= e.numberOfChannels)
187
+ throw new Error(`Invalid channel ${o}. Audio has ${e.numberOfChannels} channel(s).`);
188
+ return new Float32Array(e.getChannelData(o));
108
189
  }
109
- function K(e, s) {
110
- const t = Math.max(1, Math.floor(s)), r = new Float32Array(t), i = new Float32Array(t), o = e.length / t;
190
+ function it(e, o) {
191
+ const t = Math.max(1, Math.floor(o)), r = new Float32Array(t), i = new Float32Array(t), s = e.length / t;
111
192
  for (let a = 0; a < t; a += 1) {
112
- const n = Math.floor(a * o), h = Math.max(n + 1, Math.floor((a + 1) * o));
193
+ const n = Math.floor(a * s), h = Math.max(n + 1, Math.floor((a + 1) * s));
113
194
  let l = 1, u = -1;
114
195
  for (let d = n; d < h && d < e.length; d += 1) {
115
196
  const m = e[d] ?? 0;
@@ -119,36 +200,38 @@ function K(e, s) {
119
200
  }
120
201
  return { min: r, max: i };
121
202
  }
122
- function E(e, s, t) {
123
- return K(F(e, t), s);
203
+ function E(e, o, t) {
204
+ return it(N(e, t), o);
124
205
  }
125
- function v(e, s, t) {
206
+ function y(e, o, t) {
126
207
  const r = window.devicePixelRatio || 1;
127
- e.style.width = "100%", e.style.height = `${t}px`, e.width = Math.max(1, Math.floor(s * r)), e.height = Math.max(1, Math.floor(t * r));
208
+ e.style.width = "100%", e.style.height = `${t}px`, e.width = Math.max(1, Math.floor(o * r)), e.height = Math.max(1, Math.floor(t * r));
128
209
  const i = e.getContext("2d");
129
210
  if (!i)
130
211
  throw new Error("Canvas 2D context is unavailable.");
131
212
  return i.setTransform(r, 0, 0, r, 0, 0), i;
132
213
  }
133
- function T(e, s, t, r, i = "rgba(0, 0, 0, 0.45)") {
214
+ function B(e, o, t, r, i = "rgba(0, 0, 0, 0.45)") {
134
215
  if (!Number.isFinite(t) || t <= 0) return;
135
- const o = e.getContext("2d");
136
- if (!o) return;
137
- const a = e.clientWidth, n = e.clientHeight, h = Math.max(0, Math.min(a, s / t * a));
138
- o.save(), o.strokeStyle = i, o.lineWidth = 2, o.beginPath(), o.moveTo(h, 0), o.lineTo(h, n), o.stroke(), o.strokeStyle = r, o.lineWidth = 1, o.beginPath(), o.moveTo(h, 0), o.lineTo(h, n), o.stroke(), o.restore();
216
+ const s = o / t;
217
+ if (!Number.isFinite(s) || s >= 1) return;
218
+ const a = e.getContext("2d");
219
+ if (!a) return;
220
+ const n = e.clientWidth, h = e.clientHeight, l = Math.max(0, Math.min(n, s * n));
221
+ a.save(), a.strokeStyle = i, a.lineWidth = 2, a.beginPath(), a.moveTo(l, 0), a.lineTo(l, h), a.stroke(), a.strokeStyle = r, a.lineWidth = 1, a.beginPath(), a.moveTo(l, 0), a.lineTo(l, h), a.stroke(), a.restore();
139
222
  }
140
- function A(e, s) {
141
- const t = S(s, 0, 1) * (e.length - 1), r = Math.floor(t), i = Math.min(r + 1, e.length - 1), o = t - r, a = e[r], n = e[i];
223
+ function k(e, o) {
224
+ const t = M(o, 0, 1) * (e.length - 1), r = Math.floor(t), i = Math.min(r + 1, e.length - 1), s = t - r, a = e[r], n = e[i];
142
225
  return [
143
- Math.round(a[0] + (n[0] - a[0]) * o),
144
- Math.round(a[1] + (n[1] - a[1]) * o),
145
- Math.round(a[2] + (n[2] - a[2]) * o)
226
+ Math.round(a[0] + (n[0] - a[0]) * s),
227
+ Math.round(a[1] + (n[1] - a[1]) * s),
228
+ Math.round(a[2] + (n[2] - a[2]) * s)
146
229
  ];
147
230
  }
148
- function G(e, s) {
149
- const t = S(s, 0, 1);
231
+ function st(e, o) {
232
+ const t = M(o, 0, 1);
150
233
  if (e === "audition")
151
- return A(
234
+ return k(
152
235
  [
153
236
  [0, 0, 0],
154
237
  [12, 7, 34],
@@ -165,7 +248,7 @@ function G(e, s) {
165
248
  const r = Math.round(t * 255);
166
249
  return [r, r, r];
167
250
  }
168
- return A(
251
+ return k(
169
252
  e === "viridis" ? [
170
253
  [68, 1, 84],
171
254
  [59, 82, 139],
@@ -188,127 +271,136 @@ function G(e, s) {
188
271
  t
189
272
  );
190
273
  }
191
- function X(e, s, t) {
274
+ function at(e, o, t) {
192
275
  const r = e.getContext("2d");
193
276
  if (!r) return;
194
- const i = e.clientWidth, o = e.clientHeight, a = Math.max(1, e.width), n = Math.max(1, e.height);
195
- if (r.clearRect(0, 0, i, o), r.fillStyle = t.background, r.fillRect(0, 0, i, o), !s) return;
196
- const h = r.createImageData(a, n), l = s.maxDb - s.minDb;
277
+ const i = e.clientWidth, s = e.clientHeight, a = Math.max(1, e.width), n = Math.max(1, e.height);
278
+ if (r.clearRect(0, 0, i, s), r.fillStyle = t.background, r.fillRect(0, 0, i, s), !o) return;
279
+ const h = r.createImageData(a, n), l = o.maxDb - o.minDb;
197
280
  for (let u = 0; u < h.width; u += 1) {
198
- const d = Math.min(s.timeFrames - 1, Math.floor(u / h.width * s.timeFrames));
281
+ const d = Math.min(o.timeFrames - 1, Math.floor(u / h.width * o.timeFrames));
199
282
  for (let m = 0; m < h.height; m += 1) {
200
- const p = Math.min(
201
- s.freqBins - 1,
202
- Math.floor((h.height - 1 - m) / h.height * s.freqBins)
203
- ), g = s.values[d * s.freqBins + p], b = S((g - s.minDb) / l, 0, 1), [w, f, k] = G(t.colorMap, b), y = (m * h.width + u) * 4;
204
- h.data[y] = w, h.data[y + 1] = f, h.data[y + 2] = k, h.data[y + 3] = 255;
283
+ const g = Math.min(
284
+ o.freqBins - 1,
285
+ Math.floor((h.height - 1 - m) / h.height * o.freqBins)
286
+ ), p = o.values[d * o.freqBins + g], b = M((p - o.minDb) / l, 0, 1), [w, f, x] = st(t.colorMap, b), S = (m * h.width + u) * 4;
287
+ h.data[S] = w, h.data[S + 1] = f, h.data[S + 2] = x, h.data[S + 3] = 255;
205
288
  }
206
289
  }
207
- r.putImageData(h, 0, 0), _(r, i, o, s.sampleRate, t.tickColor);
290
+ r.putImageData(h, 0, 0), ht(r, i, s, o.maxFrequencyHz, t.tickColor);
208
291
  }
209
- function J(e, s) {
292
+ function nt(e, o) {
210
293
  if (!Number.isFinite(e) || e <= 0) return 1e3;
211
- const t = Math.max(2, Math.min(6, Math.floor(s / 28))), r = e / t, i = 10 ** Math.floor(Math.log10(r)), o = r / i;
212
- return (o <= 1 ? 1 : o <= 2 ? 2 : o <= 7.5 ? 5 : 10) * i;
294
+ const t = Math.max(2, Math.min(6, Math.floor(o / 28))), r = e / t, i = 10 ** Math.floor(Math.log10(r)), s = r / i;
295
+ return (s <= 1 ? 1 : s <= 2 ? 2 : s <= 7.5 ? 5 : 10) * i;
213
296
  }
214
- function _(e, s, t, r, i = "rgba(255, 255, 255, 0.42)") {
215
- const o = r / 2, a = J(o, t), n = 5;
297
+ function ht(e, o, t, r, i = "rgba(255, 255, 255, 0.42)") {
298
+ const s = nt(r, t), a = 5;
216
299
  e.save(), e.strokeStyle = i, e.fillStyle = i, e.lineWidth = 1, e.font = "10px system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif", e.textAlign = "left", e.textBaseline = "middle";
217
- for (let h = a; h < o; h += a) {
218
- const l = t - h / o * t;
219
- e.beginPath(), e.moveTo(0, l + 0.5), e.lineTo(s, l + 0.5), e.stroke(), e.fillText(Q(h), n, l);
300
+ for (let n = s; n < r; n += s) {
301
+ const h = t - n / r * t;
302
+ e.beginPath(), e.moveTo(0, h + 0.5), e.lineTo(o, h + 0.5), e.stroke(), e.fillText(W(n), a, h);
220
303
  }
221
- e.restore();
304
+ e.beginPath(), e.moveTo(0, 0.5), e.lineTo(o, 0.5), e.stroke(), e.fillText(W(r), a, 8), e.restore();
222
305
  }
223
- function Q(e) {
306
+ function W(e) {
224
307
  if (e >= 1e3) {
225
- const s = e / 1e3;
226
- return `${Number.isInteger(s) ? s.toFixed(0) : s.toFixed(1)}k`;
308
+ const o = e / 1e3;
309
+ return `${Number.isInteger(o) ? o.toFixed(0) : o.toFixed(1)}k`;
227
310
  }
228
311
  return `${Math.round(e)}`;
229
312
  }
230
- function P(e, s, t) {
313
+ function L(e, o, t) {
231
314
  const r = e.getContext("2d");
232
315
  if (!r) return;
233
- const i = e.clientWidth, o = e.clientHeight;
234
- if (r.clearRect(0, 0, i, o), r.fillStyle = t.background, r.fillRect(0, 0, i, o), r.strokeStyle = t.centerColor ?? t.color, r.lineWidth = 1, !s) return;
235
- const a = t.style ?? "waveform", n = tt(s), h = et(a), l = Math.max(1, t.barWidth ?? h.barWidth), u = Math.max(0, t.barSpacing ?? h.barSpacing);
236
- a === "waveform" ? rt(r, s, o, {
316
+ const { width: i, height: s } = lt(e, r);
317
+ if (r.clearRect(0, 0, i, s), r.fillStyle = t.background, r.fillRect(0, 0, i, s), r.strokeStyle = t.centerColor ?? t.color, r.lineWidth = 1, !o) return;
318
+ const a = t.style ?? "waveform", n = ct(o), h = dt(a), l = Math.max(1, t.barWidth ?? h.barWidth), u = Math.max(0, t.barSpacing ?? h.barSpacing);
319
+ a === "waveform" ? mt(r, o, s, {
237
320
  unplayedColor: t.color,
238
321
  playedColor: t.playedColor ?? t.progressColor ?? t.color,
239
322
  centerColor: t.centerColor ?? t.color,
240
323
  progress: t.progress ?? 0
241
- }) : a === "lines" ? it(r, n, i, o, t.color) : a === "blocks" ? st(r, n, i, o, t.color, l, u) : a === "dots" ? at(r, n, i, o, t.color, l, u) : ot(r, n, i, o, t.color, l, u);
324
+ }) : a === "lines" ? gt(r, n, i, s, t.color) : a === "blocks" ? pt(r, n, i, s, t.color, l, u) : a === "dots" ? bt(r, n, i, s, t.color, l, u) : ft(r, n, i, s, t.color, l, u);
242
325
  }
243
- function Z(e, s) {
244
- return Math.max(Math.abs(e.min[s] ?? 0), Math.abs(e.max[s] ?? 0));
326
+ function lt(e, o) {
327
+ if (typeof o.getTransform != "function")
328
+ return { width: e.clientWidth, height: e.clientHeight };
329
+ const t = o.getTransform(), r = Math.abs(t.a) || 1, i = Math.abs(t.d) || 1;
330
+ return {
331
+ width: Math.max(e.clientWidth, e.width / r),
332
+ height: Math.max(e.clientHeight, e.height / i)
333
+ };
245
334
  }
246
- function tt(e) {
247
- const s = [];
335
+ function ut(e, o) {
336
+ return Math.max(Math.abs(e.min[o] ?? 0), Math.abs(e.max[o] ?? 0));
337
+ }
338
+ function ct(e) {
339
+ const o = [];
248
340
  for (let t = 0; t < e.max.length; t += 1)
249
- s.push(Z(e, t));
250
- return s;
341
+ o.push(ut(e, t));
342
+ return o;
251
343
  }
252
- function M(e, s) {
253
- if (e.length === s) return e;
254
- if (e.length === 0 || s <= 0) return [];
344
+ function C(e, o) {
345
+ if (e.length === o) return e;
346
+ if (e.length === 0 || o <= 0) return [];
255
347
  const t = [];
256
- if (s > e.length) {
257
- const r = (e.length - 1) / Math.max(1, s - 1);
258
- for (let i = 0; i < s; i += 1) {
259
- const o = i * r, a = Math.floor(o), n = Math.ceil(o), h = o - a;
348
+ if (o > e.length) {
349
+ const r = (e.length - 1) / Math.max(1, o - 1);
350
+ for (let i = 0; i < o; i += 1) {
351
+ const s = i * r, a = Math.floor(s), n = Math.ceil(s), h = s - a;
260
352
  n >= e.length ? t.push(e[e.length - 1] ?? 0) : a === n ? t.push(e[a] ?? 0) : t.push((e[a] ?? 0) * (1 - h) + (e[n] ?? 0) * h);
261
353
  }
262
354
  } else {
263
- const r = e.length / s;
264
- for (let i = 0; i < s; i += 1) {
265
- const o = Math.floor(i * r), a = Math.floor((i + 1) * r);
355
+ const r = e.length / o;
356
+ for (let i = 0; i < o; i += 1) {
357
+ const s = Math.floor(i * r), a = Math.floor((i + 1) * r);
266
358
  let n = 0, h = 0;
267
- for (let l = o; l <= a && l < e.length; l += 1)
359
+ for (let l = s; l <= a && l < e.length; l += 1)
268
360
  n = Math.max(n, e[l] ?? 0), h += 1;
269
361
  h === 0 && (n = e[Math.min(Math.round(i * r), e.length - 1)] ?? 0), t.push(n);
270
362
  }
271
363
  }
272
364
  return t;
273
365
  }
274
- function et(e) {
366
+ function dt(e) {
275
367
  return e === "bars" ? { barWidth: 3, barSpacing: 1 } : e === "blocks" ? { barWidth: 4, barSpacing: 2 } : e === "dots" ? { barWidth: 3, barSpacing: 3 } : { barWidth: 2, barSpacing: 0 };
276
368
  }
277
- function rt(e, s, t, r) {
369
+ function mt(e, o, t, r) {
278
370
  const i = t / 2;
279
- e.strokeStyle = r.centerColor, e.lineWidth = 1, e.beginPath(), e.moveTo(0, i), e.lineTo(s.max.length, i), e.stroke(), B(e, s, t, 0, s.min.length, r.unplayedColor);
280
- const o = Math.max(0, Math.min(s.min.length, Math.round(s.min.length * r.progress)));
281
- o > 0 && B(e, s, t, 0, o, r.playedColor);
371
+ e.strokeStyle = r.centerColor, e.lineWidth = 1, e.beginPath(), e.moveTo(0, i), e.lineTo(o.max.length, i), e.stroke(), H(e, o, t, 0, o.min.length, r.unplayedColor);
372
+ const s = Math.max(0, Math.min(o.min.length, Math.round(o.min.length * r.progress)));
373
+ s > 0 && H(e, o, t, 0, s, r.playedColor);
282
374
  }
283
- function B(e, s, t, r, i, o) {
375
+ function H(e, o, t, r, i, s) {
284
376
  const a = t / 2;
285
- e.strokeStyle = o, e.beginPath();
377
+ e.strokeStyle = s, e.beginPath();
286
378
  for (let n = r; n < i; n += 1) {
287
- const h = a - s.min[n] * a, l = a - s.max[n] * a;
379
+ const h = a - o.min[n] * a, l = a - o.max[n] * a;
288
380
  e.moveTo(n + 0.5, h), e.lineTo(n + 0.5, l);
289
381
  }
290
382
  e.stroke();
291
383
  }
292
- function ot(e, s, t, r, i, o, a) {
293
- const n = Math.floor(t / (o + a)), h = M(s, n);
384
+ function ft(e, o, t, r, i, s, a) {
385
+ const n = Math.floor(t / (s + a)), h = C(o, n);
294
386
  e.fillStyle = i;
295
387
  for (let l = 0; l < h.length; l += 1) {
296
- const u = l * (o + a);
297
- if (u + o > t) break;
388
+ const u = l * (s + a);
389
+ if (u + s > t) break;
298
390
  const d = h[l] * r * 0.9;
299
- e.fillRect(u, r - d, o, d);
391
+ e.fillRect(u, r - d, s, d);
300
392
  }
301
393
  }
302
- function it(e, s, t, r, i) {
303
- const o = r / 2, a = M(s, Math.max(2, Math.floor(t / 3)));
304
- e.strokeStyle = i, e.lineWidth = 2, e.lineCap = "round", e.lineJoin = "round", e.strokeStyle = "rgba(255, 255, 255, 0.03)", e.lineWidth = 0.5, e.beginPath(), e.moveTo(0, o), e.lineTo(t, o), e.stroke();
394
+ function gt(e, o, t, r, i) {
395
+ const s = r / 2, a = C(o, Math.max(2, Math.floor(t / 3)));
396
+ e.strokeStyle = i, e.lineWidth = 2, e.lineCap = "round", e.lineJoin = "round", e.strokeStyle = "rgba(255, 255, 255, 0.03)", e.lineWidth = 0.5, e.beginPath(), e.moveTo(0, s), e.lineTo(t, s), e.stroke();
305
397
  for (let h = 0; h <= 10; h += 1) {
306
398
  const l = t / 10 * h;
307
399
  e.beginPath(), e.moveTo(l, 0), e.lineTo(l, r), e.stroke();
308
400
  }
309
- e.strokeStyle = i, e.lineWidth = 2, e.beginPath(), e.moveTo(0, o);
401
+ e.strokeStyle = i, e.lineWidth = 2, e.beginPath(), e.moveTo(0, s);
310
402
  const n = a.map((h, l) => {
311
- const u = l / Math.max(1, a.length - 1) * t, d = o + Math.sin(l * 0.1) * h * r * 0.35;
403
+ const u = l / Math.max(1, a.length - 1) * t, d = s + Math.sin(l * 0.1) * h * r * 0.35;
312
404
  return { x: u, y: d };
313
405
  });
314
406
  for (let h = 0; h < n.length - 1; h += 1) {
@@ -317,37 +409,37 @@ function it(e, s, t, r, i) {
317
409
  }
318
410
  e.stroke();
319
411
  }
320
- function st(e, s, t, r, i, o, a) {
321
- const n = r / 2, h = Math.floor(t / (o + a)), l = M(s, h), u = 4, d = 2;
412
+ function pt(e, o, t, r, i, s, a) {
413
+ const n = r / 2, h = Math.floor(t / (s + a)), l = C(o, h), u = 4, d = 2;
322
414
  e.fillStyle = i;
323
415
  for (let m = 0; m < l.length; m += 1) {
324
- const p = m * (o + a);
325
- if (p + o > t) break;
326
- const g = l[m] * r * 0.9, b = Math.floor(g / (u + d));
416
+ const g = m * (s + a);
417
+ if (g + s > t) break;
418
+ const p = l[m] * r * 0.9, b = Math.floor(p / (u + d));
327
419
  for (let w = 0; w < b; w += 1) {
328
420
  const f = w * (u + d);
329
- e.fillRect(p, n - f - u, o, u), w > 0 && e.fillRect(p, n + f, o, u);
421
+ e.fillRect(g, n - f - u, s, u), w > 0 && e.fillRect(g, n + f, s, u);
330
422
  }
331
423
  }
332
424
  }
333
- function at(e, s, t, r, i, o, a) {
334
- const n = r / 2, h = Math.floor(t / (o + a)), l = M(s, h), u = Math.max(1.5, o / 2);
425
+ function bt(e, o, t, r, i, s, a) {
426
+ const n = r / 2, h = Math.floor(t / (s + a)), l = C(o, h), u = Math.max(1.5, s / 2);
335
427
  e.fillStyle = i;
336
428
  for (let d = 0; d < l.length; d += 1) {
337
- const m = d * (o + a) + o / 2;
429
+ const m = d * (s + a) + s / 2;
338
430
  if (m > t) break;
339
- const p = l[d] * r * 0.9;
340
- e.beginPath(), e.arc(m, n - p / 2, u, 0, Math.PI * 2), e.fill(), e.beginPath(), e.arc(m, n + p / 2, u, 0, Math.PI * 2), e.fill();
431
+ const g = l[d] * r * 0.9;
432
+ e.beginPath(), e.arc(m, n - g / 2, u, 0, Math.PI * 2), e.fill(), e.beginPath(), e.arc(m, n + g / 2, u, 0, Math.PI * 2), e.fill();
341
433
  }
342
434
  }
343
- function R(e) {
435
+ function F(e) {
344
436
  if (!Number.isFinite(e) || e < 0)
345
437
  return "00:00.000";
346
- const s = Math.floor(e * 1e3), t = s % 1e3, r = Math.floor(s / 1e3), i = r % 60, o = Math.floor(r / 60);
347
- return `${String(o).padStart(2, "0")}:${String(i).padStart(2, "0")}.${String(t).padStart(3, "0")}`;
438
+ const o = Math.floor(e * 1e3), t = o % 1e3, r = Math.floor(o / 1e3), i = r % 60, s = Math.floor(r / 60);
439
+ return `${String(s).padStart(2, "0")}:${String(i).padStart(2, "0")}.${String(t).padStart(3, "0")}`;
348
440
  }
349
- const L = document.createElement("template");
350
- L.innerHTML = `
441
+ const O = document.createElement("template");
442
+ O.innerHTML = `
351
443
  <style>
352
444
  :host {
353
445
  --ap-bg: #ffffff;
@@ -538,17 +630,19 @@ L.innerHTML = `
538
630
  </div>
539
631
  </div>
540
632
  `;
541
- class C extends HTMLElement {
633
+ class T extends HTMLElement {
542
634
  constructor() {
543
635
  super();
544
636
  c(this, "audio");
545
637
  c(this, "audioBuffer");
638
+ c(this, "sourceSampleRate");
546
639
  c(this, "waveformPeaks");
547
640
  c(this, "spectrogram");
548
641
  c(this, "worker");
549
642
  c(this, "resizeObserver");
550
643
  c(this, "animationFrame", 0);
551
644
  c(this, "loadingToken", 0);
645
+ c(this, "waveformPeaksWidth", 0);
552
646
  c(this, "blobUrl");
553
647
  c(this, "playRequestedAt");
554
648
  c(this, "root");
@@ -571,8 +665,8 @@ class C extends HTMLElement {
571
665
  });
572
666
  c(this, "handleSeekClick", (t) => {
573
667
  if (!this.audio || !Number.isFinite(this.duration) || this.duration <= 0) return;
574
- const i = t.currentTarget.getBoundingClientRect(), o = (t.clientX - i.left) / i.width;
575
- this.audio.currentTime = Math.max(0, Math.min(this.duration, o * this.duration)), this.updateTimeLabels(), this.drawCursors(), this.dispatchTypedEvent("seek"), this.audio.paused ? (this.playRequestedAt = performance.now(), this.audio.play().catch((a) => this.handleError("Audio playback failed.", a))) : this.audio.pause();
668
+ const i = t.currentTarget.getBoundingClientRect(), s = (t.clientX - i.left) / i.width;
669
+ this.audio.currentTime = Math.max(0, Math.min(this.duration, s * this.duration)), this.updateTimeLabels(), this.drawCursors(), this.dispatchTypedEvent("seek"), this.audio.paused ? (this.playRequestedAt = performance.now(), this.audio.play().catch((a) => this.handleError("Audio playback failed.", a))) : this.audio.pause();
576
670
  });
577
671
  c(this, "handleKeydown", (t) => {
578
672
  t.key !== " " && t.key !== "Enter" || (t.preventDefault(), this.handlePlayButton());
@@ -597,9 +691,9 @@ class C extends HTMLElement {
597
691
  });
598
692
  c(this, "updateTimeLabels", () => {
599
693
  var t;
600
- this.currentEl.textContent = R(((t = this.audio) == null ? void 0 : t.currentTime) ?? 0), this.durationEl.textContent = R(this.duration);
694
+ this.currentEl.textContent = F(((t = this.audio) == null ? void 0 : t.currentTime) ?? 0), this.durationEl.textContent = F(this.duration);
601
695
  });
602
- this.root = this.attachShadow({ mode: "open" }), this.root.append(L.content.cloneNode(!0)), this.button = this.requireElement("button"), this.button.dataset.state = "play", this.toolbar = this.requireElement(".toolbar"), this.timeEl = this.requireElement(".time"), this.currentEl = this.requireElement(".current"), this.durationEl = this.requireElement(".duration"), this.statusEl = this.requireElement(".status"), this.errorEl = this.requireElement(".error"), this.waveformPane = this.requireElement(".waveform-pane"), this.spectrogramPane = this.requireElement(".spectrogram-pane"), this.waveformCanvas = this.requireElement(".waveform"), this.spectrogramCanvas = this.requireElement(".spectrogram"), this.spectrogramOverlay = this.requireElement(".spectrogram-overlay"), this.waveformCursor = this.requireElement(".waveform-cursor"), this.spectrogramCursor = this.requireElement(".spectrogram-cursor");
696
+ this.root = this.attachShadow({ mode: "open" }), this.root.append(O.content.cloneNode(!0)), this.button = this.requireElement("button"), this.button.dataset.state = "play", this.toolbar = this.requireElement(".toolbar"), this.timeEl = this.requireElement(".time"), this.currentEl = this.requireElement(".current"), this.durationEl = this.requireElement(".duration"), this.statusEl = this.requireElement(".status"), this.errorEl = this.requireElement(".error"), this.waveformPane = this.requireElement(".waveform-pane"), this.spectrogramPane = this.requireElement(".spectrogram-pane"), this.waveformCanvas = this.requireElement(".waveform"), this.spectrogramCanvas = this.requireElement(".spectrogram"), this.spectrogramOverlay = this.requireElement(".spectrogram-overlay"), this.waveformCursor = this.requireElement(".waveform-cursor"), this.spectrogramCursor = this.requireElement(".spectrogram-cursor");
603
697
  }
604
698
  get src() {
605
699
  return this.getAttribute("src") ?? "";
@@ -722,7 +816,7 @@ class C extends HTMLElement {
722
816
  this.setAttribute("channel", String(t));
723
817
  }
724
818
  connectedCallback() {
725
- this.button.addEventListener("click", this.handlePlayButton), this.waveformPane.addEventListener("click", this.handleSeekClick), this.spectrogramPane.addEventListener("click", this.handleSeekClick), this.addEventListener("keydown", this.handleKeydown), this.tabIndex = this.tabIndex >= 0 ? this.tabIndex : 0, this.resizeObserver = new ResizeObserver(() => this.layoutAndRender()), this.resizeObserver.observe(this), this.layoutAndRender(), this.src && this.load();
819
+ this.button.addEventListener("click", this.handlePlayButton), this.waveformPane.addEventListener("click", this.handleSeekClick), this.spectrogramPane.addEventListener("click", this.handleSeekClick), this.addEventListener("keydown", this.handleKeydown), this.tabIndex = this.tabIndex >= 0 ? this.tabIndex : 0, this.resizeObserver = new ResizeObserver(() => this.handleResize()), this.resizeObserver.observe(this), this.layoutAndRender(), this.src && this.load();
726
820
  }
727
821
  disconnectedCallback() {
728
822
  var t, r, i;
@@ -742,23 +836,23 @@ class C extends HTMLElement {
742
836
  }
743
837
  }
744
838
  async load() {
745
- var i, o, a;
839
+ var i, s, a;
746
840
  const t = this.src, r = ++this.loadingToken;
747
- if (this.clearError(), this.setStatus(t ? "Loading" : ""), this.dispatchTypedEvent("loadstart"), this.button.disabled = !0, this.waveformPeaks = void 0, this.spectrogram = void 0, this.layoutAndRender(), (i = this.worker) == null || i.terminate(), (o = this.audio) == null || o.pause(), this.revokeBlobUrl(), !t) {
841
+ if (this.clearError(), this.setStatus(t ? "Loading" : ""), this.dispatchTypedEvent("loadstart"), this.button.disabled = !0, this.sourceSampleRate = void 0, this.waveformPeaks = void 0, this.waveformPeaksWidth = 0, this.spectrogram = void 0, this.layoutAndRender(), (i = this.worker) == null || i.terminate(), (s = this.audio) == null || s.pause(), this.revokeBlobUrl(), !t) {
748
842
  this.setStatus("");
749
843
  return;
750
844
  }
751
845
  try {
752
- const n = performance.now(), h = await I(t), l = performance.now();
846
+ const n = performance.now(), h = await j(t), l = performance.now();
753
847
  if (r !== this.loadingToken) return;
754
- this.blobUrl = URL.createObjectURL(new Blob([h])), this.audio = O(this.blobUrl, this.autoplay), this.bindAudio();
848
+ this.sourceSampleRate = X(h), this.blobUrl = URL.createObjectURL(new Blob([h])), this.audio = Y(this.blobUrl, this.autoplay), this.bindAudio();
755
849
  const u = this.waitForAudioReady(this.audio);
756
- this.audioBuffer = await z(h);
850
+ this.audioBuffer = await $(h, this.sourceSampleRate);
757
851
  const d = performance.now();
758
852
  if (r !== this.loadingToken) return;
759
- const m = Math.max(1, Math.floor(this.getCanvasWidth())), p = performance.now();
760
- this.waveformPeaks = this.showWaveform ? E(this.audioBuffer, m, this.channel) : void 0;
761
- const g = performance.now();
853
+ const m = Math.max(1, Math.floor(this.getCanvasWidth())), g = performance.now();
854
+ this.waveformPeaks = this.showWaveform ? E(this.audioBuffer, m, this.channel) : void 0, this.waveformPeaksWidth = this.waveformPeaks ? m : 0;
855
+ const p = performance.now();
762
856
  await u;
763
857
  const b = performance.now();
764
858
  if (r !== this.loadingToken) return;
@@ -767,7 +861,7 @@ class C extends HTMLElement {
767
861
  fetchMs: l - n,
768
862
  audioReadyMs: b - l,
769
863
  decodeMs: d - l,
770
- waveformMs: g - p,
864
+ waveformMs: p - g,
771
865
  firstUsableMs: w - n
772
866
  };
773
867
  this.dispatchEvent(new CustomEvent("profile", { detail: f })), this.layoutAndRender(), this.computeSpectrogramForCurrentBuffer(r, f, n), this.autoplay && await ((a = this.audio) == null ? void 0 : a.play());
@@ -779,7 +873,7 @@ class C extends HTMLElement {
779
873
  async recomputeAnalysis() {
780
874
  if (!this.audioBuffer) return;
781
875
  const t = Math.max(1, Math.floor(this.getCanvasWidth()));
782
- this.waveformPeaks = this.showWaveform ? E(this.audioBuffer, t, this.channel) : void 0, this.layoutAndRender(), this.showSpectrogram ? (this.setStatus("Analyzing"), this.spectrogram = await this.computeSpectrogramInWorker(), this.setStatus("")) : this.spectrogram = void 0, this.layoutAndRender();
876
+ this.waveformPeaks = this.showWaveform ? E(this.audioBuffer, t, this.channel) : void 0, this.waveformPeaksWidth = this.waveformPeaks ? t : 0, this.layoutAndRender(), this.showSpectrogram ? (this.setStatus("Analyzing"), this.spectrogram = await this.computeSpectrogramInWorker(), this.setStatus("")) : this.spectrogram = void 0, this.layoutAndRender();
783
877
  }
784
878
  async computeSpectrogramForCurrentBuffer(t, r, i) {
785
879
  if (!this.audioBuffer || !this.showSpectrogram) {
@@ -787,7 +881,7 @@ class C extends HTMLElement {
787
881
  return;
788
882
  }
789
883
  try {
790
- const o = performance.now();
884
+ const s = performance.now();
791
885
  this.spectrogram = await this.computeSpectrogramInWorker();
792
886
  const a = performance.now();
793
887
  if (t !== this.loadingToken) return;
@@ -795,18 +889,18 @@ class C extends HTMLElement {
795
889
  new CustomEvent("profile", {
796
890
  detail: {
797
891
  ...r,
798
- spectrogramMs: a - o,
892
+ spectrogramMs: a - s,
799
893
  totalMs: a - i
800
894
  }
801
895
  })
802
896
  );
803
- } catch (o) {
897
+ } catch (s) {
804
898
  if (t !== this.loadingToken) return;
805
899
  this.spectrogram = void 0, this.setStatus("Spectrogram unavailable"), this.dispatchEvent(
806
900
  new CustomEvent("error", {
807
901
  detail: {
808
- message: o instanceof Error ? o.message : "Failed to compute spectrogram.",
809
- cause: o
902
+ message: s instanceof Error ? s.message : "Failed to compute spectrogram.",
903
+ cause: s
810
904
  }
811
905
  })
812
906
  );
@@ -814,28 +908,28 @@ class C extends HTMLElement {
814
908
  }
815
909
  computeSpectrogramInWorker() {
816
910
  if (!this.audioBuffer) return Promise.resolve(void 0);
817
- const t = F(this.audioBuffer, this.channel), r = {
911
+ const t = N(this.audioBuffer, this.channel), r = {
818
912
  samples: t,
819
- sampleRate: this.audioBuffer.sampleRate,
913
+ sampleRate: this.sourceSampleRate ?? this.audioBuffer.sampleRate,
820
914
  fftSize: this.fftSize,
821
915
  hopSize: this.hopSize,
822
916
  windowType: this.windowType,
823
917
  minDb: this.minDb,
824
918
  maxDb: this.maxDb
825
919
  };
826
- return typeof Worker > "u" ? Promise.resolve(Y(t, this.audioBuffer.sampleRate, r)) : new Promise((i, o) => {
920
+ return typeof Worker > "u" ? Promise.resolve(ot(t, r.sampleRate, r)) : new Promise((i, s) => {
827
921
  var a;
828
922
  (a = this.worker) == null || a.terminate(), this.worker = new Worker(new URL(
829
923
  /* @vite-ignore */
830
- "/assets/spectrogram.worker-Burn7NUr.js",
924
+ "/assets/spectrogram.worker-CJxyA_5B.js",
831
925
  import.meta.url
832
926
  ), { type: "module" }), this.worker.addEventListener(
833
927
  "message",
834
928
  (n) => {
835
- "error" in n.data ? o(new Error(n.data.error.message)) : i(n.data);
929
+ "error" in n.data ? s(new Error(n.data.error.message)) : i(n.data);
836
930
  },
837
931
  { once: !0 }
838
- ), this.worker.addEventListener("error", () => o(new Error("Spectrogram worker failed.")), { once: !0 }), this.worker.postMessage(r, [r.samples.buffer]);
932
+ ), this.worker.addEventListener("error", () => s(new Error("Spectrogram worker failed.")), { once: !0 }), this.worker.postMessage(r, [r.samples.buffer]);
839
933
  });
840
934
  }
841
935
  bindAudio() {
@@ -844,9 +938,13 @@ class C extends HTMLElement {
844
938
  return this.handleError("Audio playback failed.", (t = this.audio) == null ? void 0 : t.error);
845
939
  }));
846
940
  }
941
+ handleResize() {
942
+ const t = Math.max(1, Math.floor(this.getCanvasWidth()));
943
+ this.audioBuffer && this.showWaveform && t !== this.waveformPeaksWidth ? (this.waveformPeaks = E(this.audioBuffer, t, this.channel), this.waveformPeaksWidth = t) : this.showWaveform || (this.waveformPeaksWidth = 0), this.layoutAndRender();
944
+ }
847
945
  layoutAndRender() {
848
946
  const t = Math.max(1, Math.floor(this.getCanvasWidth())), { waveformHeight: r, spectrogramHeight: i } = this.getPaneHeights();
849
- this.toolbar.classList.toggle("hidden", !this.showControls && !this.showTime), this.button.classList.toggle("hidden", !this.showControls), this.timeEl.classList.toggle("hidden", !this.showTime), this.waveformPane.classList.toggle("hidden", !this.showWaveform), this.spectrogramPane.classList.toggle("hidden", !this.showSpectrogram), this.showWaveform && (v(this.waveformCanvas, t, r), v(this.waveformCursor, t, r), P(this.waveformCanvas, this.waveformPeaks, {
947
+ this.toolbar.classList.toggle("hidden", !this.showControls && !this.showTime), this.button.classList.toggle("hidden", !this.showControls), this.timeEl.classList.toggle("hidden", !this.showTime), this.waveformPane.classList.toggle("hidden", !this.showWaveform), this.spectrogramPane.classList.toggle("hidden", !this.showSpectrogram), this.showWaveform && (y(this.waveformCanvas, t, r), y(this.waveformCursor, t, r), L(this.waveformCanvas, this.waveformPeaks, {
850
948
  color: this.cssVar("--ap-waveform", "rgba(0, 214, 163, 0.34)"),
851
949
  playedColor: this.cssVar("--ap-waveform-played", "#00f0b5"),
852
950
  centerColor: this.cssVar("--ap-waveform-center", "rgba(0, 92, 58, 0.7)"),
@@ -856,7 +954,7 @@ class C extends HTMLElement {
856
954
  barWidth: this.waveformBarWidth,
857
955
  barSpacing: this.waveformBarSpacing,
858
956
  progress: this.playbackProgress
859
- })), this.showSpectrogram && (v(this.spectrogramCanvas, t, i), v(this.spectrogramOverlay, t, i), v(this.spectrogramCursor, t, i), X(this.spectrogramCanvas, this.spectrogram, {
957
+ })), this.showSpectrogram && (y(this.spectrogramCanvas, t, i), y(this.spectrogramOverlay, t, i), y(this.spectrogramCursor, t, i), at(this.spectrogramCanvas, this.spectrogram, {
860
958
  colorMap: this.colorMap,
861
959
  background: this.cssVar("--ap-bg", "#ffffff"),
862
960
  tickColor: this.cssVar("--ap-spectrogram-tick", "rgba(255, 255, 255, 0.42)")
@@ -864,8 +962,8 @@ class C extends HTMLElement {
864
962
  }
865
963
  drawCursors() {
866
964
  var a;
867
- const t = ((a = this.audio) == null ? void 0 : a.currentTime) ?? 0, r = this.duration, i = this.cssVar("--ap-cursor", "#ff0000"), o = this.cssVar("--ap-cursor-shadow", "rgba(0, 0, 0, 0.45)");
868
- this.showWaveform && this.waveformStyle === "waveform" && P(this.waveformCanvas, this.waveformPeaks, {
965
+ const t = ((a = this.audio) == null ? void 0 : a.currentTime) ?? 0, r = this.duration, i = this.cssVar("--ap-cursor", "#ff0000"), s = this.cssVar("--ap-cursor-shadow", "rgba(0, 0, 0, 0.45)");
966
+ this.showWaveform && this.waveformStyle === "waveform" && L(this.waveformCanvas, this.waveformPeaks, {
869
967
  color: this.cssVar("--ap-waveform", "rgba(0, 214, 163, 0.34)"),
870
968
  playedColor: this.cssVar("--ap-waveform-played", "#00f0b5"),
871
969
  centerColor: this.cssVar("--ap-waveform-center", "rgba(0, 92, 58, 0.7)"),
@@ -875,19 +973,21 @@ class C extends HTMLElement {
875
973
  barWidth: this.waveformBarWidth,
876
974
  barSpacing: this.waveformBarSpacing,
877
975
  progress: this.playbackProgress
878
- }), this.drawSpectrogramOverlay(), this.clearCursor(this.waveformCursor), this.clearCursor(this.spectrogramCursor), this.showWaveform && T(this.waveformCursor, t, r, i, o), this.showSpectrogram && T(this.spectrogramCursor, t, r, i, o);
976
+ }), this.drawSpectrogramOverlay(), this.clearCursor(this.waveformCursor), this.clearCursor(this.spectrogramCursor), this.showWaveform && B(this.waveformCursor, t, r, i, s), this.showSpectrogram && B(this.spectrogramCursor, t, r, i, s);
879
977
  }
880
978
  clearCursor(t) {
881
979
  const r = t.getContext("2d");
882
- r == null || r.clearRect(0, 0, t.clientWidth, t.clientHeight);
980
+ if (!r) return;
981
+ const i = typeof r.getTransform == "function" ? r.getTransform() : void 0, s = Math.abs((i == null ? void 0 : i.a) ?? 1) || 1, a = Math.abs((i == null ? void 0 : i.d) ?? 1) || 1, n = Math.max(t.clientWidth, t.width / s), h = Math.max(t.clientHeight, t.height / a);
982
+ r.clearRect(0, 0, n, h);
883
983
  }
884
984
  drawSpectrogramOverlay() {
885
985
  const t = this.spectrogramOverlay.getContext("2d");
886
986
  if (!t) return;
887
987
  const r = this.spectrogramOverlay.clientWidth, i = this.spectrogramOverlay.clientHeight;
888
988
  if (t.clearRect(0, 0, r, i), !this.showSpectrogram || !this.spectrogram) return;
889
- const o = r * this.playbackProgress, a = 1 - this.cssNumberVar("--ap-spectrogram-unplayed-opacity", 0.48);
890
- o < r && (t.fillStyle = `rgba(0, 0, 0, ${Math.max(0, Math.min(1, a))})`, t.fillRect(o, 0, r - o, i));
989
+ const s = r * this.playbackProgress, a = 1 - this.cssNumberVar("--ap-spectrogram-unplayed-opacity", 0.48);
990
+ s < r && (t.fillStyle = `rgba(0, 0, 0, ${Math.max(0, Math.min(1, a))})`, t.fillRect(s, 0, r - s, i));
891
991
  }
892
992
  startAnimation() {
893
993
  this.stopAnimation();
@@ -942,10 +1042,10 @@ class C extends HTMLElement {
942
1042
  waveformHeight: this.showWaveform ? this.waveformHeight : 0,
943
1043
  spectrogramHeight: this.showSpectrogram ? this.spectrogramHeight : 0
944
1044
  };
945
- const o = this.height;
946
- return this.showWaveform && !this.showSpectrogram ? { waveformHeight: r ? this.waveformHeight : o, spectrogramHeight: 0 } : !this.showWaveform && this.showSpectrogram ? { waveformHeight: 0, spectrogramHeight: i ? this.spectrogramHeight : o } : r && i ? { waveformHeight: this.waveformHeight, spectrogramHeight: this.spectrogramHeight } : r ? { waveformHeight: this.waveformHeight, spectrogramHeight: Math.max(1, o - this.waveformHeight) } : i ? { waveformHeight: Math.max(1, o - this.spectrogramHeight), spectrogramHeight: this.spectrogramHeight } : {
947
- waveformHeight: Math.max(1, Math.round(o * (80 / 200))),
948
- spectrogramHeight: Math.max(1, o - Math.round(o * (80 / 200)))
1045
+ const s = this.height;
1046
+ return this.showWaveform && !this.showSpectrogram ? { waveformHeight: r ? this.waveformHeight : s, spectrogramHeight: 0 } : !this.showWaveform && this.showSpectrogram ? { waveformHeight: 0, spectrogramHeight: i ? this.spectrogramHeight : s } : r && i ? { waveformHeight: this.waveformHeight, spectrogramHeight: this.spectrogramHeight } : r ? { waveformHeight: this.waveformHeight, spectrogramHeight: Math.max(1, s - this.waveformHeight) } : i ? { waveformHeight: Math.max(1, s - this.spectrogramHeight), spectrogramHeight: this.spectrogramHeight } : {
1047
+ waveformHeight: Math.max(1, Math.round(s * (80 / 200))),
1048
+ spectrogramHeight: Math.max(1, s - Math.round(s * (80 / 200)))
949
1049
  };
950
1050
  }
951
1051
  getNumberAttribute(t, r) {
@@ -979,12 +1079,12 @@ class C extends HTMLElement {
979
1079
  }
980
1080
  waitForAudioReady(t) {
981
1081
  return t.readyState >= HTMLMediaElement.HAVE_METADATA ? Promise.resolve() : new Promise((r, i) => {
982
- const o = () => {
1082
+ const s = () => {
983
1083
  t.removeEventListener("loadedmetadata", a), t.removeEventListener("error", n);
984
1084
  }, a = () => {
985
- o(), r();
1085
+ s(), r();
986
1086
  }, n = () => {
987
- o(), i(t.error ?? new Error("Audio metadata failed to load."));
1087
+ s(), i(t.error ?? new Error("Audio metadata failed to load."));
988
1088
  };
989
1089
  t.addEventListener("loadedmetadata", a, { once: !0 }), t.addEventListener("error", n, { once: !0 }), t.load();
990
1090
  });
@@ -993,7 +1093,7 @@ class C extends HTMLElement {
993
1093
  this.blobUrl && (URL.revokeObjectURL(this.blobUrl), this.blobUrl = void 0);
994
1094
  }
995
1095
  }
996
- c(C, "observedAttributes", [
1096
+ c(T, "observedAttributes", [
997
1097
  "src",
998
1098
  "height",
999
1099
  "waveform-height",
@@ -1014,11 +1114,11 @@ c(C, "observedAttributes", [
1014
1114
  "color-map",
1015
1115
  "channel"
1016
1116
  ]);
1017
- class nt extends C {
1117
+ class wt extends T {
1018
1118
  }
1019
- customElements.get("wavegram-player") || customElements.define("wavegram-player", C);
1020
- customElements.get("audio-preview-spectrogram") || customElements.define("audio-preview-spectrogram", nt);
1119
+ customElements.get("wavegram-player") || customElements.define("wavegram-player", T);
1120
+ customElements.get("audio-preview-spectrogram") || customElements.define("audio-preview-spectrogram", wt);
1021
1121
  export {
1022
- nt as AudioPreviewSpectrogram,
1023
- C as Wavegram
1122
+ wt as AudioPreviewSpectrogram,
1123
+ T as Wavegram
1024
1124
  };
package/dist/index.umd.js CHANGED
@@ -1,4 +1,4 @@
1
- (function(b,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(b=typeof globalThis<"u"?globalThis:b||self,g(b.Wavegram={}))})(this,(function(b){"use strict";var ht=Object.defineProperty;var lt=(b,g,A)=>g in b?ht(b,g,{enumerable:!0,configurable:!0,writable:!0,value:A}):b[g]=A;var c=(b,g,A)=>lt(b,typeof g!="symbol"?g+"":g,A);var g=typeof document<"u"?document.currentScript:null;let A;function z(){return A??(A=new AudioContext),A}async function I(e){return z().decodeAudioData(e.slice(0))}async function O(e){const s=await fetch(e);if(!s.ok)throw new Error(`Failed to load audio: ${s.status} ${s.statusText}`);return s.arrayBuffer()}function U(e,s){const t=new Audio(e);return t.preload="auto",t.autoplay=s,t.crossOrigin="anonymous",t}function M(e,s,t){return Math.min(t,Math.max(s,e))}const P=1e-10;function R(e){return Number.isInteger(e)&&e>0&&(e&e-1)===0}function V(e,s){const t=new Float32Array(e);if(e===1)return t[0]=1,t;for(let r=0;r<e;r+=1)s==="hann"?t[r]=.5-.5*Math.cos(2*Math.PI*r/(e-1)):s==="hamming"?t[r]=.54-.46*Math.cos(2*Math.PI*r/(e-1)):t[r]=1;return t}function $(e){let s=0;for(const t of e)s+=t;return s/e.length}function j(e){return 20*Math.log10(Math.abs(e)+P)}function Y(e,s){const t=e.length;if(!R(t)||s.length!==t)throw new Error("FFT input length must be a radix-2 size.");for(let r=1,i=0;r<t;r+=1){let o=t>>1;for(;i&o;o>>=1)i^=o;if(i^=o,r<i){const a=e[r];e[r]=e[i],e[i]=a;const n=s[r];s[r]=s[i],s[i]=n}}for(let r=2;r<=t;r<<=1){const i=-2*Math.PI/r,o=Math.cos(i),a=Math.sin(i);for(let n=0;n<t;n+=r){let h=1,l=0;for(let u=0;u<r/2;u+=1){const d=e[n+u],m=s[n+u],p=e[n+u+r/2]*h-s[n+u+r/2]*l,w=e[n+u+r/2]*l+s[n+u+r/2]*h;e[n+u]=d+p,s[n+u]=m+w,e[n+u+r/2]=d-p,s[n+u+r/2]=m-w;const v=h*o-l*a;l=h*a+l*o,h=v}}}}function _(e,s,t){const{fftSize:r,hopSize:i,windowType:o,minDb:a,maxDb:n}=t;if(!R(r))throw new Error(`fftSize must be a power of two. Received ${r}.`);if(!Number.isInteger(i)||i<=0)throw new Error(`hopSize must be a positive integer. Received ${i}.`);if(n<=a)throw new Error("maxDb must be greater than minDb.");const h=r/2+1,l=Math.max(1,Math.floor(Math.max(0,e.length-r)/i)+1),u=new Float32Array(l*h),d=V(r,o),m=Math.max(P,r*$(d)/2),p=new Float32Array(r),w=new Float32Array(r);for(let v=0;v<l;v+=1){const y=v*i;p.fill(0),w.fill(0);for(let f=0;f<r;f+=1)p[f]=(e[y+f]??0)*d[f];Y(p,w);for(let f=0;f<h;f+=1){const T=Math.hypot(p[f],w[f])/m;u[v*h+f]=M(j(T),a,n)}}return{values:u,freqBins:h,timeFrames:l,sampleRate:s,fftSize:r,hopSize:i,minDb:a,maxDb:n}}function B(e,s){if(s==="mix"){const t=new Float32Array(e.length);for(let r=0;r<e.numberOfChannels;r+=1){const i=e.getChannelData(r);for(let o=0;o<t.length;o+=1)t[o]+=i[o]/e.numberOfChannels}return t}if(!Number.isInteger(s)||s<0||s>=e.numberOfChannels)throw new Error(`Invalid channel ${s}. Audio has ${e.numberOfChannels} channel(s).`);return new Float32Array(e.getChannelData(s))}function K(e,s){const t=Math.max(1,Math.floor(s)),r=new Float32Array(t),i=new Float32Array(t),o=e.length/t;for(let a=0;a<t;a+=1){const n=Math.floor(a*o),h=Math.max(n+1,Math.floor((a+1)*o));let l=1,u=-1;for(let d=n;d<h&&d<e.length;d+=1){const m=e[d]??0;m<l&&(l=m),m>u&&(u=m)}r[a]=l===1?0:l,i[a]=u===-1?0:u}return{min:r,max:i}}function H(e,s,t){return K(B(e,t),s)}function S(e,s,t){const r=window.devicePixelRatio||1;e.style.width="100%",e.style.height=`${t}px`,e.width=Math.max(1,Math.floor(s*r)),e.height=Math.max(1,Math.floor(t*r));const i=e.getContext("2d");if(!i)throw new Error("Canvas 2D context is unavailable.");return i.setTransform(r,0,0,r,0,0),i}function W(e,s,t,r,i="rgba(0, 0, 0, 0.45)"){if(!Number.isFinite(t)||t<=0)return;const o=e.getContext("2d");if(!o)return;const a=e.clientWidth,n=e.clientHeight,h=Math.max(0,Math.min(a,s/t*a));o.save(),o.strokeStyle=i,o.lineWidth=2,o.beginPath(),o.moveTo(h,0),o.lineTo(h,n),o.stroke(),o.strokeStyle=r,o.lineWidth=1,o.beginPath(),o.moveTo(h,0),o.lineTo(h,n),o.stroke(),o.restore()}function k(e,s){const t=M(s,0,1)*(e.length-1),r=Math.floor(t),i=Math.min(r+1,e.length-1),o=t-r,a=e[r],n=e[i];return[Math.round(a[0]+(n[0]-a[0])*o),Math.round(a[1]+(n[1]-a[1])*o),Math.round(a[2]+(n[2]-a[2])*o)]}function G(e,s){const t=M(s,0,1);if(e==="audition")return k([[0,0,0],[12,7,34],[25,37,114],[18,104,174],[39,178,172],[244,180,43],[252,76,27],[255,238,117]],t);if(e==="gray"){const r=Math.round(t*255);return[r,r,r]}return k(e==="viridis"?[[68,1,84],[59,82,139],[33,145,140],[94,201,98],[253,231,37]]:e==="inferno"?[[0,0,4],[87,15,109],[187,55,84],[249,142,8],[252,255,164]]:[[0,0,4],[73,16,105],[182,54,121],[251,136,97],[252,253,191]],t)}function X(e,s,t){const r=e.getContext("2d");if(!r)return;const i=e.clientWidth,o=e.clientHeight,a=Math.max(1,e.width),n=Math.max(1,e.height);if(r.clearRect(0,0,i,o),r.fillStyle=t.background,r.fillRect(0,0,i,o),!s)return;const h=r.createImageData(a,n),l=s.maxDb-s.minDb;for(let u=0;u<h.width;u+=1){const d=Math.min(s.timeFrames-1,Math.floor(u/h.width*s.timeFrames));for(let m=0;m<h.height;m+=1){const p=Math.min(s.freqBins-1,Math.floor((h.height-1-m)/h.height*s.freqBins)),w=s.values[d*s.freqBins+p],v=M((w-s.minDb)/l,0,1),[y,f,T]=G(t.colorMap,v),E=(m*h.width+u)*4;h.data[E]=y,h.data[E+1]=f,h.data[E+2]=T,h.data[E+3]=255}}r.putImageData(h,0,0),Q(r,i,o,s.sampleRate,t.tickColor)}function J(e,s){if(!Number.isFinite(e)||e<=0)return 1e3;const t=Math.max(2,Math.min(6,Math.floor(s/28))),r=e/t,i=10**Math.floor(Math.log10(r)),o=r/i;return(o<=1?1:o<=2?2:o<=7.5?5:10)*i}function Q(e,s,t,r,i="rgba(255, 255, 255, 0.42)"){const o=r/2,a=J(o,t),n=5;e.save(),e.strokeStyle=i,e.fillStyle=i,e.lineWidth=1,e.font="10px system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif",e.textAlign="left",e.textBaseline="middle";for(let h=a;h<o;h+=a){const l=t-h/o*t;e.beginPath(),e.moveTo(0,l+.5),e.lineTo(s,l+.5),e.stroke(),e.fillText(Z(h),n,l)}e.restore()}function Z(e){if(e>=1e3){const s=e/1e3;return`${Number.isInteger(s)?s.toFixed(0):s.toFixed(1)}k`}return`${Math.round(e)}`}function F(e,s,t){const r=e.getContext("2d");if(!r)return;const i=e.clientWidth,o=e.clientHeight;if(r.clearRect(0,0,i,o),r.fillStyle=t.background,r.fillRect(0,0,i,o),r.strokeStyle=t.centerColor??t.color,r.lineWidth=1,!s)return;const a=t.style??"waveform",n=et(s),h=rt(a),l=Math.max(1,t.barWidth??h.barWidth),u=Math.max(0,t.barSpacing??h.barSpacing);a==="waveform"?ot(r,s,o,{unplayedColor:t.color,playedColor:t.playedColor??t.progressColor??t.color,centerColor:t.centerColor??t.color,progress:t.progress??0}):a==="lines"?st(r,n,i,o,t.color):a==="blocks"?at(r,n,i,o,t.color,l,u):a==="dots"?nt(r,n,i,o,t.color,l,u):it(r,n,i,o,t.color,l,u)}function tt(e,s){return Math.max(Math.abs(e.min[s]??0),Math.abs(e.max[s]??0))}function et(e){const s=[];for(let t=0;t<e.max.length;t+=1)s.push(tt(e,t));return s}function C(e,s){if(e.length===s)return e;if(e.length===0||s<=0)return[];const t=[];if(s>e.length){const r=(e.length-1)/Math.max(1,s-1);for(let i=0;i<s;i+=1){const o=i*r,a=Math.floor(o),n=Math.ceil(o),h=o-a;n>=e.length?t.push(e[e.length-1]??0):a===n?t.push(e[a]??0):t.push((e[a]??0)*(1-h)+(e[n]??0)*h)}}else{const r=e.length/s;for(let i=0;i<s;i+=1){const o=Math.floor(i*r),a=Math.floor((i+1)*r);let n=0,h=0;for(let l=o;l<=a&&l<e.length;l+=1)n=Math.max(n,e[l]??0),h+=1;h===0&&(n=e[Math.min(Math.round(i*r),e.length-1)]??0),t.push(n)}}return t}function rt(e){return e==="bars"?{barWidth:3,barSpacing:1}:e==="blocks"?{barWidth:4,barSpacing:2}:e==="dots"?{barWidth:3,barSpacing:3}:{barWidth:2,barSpacing:0}}function ot(e,s,t,r){const i=t/2;e.strokeStyle=r.centerColor,e.lineWidth=1,e.beginPath(),e.moveTo(0,i),e.lineTo(s.max.length,i),e.stroke(),L(e,s,t,0,s.min.length,r.unplayedColor);const o=Math.max(0,Math.min(s.min.length,Math.round(s.min.length*r.progress)));o>0&&L(e,s,t,0,o,r.playedColor)}function L(e,s,t,r,i,o){const a=t/2;e.strokeStyle=o,e.beginPath();for(let n=r;n<i;n+=1){const h=a-s.min[n]*a,l=a-s.max[n]*a;e.moveTo(n+.5,h),e.lineTo(n+.5,l)}e.stroke()}function it(e,s,t,r,i,o,a){const n=Math.floor(t/(o+a)),h=C(s,n);e.fillStyle=i;for(let l=0;l<h.length;l+=1){const u=l*(o+a);if(u+o>t)break;const d=h[l]*r*.9;e.fillRect(u,r-d,o,d)}}function st(e,s,t,r,i){const o=r/2,a=C(s,Math.max(2,Math.floor(t/3)));e.strokeStyle=i,e.lineWidth=2,e.lineCap="round",e.lineJoin="round",e.strokeStyle="rgba(255, 255, 255, 0.03)",e.lineWidth=.5,e.beginPath(),e.moveTo(0,o),e.lineTo(t,o),e.stroke();for(let h=0;h<=10;h+=1){const l=t/10*h;e.beginPath(),e.moveTo(l,0),e.lineTo(l,r),e.stroke()}e.strokeStyle=i,e.lineWidth=2,e.beginPath(),e.moveTo(0,o);const n=a.map((h,l)=>{const u=l/Math.max(1,a.length-1)*t,d=o+Math.sin(l*.1)*h*r*.35;return{x:u,y:d}});for(let h=0;h<n.length-1;h+=1){const l=n[h],u=n[h+1],d=l.x+(u.x-l.x)*.5,m=u.x-(u.x-l.x)*.5;e.bezierCurveTo(d,l.y,m,u.y,u.x,u.y)}e.stroke()}function at(e,s,t,r,i,o,a){const n=r/2,h=Math.floor(t/(o+a)),l=C(s,h),u=4,d=2;e.fillStyle=i;for(let m=0;m<l.length;m+=1){const p=m*(o+a);if(p+o>t)break;const w=l[m]*r*.9,v=Math.floor(w/(u+d));for(let y=0;y<v;y+=1){const f=y*(u+d);e.fillRect(p,n-f-u,o,u),y>0&&e.fillRect(p,n+f,o,u)}}}function nt(e,s,t,r,i,o,a){const n=r/2,h=Math.floor(t/(o+a)),l=C(s,h),u=Math.max(1.5,o/2);e.fillStyle=i;for(let d=0;d<l.length;d+=1){const m=d*(o+a)+o/2;if(m>t)break;const p=l[d]*r*.9;e.beginPath(),e.arc(m,n-p/2,u,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(m,n+p/2,u,0,Math.PI*2),e.fill()}}function D(e){if(!Number.isFinite(e)||e<0)return"00:00.000";const s=Math.floor(e*1e3),t=s%1e3,r=Math.floor(s/1e3),i=r%60,o=Math.floor(r/60);return`${String(o).padStart(2,"0")}:${String(i).padStart(2,"0")}.${String(t).padStart(3,"0")}`}const N=document.createElement("template");N.innerHTML=`
1
+ (function(b,p){typeof exports=="object"&&typeof module<"u"?p(exports):typeof define=="function"&&define.amd?define(["exports"],p):(b=typeof globalThis<"u"?globalThis:b||self,p(b.Wavegram={}))})(this,(function(b){"use strict";var vt=Object.defineProperty;var yt=(b,p,y)=>p in b?vt(b,p,{enumerable:!0,configurable:!0,writable:!0,value:y}):b[p]=y;var c=(b,p,y)=>yt(b,typeof p!="symbol"?p+"":p,y);var p=typeof document<"u"?document.currentScript:null;let y,B;function $(e){return(!y||B!==e)&&(y==null||y.close(),y=new AudioContext(e?{sampleRate:e}:void 0),B=e),y}async function j(e,o){return $(o).decodeAudioData(e.slice(0))}async function Y(e){const o=await fetch(e);if(!o.ok)throw new Error(`Failed to load audio: ${o.status} ${o.statusText}`);return o.arrayBuffer()}function _(e,o){const t=new Audio(e);return t.preload="auto",t.autoplay=o,t.crossOrigin="anonymous",t}function X(e){const o=new DataView(e);return K(o)??G(o)??J(o)??Q(o)}function K(e){if(e.byteLength<28||!A(e,0,"RIFF")&&!A(e,0,"RF64")||!A(e,8,"WAVE"))return;let o=12;for(;o+8<=e.byteLength;){const t=L(e,o,4),r=e.getUint32(o+4,!0),i=o+8;if(i+r>e.byteLength)return;if(t==="fmt "){if(r<8)return;const s=e.getUint32(i+4,!0);return Number.isFinite(s)&&s>0?s:void 0}o=i+r+r%2}}function G(e){if(!A(e,0,"fLaC"))return;let o=4;for(;o+4<=e.byteLength;){const r=e.getUint8(o)&127,i=e.getUint8(o+1)<<16|e.getUint8(o+2)<<8|e.getUint8(o+3),s=o+4;if(s+i>e.byteLength)return;if(r===0){if(i<13)return;const a=e.getUint8(s+10)<<12|e.getUint8(s+11)<<4|e.getUint8(s+12)>>4;return a>0?a:void 0}o=s+i}}function J(e){const o=W(e,[1,118,111,114,98,105,115]);if(o!==-1&&o+16<=e.byteLength){const r=e.getUint32(o+12,!0);return r>0?r:void 0}const t=W(e,[79,112,117,115,72,101,97,100]);if(t!==-1&&t+16<=e.byteLength){const r=e.getUint32(t+12,!0);return r>0?r:48e3}}function Q(e){let o=0;A(e,0,"ID3")&&e.byteLength>=10&&(o=10+Z(e,6));const t=[44100,48e3,32e3],r=[22050,24e3,16e3],i=[11025,12e3,8e3];for(;o+4<=e.byteLength;o+=1){const s=e.getUint8(o),a=e.getUint8(o+1);if(s!==255||(a&224)!==224)continue;const n=a>>3&3,h=a>>1&3,l=e.getUint8(o+2)>>2&3;if(n===1||h===0||l===3)continue;return(n===3?t:n===2?r:i)[l]}}function W(e,o){const t=e.byteLength-o.length;for(let r=0;r<=t;r+=1){let i=!0;for(let s=0;s<o.length;s+=1)if(e.getUint8(r+s)!==o[s]){i=!1;break}if(i)return r}return-1}function Z(e,o){return e.getUint8(o)<<21|e.getUint8(o+1)<<14|e.getUint8(o+2)<<7|e.getUint8(o+3)}function A(e,o,t){return o+t.length>e.byteLength?!1:L(e,o,t.length)===t}function L(e,o,t){let r="";for(let i=0;i<t;i+=1)r+=String.fromCharCode(e.getUint8(o+i));return r}function M(e,o,t){return Math.min(t,Math.max(o,e))}const F=1e-10;function H(e){return Number.isInteger(e)&&e>0&&(e&e-1)===0}function tt(e,o){const t=new Float32Array(e);if(e===1)return t[0]=1,t;for(let r=0;r<e;r+=1)o==="hann"?t[r]=.5-.5*Math.cos(2*Math.PI*r/(e-1)):o==="hamming"?t[r]=.54-.46*Math.cos(2*Math.PI*r/(e-1)):t[r]=1;return t}function et(e){let o=0;for(const t of e)o+=t;return o/e.length}function rt(e){return 20*Math.log10(Math.abs(e)+F)}function ot(e,o){const t=e.length;if(!H(t)||o.length!==t)throw new Error("FFT input length must be a radix-2 size.");for(let r=1,i=0;r<t;r+=1){let s=t>>1;for(;i&s;s>>=1)i^=s;if(i^=s,r<i){const a=e[r];e[r]=e[i],e[i]=a;const n=o[r];o[r]=o[i],o[i]=n}}for(let r=2;r<=t;r<<=1){const i=-2*Math.PI/r,s=Math.cos(i),a=Math.sin(i);for(let n=0;n<t;n+=r){let h=1,l=0;for(let u=0;u<r/2;u+=1){const d=e[n+u],m=o[n+u],g=e[n+u+r/2]*h-o[n+u+r/2]*l,w=e[n+u+r/2]*l+o[n+u+r/2]*h;e[n+u]=d+g,o[n+u]=m+w,e[n+u+r/2]=d-g,o[n+u+r/2]=m-w;const v=h*s-l*a;l=h*a+l*s,h=v}}}}function it(e,o,t){const{fftSize:r,hopSize:i,windowType:s,minDb:a,maxDb:n}=t;if(!H(r))throw new Error(`fftSize must be a power of two. Received ${r}.`);if(!Number.isInteger(i)||i<=0)throw new Error(`hopSize must be a positive integer. Received ${i}.`);if(n<=a)throw new Error("maxDb must be greater than minDb.");const h=r/2+1,l=Math.max(1,Math.floor(Math.max(0,e.length-r)/i)+1),u=new Float32Array(l*h),d=tt(r,s),m=Math.max(F,r*et(d)/2),g=new Float32Array(r),w=new Float32Array(r);for(let v=0;v<l;v+=1){const S=v*i;g.fill(0),w.fill(0);for(let f=0;f<r;f+=1)g[f]=(e[S+f]??0)*d[f];ot(g,w);for(let f=0;f<h;f+=1){const R=Math.hypot(g[f],w[f])/m;u[v*h+f]=M(rt(R),a,n)}}return{values:u,freqBins:h,timeFrames:l,sampleRate:o,maxFrequencyHz:o/2,fftSize:r,hopSize:i,minDb:a,maxDb:n}}function U(e,o){if(o==="mix"){const t=new Float32Array(e.length);for(let r=0;r<e.numberOfChannels;r+=1){const i=e.getChannelData(r);for(let s=0;s<t.length;s+=1)t[s]+=i[s]/e.numberOfChannels}return t}if(!Number.isInteger(o)||o<0||o>=e.numberOfChannels)throw new Error(`Invalid channel ${o}. Audio has ${e.numberOfChannels} channel(s).`);return new Float32Array(e.getChannelData(o))}function st(e,o){const t=Math.max(1,Math.floor(o)),r=new Float32Array(t),i=new Float32Array(t),s=e.length/t;for(let a=0;a<t;a+=1){const n=Math.floor(a*s),h=Math.max(n+1,Math.floor((a+1)*s));let l=1,u=-1;for(let d=n;d<h&&d<e.length;d+=1){const m=e[d]??0;m<l&&(l=m),m>u&&(u=m)}r[a]=l===1?0:l,i[a]=u===-1?0:u}return{min:r,max:i}}function P(e,o,t){return st(U(e,t),o)}function k(e,o,t){const r=window.devicePixelRatio||1;e.style.width="100%",e.style.height=`${t}px`,e.width=Math.max(1,Math.floor(o*r)),e.height=Math.max(1,Math.floor(t*r));const i=e.getContext("2d");if(!i)throw new Error("Canvas 2D context is unavailable.");return i.setTransform(r,0,0,r,0,0),i}function D(e,o,t,r,i="rgba(0, 0, 0, 0.45)"){if(!Number.isFinite(t)||t<=0)return;const s=o/t;if(!Number.isFinite(s)||s>=1)return;const a=e.getContext("2d");if(!a)return;const n=e.clientWidth,h=e.clientHeight,l=Math.max(0,Math.min(n,s*n));a.save(),a.strokeStyle=i,a.lineWidth=2,a.beginPath(),a.moveTo(l,0),a.lineTo(l,h),a.stroke(),a.strokeStyle=r,a.lineWidth=1,a.beginPath(),a.moveTo(l,0),a.lineTo(l,h),a.stroke(),a.restore()}function C(e,o){const t=M(o,0,1)*(e.length-1),r=Math.floor(t),i=Math.min(r+1,e.length-1),s=t-r,a=e[r],n=e[i];return[Math.round(a[0]+(n[0]-a[0])*s),Math.round(a[1]+(n[1]-a[1])*s),Math.round(a[2]+(n[2]-a[2])*s)]}function at(e,o){const t=M(o,0,1);if(e==="audition")return C([[0,0,0],[12,7,34],[25,37,114],[18,104,174],[39,178,172],[244,180,43],[252,76,27],[255,238,117]],t);if(e==="gray"){const r=Math.round(t*255);return[r,r,r]}return C(e==="viridis"?[[68,1,84],[59,82,139],[33,145,140],[94,201,98],[253,231,37]]:e==="inferno"?[[0,0,4],[87,15,109],[187,55,84],[249,142,8],[252,255,164]]:[[0,0,4],[73,16,105],[182,54,121],[251,136,97],[252,253,191]],t)}function nt(e,o,t){const r=e.getContext("2d");if(!r)return;const i=e.clientWidth,s=e.clientHeight,a=Math.max(1,e.width),n=Math.max(1,e.height);if(r.clearRect(0,0,i,s),r.fillStyle=t.background,r.fillRect(0,0,i,s),!o)return;const h=r.createImageData(a,n),l=o.maxDb-o.minDb;for(let u=0;u<h.width;u+=1){const d=Math.min(o.timeFrames-1,Math.floor(u/h.width*o.timeFrames));for(let m=0;m<h.height;m+=1){const g=Math.min(o.freqBins-1,Math.floor((h.height-1-m)/h.height*o.freqBins)),w=o.values[d*o.freqBins+g],v=M((w-o.minDb)/l,0,1),[S,f,R]=at(t.colorMap,v),T=(m*h.width+u)*4;h.data[T]=S,h.data[T+1]=f,h.data[T+2]=R,h.data[T+3]=255}}r.putImageData(h,0,0),lt(r,i,s,o.maxFrequencyHz,t.tickColor)}function ht(e,o){if(!Number.isFinite(e)||e<=0)return 1e3;const t=Math.max(2,Math.min(6,Math.floor(o/28))),r=e/t,i=10**Math.floor(Math.log10(r)),s=r/i;return(s<=1?1:s<=2?2:s<=7.5?5:10)*i}function lt(e,o,t,r,i="rgba(255, 255, 255, 0.42)"){const s=ht(r,t),a=5;e.save(),e.strokeStyle=i,e.fillStyle=i,e.lineWidth=1,e.font="10px system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif",e.textAlign="left",e.textBaseline="middle";for(let n=s;n<r;n+=s){const h=t-n/r*t;e.beginPath(),e.moveTo(0,h+.5),e.lineTo(o,h+.5),e.stroke(),e.fillText(N(n),a,h)}e.beginPath(),e.moveTo(0,.5),e.lineTo(o,.5),e.stroke(),e.fillText(N(r),a,8),e.restore()}function N(e){if(e>=1e3){const o=e/1e3;return`${Number.isInteger(o)?o.toFixed(0):o.toFixed(1)}k`}return`${Math.round(e)}`}function z(e,o,t){const r=e.getContext("2d");if(!r)return;const{width:i,height:s}=ut(e,r);if(r.clearRect(0,0,i,s),r.fillStyle=t.background,r.fillRect(0,0,i,s),r.strokeStyle=t.centerColor??t.color,r.lineWidth=1,!o)return;const a=t.style??"waveform",n=dt(o),h=mt(a),l=Math.max(1,t.barWidth??h.barWidth),u=Math.max(0,t.barSpacing??h.barSpacing);a==="waveform"?ft(r,o,s,{unplayedColor:t.color,playedColor:t.playedColor??t.progressColor??t.color,centerColor:t.centerColor??t.color,progress:t.progress??0}):a==="lines"?pt(r,n,i,s,t.color):a==="blocks"?bt(r,n,i,s,t.color,l,u):a==="dots"?wt(r,n,i,s,t.color,l,u):gt(r,n,i,s,t.color,l,u)}function ut(e,o){if(typeof o.getTransform!="function")return{width:e.clientWidth,height:e.clientHeight};const t=o.getTransform(),r=Math.abs(t.a)||1,i=Math.abs(t.d)||1;return{width:Math.max(e.clientWidth,e.width/r),height:Math.max(e.clientHeight,e.height/i)}}function ct(e,o){return Math.max(Math.abs(e.min[o]??0),Math.abs(e.max[o]??0))}function dt(e){const o=[];for(let t=0;t<e.max.length;t+=1)o.push(ct(e,t));return o}function x(e,o){if(e.length===o)return e;if(e.length===0||o<=0)return[];const t=[];if(o>e.length){const r=(e.length-1)/Math.max(1,o-1);for(let i=0;i<o;i+=1){const s=i*r,a=Math.floor(s),n=Math.ceil(s),h=s-a;n>=e.length?t.push(e[e.length-1]??0):a===n?t.push(e[a]??0):t.push((e[a]??0)*(1-h)+(e[n]??0)*h)}}else{const r=e.length/o;for(let i=0;i<o;i+=1){const s=Math.floor(i*r),a=Math.floor((i+1)*r);let n=0,h=0;for(let l=s;l<=a&&l<e.length;l+=1)n=Math.max(n,e[l]??0),h+=1;h===0&&(n=e[Math.min(Math.round(i*r),e.length-1)]??0),t.push(n)}}return t}function mt(e){return e==="bars"?{barWidth:3,barSpacing:1}:e==="blocks"?{barWidth:4,barSpacing:2}:e==="dots"?{barWidth:3,barSpacing:3}:{barWidth:2,barSpacing:0}}function ft(e,o,t,r){const i=t/2;e.strokeStyle=r.centerColor,e.lineWidth=1,e.beginPath(),e.moveTo(0,i),e.lineTo(o.max.length,i),e.stroke(),I(e,o,t,0,o.min.length,r.unplayedColor);const s=Math.max(0,Math.min(o.min.length,Math.round(o.min.length*r.progress)));s>0&&I(e,o,t,0,s,r.playedColor)}function I(e,o,t,r,i,s){const a=t/2;e.strokeStyle=s,e.beginPath();for(let n=r;n<i;n+=1){const h=a-o.min[n]*a,l=a-o.max[n]*a;e.moveTo(n+.5,h),e.lineTo(n+.5,l)}e.stroke()}function gt(e,o,t,r,i,s,a){const n=Math.floor(t/(s+a)),h=x(o,n);e.fillStyle=i;for(let l=0;l<h.length;l+=1){const u=l*(s+a);if(u+s>t)break;const d=h[l]*r*.9;e.fillRect(u,r-d,s,d)}}function pt(e,o,t,r,i){const s=r/2,a=x(o,Math.max(2,Math.floor(t/3)));e.strokeStyle=i,e.lineWidth=2,e.lineCap="round",e.lineJoin="round",e.strokeStyle="rgba(255, 255, 255, 0.03)",e.lineWidth=.5,e.beginPath(),e.moveTo(0,s),e.lineTo(t,s),e.stroke();for(let h=0;h<=10;h+=1){const l=t/10*h;e.beginPath(),e.moveTo(l,0),e.lineTo(l,r),e.stroke()}e.strokeStyle=i,e.lineWidth=2,e.beginPath(),e.moveTo(0,s);const n=a.map((h,l)=>{const u=l/Math.max(1,a.length-1)*t,d=s+Math.sin(l*.1)*h*r*.35;return{x:u,y:d}});for(let h=0;h<n.length-1;h+=1){const l=n[h],u=n[h+1],d=l.x+(u.x-l.x)*.5,m=u.x-(u.x-l.x)*.5;e.bezierCurveTo(d,l.y,m,u.y,u.x,u.y)}e.stroke()}function bt(e,o,t,r,i,s,a){const n=r/2,h=Math.floor(t/(s+a)),l=x(o,h),u=4,d=2;e.fillStyle=i;for(let m=0;m<l.length;m+=1){const g=m*(s+a);if(g+s>t)break;const w=l[m]*r*.9,v=Math.floor(w/(u+d));for(let S=0;S<v;S+=1){const f=S*(u+d);e.fillRect(g,n-f-u,s,u),S>0&&e.fillRect(g,n+f,s,u)}}}function wt(e,o,t,r,i,s,a){const n=r/2,h=Math.floor(t/(s+a)),l=x(o,h),u=Math.max(1.5,s/2);e.fillStyle=i;for(let d=0;d<l.length;d+=1){const m=d*(s+a)+s/2;if(m>t)break;const g=l[d]*r*.9;e.beginPath(),e.arc(m,n-g/2,u,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(m,n+g/2,u,0,Math.PI*2),e.fill()}}function O(e){if(!Number.isFinite(e)||e<0)return"00:00.000";const o=Math.floor(e*1e3),t=o%1e3,r=Math.floor(o/1e3),i=r%60,s=Math.floor(r/60);return`${String(s).padStart(2,"0")}:${String(i).padStart(2,"0")}.${String(t).padStart(3,"0")}`}const q=document.createElement("template");q.innerHTML=`
2
2
  <style>
3
3
  :host {
4
4
  --ap-bg: #ffffff;
@@ -188,4 +188,4 @@
188
188
  </div>
189
189
  </div>
190
190
  </div>
191
- `;class x extends HTMLElement{constructor(){super();c(this,"audio");c(this,"audioBuffer");c(this,"waveformPeaks");c(this,"spectrogram");c(this,"worker");c(this,"resizeObserver");c(this,"animationFrame",0);c(this,"loadingToken",0);c(this,"blobUrl");c(this,"playRequestedAt");c(this,"root");c(this,"button");c(this,"toolbar");c(this,"timeEl");c(this,"currentEl");c(this,"durationEl");c(this,"statusEl");c(this,"errorEl");c(this,"waveformPane");c(this,"spectrogramPane");c(this,"waveformCanvas");c(this,"spectrogramCanvas");c(this,"spectrogramOverlay");c(this,"waveformCursor");c(this,"spectrogramCursor");c(this,"handlePlayButton",()=>{this.audio&&(this.audio.paused?(this.playRequestedAt=performance.now(),this.audio.play().catch(t=>this.handleError("Audio playback failed.",t))):this.audio.pause())});c(this,"handleSeekClick",t=>{if(!this.audio||!Number.isFinite(this.duration)||this.duration<=0)return;const i=t.currentTarget.getBoundingClientRect(),o=(t.clientX-i.left)/i.width;this.audio.currentTime=Math.max(0,Math.min(this.duration,o*this.duration)),this.updateTimeLabels(),this.drawCursors(),this.dispatchTypedEvent("seek"),this.audio.paused?(this.playRequestedAt=performance.now(),this.audio.play().catch(a=>this.handleError("Audio playback failed.",a))):this.audio.pause()});c(this,"handleKeydown",t=>{t.key!==" "&&t.key!=="Enter"||(t.preventDefault(),this.handlePlayButton())});c(this,"handleTimeUpdate",()=>{this.updateTimeLabels(),this.dispatchTypedEvent("timeupdate")});c(this,"handleAudioPlay",()=>{this.button.textContent="Pause",this.button.setAttribute("aria-label","Pause"),this.button.dataset.state="pause",this.dispatchTypedEvent("play")});c(this,"handleAudioPlaying",()=>{if(this.playRequestedAt!==void 0){const t={playToPlayingMs:performance.now()-this.playRequestedAt};this.dispatchEvent(new CustomEvent("playprofile",{detail:t})),this.playRequestedAt=void 0}this.startAnimation()});c(this,"handleAudioPause",()=>{this.button.textContent="Play",this.button.setAttribute("aria-label","Play"),this.button.dataset.state="play",this.dispatchTypedEvent("pause"),this.stopAnimation(),this.drawCursors()});c(this,"updateTimeLabels",()=>{var t;this.currentEl.textContent=D(((t=this.audio)==null?void 0:t.currentTime)??0),this.durationEl.textContent=D(this.duration)});this.root=this.attachShadow({mode:"open"}),this.root.append(N.content.cloneNode(!0)),this.button=this.requireElement("button"),this.button.dataset.state="play",this.toolbar=this.requireElement(".toolbar"),this.timeEl=this.requireElement(".time"),this.currentEl=this.requireElement(".current"),this.durationEl=this.requireElement(".duration"),this.statusEl=this.requireElement(".status"),this.errorEl=this.requireElement(".error"),this.waveformPane=this.requireElement(".waveform-pane"),this.spectrogramPane=this.requireElement(".spectrogram-pane"),this.waveformCanvas=this.requireElement(".waveform"),this.spectrogramCanvas=this.requireElement(".spectrogram"),this.spectrogramOverlay=this.requireElement(".spectrogram-overlay"),this.waveformCursor=this.requireElement(".waveform-cursor"),this.spectrogramCursor=this.requireElement(".spectrogram-cursor")}get src(){return this.getAttribute("src")??""}set src(t){this.setAttribute("src",t)}get height(){return this.getNumberAttribute("height",this.waveformHeight+this.spectrogramHeight)}set height(t){this.setAttribute("height",String(t))}get waveformHeight(){return this.getNumberAttribute("waveform-height",80)}set waveformHeight(t){this.setAttribute("waveform-height",String(t))}get spectrogramHeight(){return this.getNumberAttribute("spectrogram-height",120)}set spectrogramHeight(t){this.setAttribute("spectrogram-height",String(t))}get showWaveform(){return this.getBooleanAttribute("show-waveform",!0)}set showWaveform(t){this.setBooleanAttribute("show-waveform",t)}get showSpectrogram(){return this.getBooleanAttribute("show-spectrogram",!0)}set showSpectrogram(t){this.setBooleanAttribute("show-spectrogram",t)}get showControls(){return this.getBooleanAttribute("show-controls",!1)}set showControls(t){this.setBooleanAttribute("show-controls",t)}get showTime(){return this.getBooleanAttribute("show-time",!1)}set showTime(t){this.setBooleanAttribute("show-time",t)}get waveformStyle(){const t=this.getAttribute("waveform-style");return t==="line"?"lines":t==="waveform"?"waveform":t==="bars"||t==="lines"||t==="blocks"||t==="dots"?t:"waveform"}set waveformStyle(t){this.setAttribute("waveform-style",t)}get waveformBarWidth(){return this.getOptionalNumberAttribute("waveform-bar-width")}set waveformBarWidth(t){this.setAttribute("waveform-bar-width",String(t))}get waveformBarSpacing(){return this.getOptionalNumberAttribute("waveform-bar-spacing")}set waveformBarSpacing(t){this.setAttribute("waveform-bar-spacing",String(t))}get autoplay(){return this.getBooleanAttribute("autoplay",!1)}set autoplay(t){this.setBooleanAttribute("autoplay",t)}get fftSize(){return this.getNumberAttribute("fft-size",1024)}set fftSize(t){this.setAttribute("fft-size",String(t))}get hopSize(){return this.getNumberAttribute("hop-size",256)}set hopSize(t){this.setAttribute("hop-size",String(t))}get windowType(){const t=this.getAttribute("window-type");return t==="hamming"||t==="rectangular"?t:"hann"}set windowType(t){this.setAttribute("window-type",t)}get minDb(){return this.getNumberAttribute("min-db",-80)}set minDb(t){this.setAttribute("min-db",String(t))}get maxDb(){return this.getNumberAttribute("max-db",0)}set maxDb(t){this.setAttribute("max-db",String(t))}get colorMap(){const t=this.getAttribute("color-map");return t==="gray"||t==="magma"||t==="viridis"||t==="inferno"?t:"audition"}set colorMap(t){this.setAttribute("color-map",t)}get channel(){const t=this.getAttribute("channel");if(!t||t==="mix")return"mix";const r=Number(t);return Number.isInteger(r)?r:"mix"}set channel(t){this.setAttribute("channel",String(t))}connectedCallback(){this.button.addEventListener("click",this.handlePlayButton),this.waveformPane.addEventListener("click",this.handleSeekClick),this.spectrogramPane.addEventListener("click",this.handleSeekClick),this.addEventListener("keydown",this.handleKeydown),this.tabIndex=this.tabIndex>=0?this.tabIndex:0,this.resizeObserver=new ResizeObserver(()=>this.layoutAndRender()),this.resizeObserver.observe(this),this.layoutAndRender(),this.src&&this.load()}disconnectedCallback(){var t,r,i;this.button.removeEventListener("click",this.handlePlayButton),this.waveformPane.removeEventListener("click",this.handleSeekClick),this.spectrogramPane.removeEventListener("click",this.handleSeekClick),this.removeEventListener("keydown",this.handleKeydown),(t=this.resizeObserver)==null||t.disconnect(),this.stopAnimation(),(r=this.worker)==null||r.terminate(),(i=this.audio)==null||i.pause(),this.revokeBlobUrl()}attributeChangedCallback(t,r,i){if(!(r===i||!this.isConnected)){if(t==="src"){this.load();return}if(["fft-size","hop-size","window-type","min-db","max-db","channel"].includes(t)){this.audioBuffer&&this.recomputeAnalysis();return}this.layoutAndRender()}}async load(){var i,o,a;const t=this.src,r=++this.loadingToken;if(this.clearError(),this.setStatus(t?"Loading":""),this.dispatchTypedEvent("loadstart"),this.button.disabled=!0,this.waveformPeaks=void 0,this.spectrogram=void 0,this.layoutAndRender(),(i=this.worker)==null||i.terminate(),(o=this.audio)==null||o.pause(),this.revokeBlobUrl(),!t){this.setStatus("");return}try{const n=performance.now(),h=await O(t),l=performance.now();if(r!==this.loadingToken)return;this.blobUrl=URL.createObjectURL(new Blob([h])),this.audio=U(this.blobUrl,this.autoplay),this.bindAudio();const u=this.waitForAudioReady(this.audio);this.audioBuffer=await I(h);const d=performance.now();if(r!==this.loadingToken)return;const m=Math.max(1,Math.floor(this.getCanvasWidth())),p=performance.now();this.waveformPeaks=this.showWaveform?H(this.audioBuffer,m,this.channel):void 0;const w=performance.now();await u;const v=performance.now();if(r!==this.loadingToken)return;this.button.disabled=!1,this.setStatus(this.showSpectrogram?"Analyzing":""),this.updateTimeLabels(),this.dispatchTypedEvent("loaded");const y=performance.now(),f={fetchMs:l-n,audioReadyMs:v-l,decodeMs:d-l,waveformMs:w-p,firstUsableMs:y-n};this.dispatchEvent(new CustomEvent("profile",{detail:f})),this.layoutAndRender(),this.computeSpectrogramForCurrentBuffer(r,f,n),this.autoplay&&await((a=this.audio)==null?void 0:a.play())}catch(n){if(r!==this.loadingToken)return;this.handleError("Failed to load audio.",n)}}async recomputeAnalysis(){if(!this.audioBuffer)return;const t=Math.max(1,Math.floor(this.getCanvasWidth()));this.waveformPeaks=this.showWaveform?H(this.audioBuffer,t,this.channel):void 0,this.layoutAndRender(),this.showSpectrogram?(this.setStatus("Analyzing"),this.spectrogram=await this.computeSpectrogramInWorker(),this.setStatus("")):this.spectrogram=void 0,this.layoutAndRender()}async computeSpectrogramForCurrentBuffer(t,r,i){if(!this.audioBuffer||!this.showSpectrogram){this.spectrogram=void 0,this.setStatus(""),this.layoutAndRender();return}try{const o=performance.now();this.spectrogram=await this.computeSpectrogramInWorker();const a=performance.now();if(t!==this.loadingToken)return;this.setStatus(""),this.layoutAndRender(),this.dispatchEvent(new CustomEvent("profile",{detail:{...r,spectrogramMs:a-o,totalMs:a-i}}))}catch(o){if(t!==this.loadingToken)return;this.spectrogram=void 0,this.setStatus("Spectrogram unavailable"),this.dispatchEvent(new CustomEvent("error",{detail:{message:o instanceof Error?o.message:"Failed to compute spectrogram.",cause:o}}))}}computeSpectrogramInWorker(){if(!this.audioBuffer)return Promise.resolve(void 0);const t=B(this.audioBuffer,this.channel),r={samples:t,sampleRate:this.audioBuffer.sampleRate,fftSize:this.fftSize,hopSize:this.hopSize,windowType:this.windowType,minDb:this.minDb,maxDb:this.maxDb};return typeof Worker>"u"?Promise.resolve(_(t,this.audioBuffer.sampleRate,r)):new Promise((i,o)=>{var a;(a=this.worker)==null||a.terminate(),this.worker=new Worker(new URL("/assets/spectrogram.worker-Burn7NUr.js",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:g&&g.tagName.toUpperCase()==="SCRIPT"&&g.src||new URL("index.umd.js",document.baseURI).href),{type:"module"}),this.worker.addEventListener("message",n=>{"error"in n.data?o(new Error(n.data.error.message)):i(n.data)},{once:!0}),this.worker.addEventListener("error",()=>o(new Error("Spectrogram worker failed.")),{once:!0}),this.worker.postMessage(r,[r.samples.buffer])})}bindAudio(){this.audio&&(this.audio.addEventListener("loadedmetadata",this.updateTimeLabels),this.audio.addEventListener("timeupdate",this.handleTimeUpdate),this.audio.addEventListener("play",this.handleAudioPlay),this.audio.addEventListener("playing",this.handleAudioPlaying),this.audio.addEventListener("pause",this.handleAudioPause),this.audio.addEventListener("ended",this.handleAudioPause),this.audio.addEventListener("error",()=>{var t;return this.handleError("Audio playback failed.",(t=this.audio)==null?void 0:t.error)}))}layoutAndRender(){const t=Math.max(1,Math.floor(this.getCanvasWidth())),{waveformHeight:r,spectrogramHeight:i}=this.getPaneHeights();this.toolbar.classList.toggle("hidden",!this.showControls&&!this.showTime),this.button.classList.toggle("hidden",!this.showControls),this.timeEl.classList.toggle("hidden",!this.showTime),this.waveformPane.classList.toggle("hidden",!this.showWaveform),this.spectrogramPane.classList.toggle("hidden",!this.showSpectrogram),this.showWaveform&&(S(this.waveformCanvas,t,r),S(this.waveformCursor,t,r),F(this.waveformCanvas,this.waveformPeaks,{color:this.cssVar("--ap-waveform","rgba(0, 214, 163, 0.34)"),playedColor:this.cssVar("--ap-waveform-played","#00f0b5"),centerColor:this.cssVar("--ap-waveform-center","rgba(0, 92, 58, 0.7)"),progressColor:this.cssVar("--ap-waveform-progress","#00f0b5"),background:this.cssVar("--ap-waveform-bg","#020604"),style:this.waveformStyle,barWidth:this.waveformBarWidth,barSpacing:this.waveformBarSpacing,progress:this.playbackProgress})),this.showSpectrogram&&(S(this.spectrogramCanvas,t,i),S(this.spectrogramOverlay,t,i),S(this.spectrogramCursor,t,i),X(this.spectrogramCanvas,this.spectrogram,{colorMap:this.colorMap,background:this.cssVar("--ap-bg","#ffffff"),tickColor:this.cssVar("--ap-spectrogram-tick","rgba(255, 255, 255, 0.42)")}),this.drawSpectrogramOverlay()),this.drawCursors()}drawCursors(){var a;const t=((a=this.audio)==null?void 0:a.currentTime)??0,r=this.duration,i=this.cssVar("--ap-cursor","#ff0000"),o=this.cssVar("--ap-cursor-shadow","rgba(0, 0, 0, 0.45)");this.showWaveform&&this.waveformStyle==="waveform"&&F(this.waveformCanvas,this.waveformPeaks,{color:this.cssVar("--ap-waveform","rgba(0, 214, 163, 0.34)"),playedColor:this.cssVar("--ap-waveform-played","#00f0b5"),centerColor:this.cssVar("--ap-waveform-center","rgba(0, 92, 58, 0.7)"),progressColor:this.cssVar("--ap-waveform-progress","#00f0b5"),background:this.cssVar("--ap-waveform-bg","#020604"),style:this.waveformStyle,barWidth:this.waveformBarWidth,barSpacing:this.waveformBarSpacing,progress:this.playbackProgress}),this.drawSpectrogramOverlay(),this.clearCursor(this.waveformCursor),this.clearCursor(this.spectrogramCursor),this.showWaveform&&W(this.waveformCursor,t,r,i,o),this.showSpectrogram&&W(this.spectrogramCursor,t,r,i,o)}clearCursor(t){const r=t.getContext("2d");r==null||r.clearRect(0,0,t.clientWidth,t.clientHeight)}drawSpectrogramOverlay(){const t=this.spectrogramOverlay.getContext("2d");if(!t)return;const r=this.spectrogramOverlay.clientWidth,i=this.spectrogramOverlay.clientHeight;if(t.clearRect(0,0,r,i),!this.showSpectrogram||!this.spectrogram)return;const o=r*this.playbackProgress,a=1-this.cssNumberVar("--ap-spectrogram-unplayed-opacity",.48);o<r&&(t.fillStyle=`rgba(0, 0, 0, ${Math.max(0,Math.min(1,a))})`,t.fillRect(o,0,r-o,i))}startAnimation(){this.stopAnimation();const t=()=>{this.updateTimeLabels(),this.drawCursors(),this.animationFrame=requestAnimationFrame(t)};this.animationFrame=requestAnimationFrame(t)}stopAnimation(){this.animationFrame&&(cancelAnimationFrame(this.animationFrame),this.animationFrame=0)}get duration(){var t,r;return((t=this.audio)==null?void 0:t.duration)||((r=this.audioBuffer)==null?void 0:r.duration)||0}get playbackProgress(){var r;const t=this.duration;return!Number.isFinite(t)||t<=0?0:Math.max(0,Math.min(1,(((r=this.audio)==null?void 0:r.currentTime)??0)/t))}dispatchTypedEvent(t){var i;const r={currentTime:((i=this.audio)==null?void 0:i.currentTime)??0,duration:this.duration};this.dispatchEvent(new CustomEvent(t,{detail:r}))}handleError(t,r){this.button.disabled=!0,this.setStatus("");const i={message:r instanceof Error?`${t} ${r.message}`:t,cause:r};this.errorEl.textContent=i.message,this.errorEl.classList.remove("hidden"),this.dispatchEvent(new CustomEvent("error",{detail:i}))}clearError(){this.errorEl.textContent="",this.errorEl.classList.add("hidden")}setStatus(t){this.statusEl.textContent=t}getCanvasWidth(){return this.clientWidth||this.getBoundingClientRect().width||640}getPaneHeights(){if(!this.showWaveform&&!this.showSpectrogram)return{waveformHeight:0,spectrogramHeight:0};const t=this.hasAttribute("height"),r=this.hasAttribute("waveform-height"),i=this.hasAttribute("spectrogram-height");if(!t)return{waveformHeight:this.showWaveform?this.waveformHeight:0,spectrogramHeight:this.showSpectrogram?this.spectrogramHeight:0};const o=this.height;return this.showWaveform&&!this.showSpectrogram?{waveformHeight:r?this.waveformHeight:o,spectrogramHeight:0}:!this.showWaveform&&this.showSpectrogram?{waveformHeight:0,spectrogramHeight:i?this.spectrogramHeight:o}:r&&i?{waveformHeight:this.waveformHeight,spectrogramHeight:this.spectrogramHeight}:r?{waveformHeight:this.waveformHeight,spectrogramHeight:Math.max(1,o-this.waveformHeight)}:i?{waveformHeight:Math.max(1,o-this.spectrogramHeight),spectrogramHeight:this.spectrogramHeight}:{waveformHeight:Math.max(1,Math.round(o*(80/200))),spectrogramHeight:Math.max(1,o-Math.round(o*(80/200)))}}getNumberAttribute(t,r){const i=Number(this.getAttribute(t));return Number.isFinite(i)&&i>0?i:r}getOptionalNumberAttribute(t){if(!this.hasAttribute(t))return;const r=Number(this.getAttribute(t));return Number.isFinite(r)&&r>0?r:void 0}getBooleanAttribute(t,r){if(!this.hasAttribute(t))return r;const i=this.getAttribute(t);return i===""||i==="true"||i===t}setBooleanAttribute(t,r){r?this.setAttribute(t,""):this.setAttribute(t,"false")}cssVar(t,r){return getComputedStyle(this).getPropertyValue(t).trim()||r}cssNumberVar(t,r){const i=Number(getComputedStyle(this).getPropertyValue(t).trim());return Number.isFinite(i)?i:r}requireElement(t){const r=this.root.querySelector(t);if(!r)throw new Error(`Missing template element: ${t}`);return r}waitForAudioReady(t){return t.readyState>=HTMLMediaElement.HAVE_METADATA?Promise.resolve():new Promise((r,i)=>{const o=()=>{t.removeEventListener("loadedmetadata",a),t.removeEventListener("error",n)},a=()=>{o(),r()},n=()=>{o(),i(t.error??new Error("Audio metadata failed to load."))};t.addEventListener("loadedmetadata",a,{once:!0}),t.addEventListener("error",n,{once:!0}),t.load()})}revokeBlobUrl(){this.blobUrl&&(URL.revokeObjectURL(this.blobUrl),this.blobUrl=void 0)}}c(x,"observedAttributes",["src","height","waveform-height","spectrogram-height","show-waveform","show-spectrogram","show-controls","show-time","waveform-style","waveform-bar-width","waveform-bar-spacing","autoplay","fft-size","hop-size","window-type","min-db","max-db","color-map","channel"]);class q extends x{}customElements.get("wavegram-player")||customElements.define("wavegram-player",x),customElements.get("audio-preview-spectrogram")||customElements.define("audio-preview-spectrogram",q),b.AudioPreviewSpectrogram=q,b.Wavegram=x,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})}));
191
+ `;class E extends HTMLElement{constructor(){super();c(this,"audio");c(this,"audioBuffer");c(this,"sourceSampleRate");c(this,"waveformPeaks");c(this,"spectrogram");c(this,"worker");c(this,"resizeObserver");c(this,"animationFrame",0);c(this,"loadingToken",0);c(this,"waveformPeaksWidth",0);c(this,"blobUrl");c(this,"playRequestedAt");c(this,"root");c(this,"button");c(this,"toolbar");c(this,"timeEl");c(this,"currentEl");c(this,"durationEl");c(this,"statusEl");c(this,"errorEl");c(this,"waveformPane");c(this,"spectrogramPane");c(this,"waveformCanvas");c(this,"spectrogramCanvas");c(this,"spectrogramOverlay");c(this,"waveformCursor");c(this,"spectrogramCursor");c(this,"handlePlayButton",()=>{this.audio&&(this.audio.paused?(this.playRequestedAt=performance.now(),this.audio.play().catch(t=>this.handleError("Audio playback failed.",t))):this.audio.pause())});c(this,"handleSeekClick",t=>{if(!this.audio||!Number.isFinite(this.duration)||this.duration<=0)return;const i=t.currentTarget.getBoundingClientRect(),s=(t.clientX-i.left)/i.width;this.audio.currentTime=Math.max(0,Math.min(this.duration,s*this.duration)),this.updateTimeLabels(),this.drawCursors(),this.dispatchTypedEvent("seek"),this.audio.paused?(this.playRequestedAt=performance.now(),this.audio.play().catch(a=>this.handleError("Audio playback failed.",a))):this.audio.pause()});c(this,"handleKeydown",t=>{t.key!==" "&&t.key!=="Enter"||(t.preventDefault(),this.handlePlayButton())});c(this,"handleTimeUpdate",()=>{this.updateTimeLabels(),this.dispatchTypedEvent("timeupdate")});c(this,"handleAudioPlay",()=>{this.button.textContent="Pause",this.button.setAttribute("aria-label","Pause"),this.button.dataset.state="pause",this.dispatchTypedEvent("play")});c(this,"handleAudioPlaying",()=>{if(this.playRequestedAt!==void 0){const t={playToPlayingMs:performance.now()-this.playRequestedAt};this.dispatchEvent(new CustomEvent("playprofile",{detail:t})),this.playRequestedAt=void 0}this.startAnimation()});c(this,"handleAudioPause",()=>{this.button.textContent="Play",this.button.setAttribute("aria-label","Play"),this.button.dataset.state="play",this.dispatchTypedEvent("pause"),this.stopAnimation(),this.drawCursors()});c(this,"updateTimeLabels",()=>{var t;this.currentEl.textContent=O(((t=this.audio)==null?void 0:t.currentTime)??0),this.durationEl.textContent=O(this.duration)});this.root=this.attachShadow({mode:"open"}),this.root.append(q.content.cloneNode(!0)),this.button=this.requireElement("button"),this.button.dataset.state="play",this.toolbar=this.requireElement(".toolbar"),this.timeEl=this.requireElement(".time"),this.currentEl=this.requireElement(".current"),this.durationEl=this.requireElement(".duration"),this.statusEl=this.requireElement(".status"),this.errorEl=this.requireElement(".error"),this.waveformPane=this.requireElement(".waveform-pane"),this.spectrogramPane=this.requireElement(".spectrogram-pane"),this.waveformCanvas=this.requireElement(".waveform"),this.spectrogramCanvas=this.requireElement(".spectrogram"),this.spectrogramOverlay=this.requireElement(".spectrogram-overlay"),this.waveformCursor=this.requireElement(".waveform-cursor"),this.spectrogramCursor=this.requireElement(".spectrogram-cursor")}get src(){return this.getAttribute("src")??""}set src(t){this.setAttribute("src",t)}get height(){return this.getNumberAttribute("height",this.waveformHeight+this.spectrogramHeight)}set height(t){this.setAttribute("height",String(t))}get waveformHeight(){return this.getNumberAttribute("waveform-height",80)}set waveformHeight(t){this.setAttribute("waveform-height",String(t))}get spectrogramHeight(){return this.getNumberAttribute("spectrogram-height",120)}set spectrogramHeight(t){this.setAttribute("spectrogram-height",String(t))}get showWaveform(){return this.getBooleanAttribute("show-waveform",!0)}set showWaveform(t){this.setBooleanAttribute("show-waveform",t)}get showSpectrogram(){return this.getBooleanAttribute("show-spectrogram",!0)}set showSpectrogram(t){this.setBooleanAttribute("show-spectrogram",t)}get showControls(){return this.getBooleanAttribute("show-controls",!1)}set showControls(t){this.setBooleanAttribute("show-controls",t)}get showTime(){return this.getBooleanAttribute("show-time",!1)}set showTime(t){this.setBooleanAttribute("show-time",t)}get waveformStyle(){const t=this.getAttribute("waveform-style");return t==="line"?"lines":t==="waveform"?"waveform":t==="bars"||t==="lines"||t==="blocks"||t==="dots"?t:"waveform"}set waveformStyle(t){this.setAttribute("waveform-style",t)}get waveformBarWidth(){return this.getOptionalNumberAttribute("waveform-bar-width")}set waveformBarWidth(t){this.setAttribute("waveform-bar-width",String(t))}get waveformBarSpacing(){return this.getOptionalNumberAttribute("waveform-bar-spacing")}set waveformBarSpacing(t){this.setAttribute("waveform-bar-spacing",String(t))}get autoplay(){return this.getBooleanAttribute("autoplay",!1)}set autoplay(t){this.setBooleanAttribute("autoplay",t)}get fftSize(){return this.getNumberAttribute("fft-size",1024)}set fftSize(t){this.setAttribute("fft-size",String(t))}get hopSize(){return this.getNumberAttribute("hop-size",256)}set hopSize(t){this.setAttribute("hop-size",String(t))}get windowType(){const t=this.getAttribute("window-type");return t==="hamming"||t==="rectangular"?t:"hann"}set windowType(t){this.setAttribute("window-type",t)}get minDb(){return this.getNumberAttribute("min-db",-80)}set minDb(t){this.setAttribute("min-db",String(t))}get maxDb(){return this.getNumberAttribute("max-db",0)}set maxDb(t){this.setAttribute("max-db",String(t))}get colorMap(){const t=this.getAttribute("color-map");return t==="gray"||t==="magma"||t==="viridis"||t==="inferno"?t:"audition"}set colorMap(t){this.setAttribute("color-map",t)}get channel(){const t=this.getAttribute("channel");if(!t||t==="mix")return"mix";const r=Number(t);return Number.isInteger(r)?r:"mix"}set channel(t){this.setAttribute("channel",String(t))}connectedCallback(){this.button.addEventListener("click",this.handlePlayButton),this.waveformPane.addEventListener("click",this.handleSeekClick),this.spectrogramPane.addEventListener("click",this.handleSeekClick),this.addEventListener("keydown",this.handleKeydown),this.tabIndex=this.tabIndex>=0?this.tabIndex:0,this.resizeObserver=new ResizeObserver(()=>this.handleResize()),this.resizeObserver.observe(this),this.layoutAndRender(),this.src&&this.load()}disconnectedCallback(){var t,r,i;this.button.removeEventListener("click",this.handlePlayButton),this.waveformPane.removeEventListener("click",this.handleSeekClick),this.spectrogramPane.removeEventListener("click",this.handleSeekClick),this.removeEventListener("keydown",this.handleKeydown),(t=this.resizeObserver)==null||t.disconnect(),this.stopAnimation(),(r=this.worker)==null||r.terminate(),(i=this.audio)==null||i.pause(),this.revokeBlobUrl()}attributeChangedCallback(t,r,i){if(!(r===i||!this.isConnected)){if(t==="src"){this.load();return}if(["fft-size","hop-size","window-type","min-db","max-db","channel"].includes(t)){this.audioBuffer&&this.recomputeAnalysis();return}this.layoutAndRender()}}async load(){var i,s,a;const t=this.src,r=++this.loadingToken;if(this.clearError(),this.setStatus(t?"Loading":""),this.dispatchTypedEvent("loadstart"),this.button.disabled=!0,this.sourceSampleRate=void 0,this.waveformPeaks=void 0,this.waveformPeaksWidth=0,this.spectrogram=void 0,this.layoutAndRender(),(i=this.worker)==null||i.terminate(),(s=this.audio)==null||s.pause(),this.revokeBlobUrl(),!t){this.setStatus("");return}try{const n=performance.now(),h=await Y(t),l=performance.now();if(r!==this.loadingToken)return;this.sourceSampleRate=X(h),this.blobUrl=URL.createObjectURL(new Blob([h])),this.audio=_(this.blobUrl,this.autoplay),this.bindAudio();const u=this.waitForAudioReady(this.audio);this.audioBuffer=await j(h,this.sourceSampleRate);const d=performance.now();if(r!==this.loadingToken)return;const m=Math.max(1,Math.floor(this.getCanvasWidth())),g=performance.now();this.waveformPeaks=this.showWaveform?P(this.audioBuffer,m,this.channel):void 0,this.waveformPeaksWidth=this.waveformPeaks?m:0;const w=performance.now();await u;const v=performance.now();if(r!==this.loadingToken)return;this.button.disabled=!1,this.setStatus(this.showSpectrogram?"Analyzing":""),this.updateTimeLabels(),this.dispatchTypedEvent("loaded");const S=performance.now(),f={fetchMs:l-n,audioReadyMs:v-l,decodeMs:d-l,waveformMs:w-g,firstUsableMs:S-n};this.dispatchEvent(new CustomEvent("profile",{detail:f})),this.layoutAndRender(),this.computeSpectrogramForCurrentBuffer(r,f,n),this.autoplay&&await((a=this.audio)==null?void 0:a.play())}catch(n){if(r!==this.loadingToken)return;this.handleError("Failed to load audio.",n)}}async recomputeAnalysis(){if(!this.audioBuffer)return;const t=Math.max(1,Math.floor(this.getCanvasWidth()));this.waveformPeaks=this.showWaveform?P(this.audioBuffer,t,this.channel):void 0,this.waveformPeaksWidth=this.waveformPeaks?t:0,this.layoutAndRender(),this.showSpectrogram?(this.setStatus("Analyzing"),this.spectrogram=await this.computeSpectrogramInWorker(),this.setStatus("")):this.spectrogram=void 0,this.layoutAndRender()}async computeSpectrogramForCurrentBuffer(t,r,i){if(!this.audioBuffer||!this.showSpectrogram){this.spectrogram=void 0,this.setStatus(""),this.layoutAndRender();return}try{const s=performance.now();this.spectrogram=await this.computeSpectrogramInWorker();const a=performance.now();if(t!==this.loadingToken)return;this.setStatus(""),this.layoutAndRender(),this.dispatchEvent(new CustomEvent("profile",{detail:{...r,spectrogramMs:a-s,totalMs:a-i}}))}catch(s){if(t!==this.loadingToken)return;this.spectrogram=void 0,this.setStatus("Spectrogram unavailable"),this.dispatchEvent(new CustomEvent("error",{detail:{message:s instanceof Error?s.message:"Failed to compute spectrogram.",cause:s}}))}}computeSpectrogramInWorker(){if(!this.audioBuffer)return Promise.resolve(void 0);const t=U(this.audioBuffer,this.channel),r={samples:t,sampleRate:this.sourceSampleRate??this.audioBuffer.sampleRate,fftSize:this.fftSize,hopSize:this.hopSize,windowType:this.windowType,minDb:this.minDb,maxDb:this.maxDb};return typeof Worker>"u"?Promise.resolve(it(t,r.sampleRate,r)):new Promise((i,s)=>{var a;(a=this.worker)==null||a.terminate(),this.worker=new Worker(new URL("/assets/spectrogram.worker-CJxyA_5B.js",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:p&&p.tagName.toUpperCase()==="SCRIPT"&&p.src||new URL("index.umd.js",document.baseURI).href),{type:"module"}),this.worker.addEventListener("message",n=>{"error"in n.data?s(new Error(n.data.error.message)):i(n.data)},{once:!0}),this.worker.addEventListener("error",()=>s(new Error("Spectrogram worker failed.")),{once:!0}),this.worker.postMessage(r,[r.samples.buffer])})}bindAudio(){this.audio&&(this.audio.addEventListener("loadedmetadata",this.updateTimeLabels),this.audio.addEventListener("timeupdate",this.handleTimeUpdate),this.audio.addEventListener("play",this.handleAudioPlay),this.audio.addEventListener("playing",this.handleAudioPlaying),this.audio.addEventListener("pause",this.handleAudioPause),this.audio.addEventListener("ended",this.handleAudioPause),this.audio.addEventListener("error",()=>{var t;return this.handleError("Audio playback failed.",(t=this.audio)==null?void 0:t.error)}))}handleResize(){const t=Math.max(1,Math.floor(this.getCanvasWidth()));this.audioBuffer&&this.showWaveform&&t!==this.waveformPeaksWidth?(this.waveformPeaks=P(this.audioBuffer,t,this.channel),this.waveformPeaksWidth=t):this.showWaveform||(this.waveformPeaksWidth=0),this.layoutAndRender()}layoutAndRender(){const t=Math.max(1,Math.floor(this.getCanvasWidth())),{waveformHeight:r,spectrogramHeight:i}=this.getPaneHeights();this.toolbar.classList.toggle("hidden",!this.showControls&&!this.showTime),this.button.classList.toggle("hidden",!this.showControls),this.timeEl.classList.toggle("hidden",!this.showTime),this.waveformPane.classList.toggle("hidden",!this.showWaveform),this.spectrogramPane.classList.toggle("hidden",!this.showSpectrogram),this.showWaveform&&(k(this.waveformCanvas,t,r),k(this.waveformCursor,t,r),z(this.waveformCanvas,this.waveformPeaks,{color:this.cssVar("--ap-waveform","rgba(0, 214, 163, 0.34)"),playedColor:this.cssVar("--ap-waveform-played","#00f0b5"),centerColor:this.cssVar("--ap-waveform-center","rgba(0, 92, 58, 0.7)"),progressColor:this.cssVar("--ap-waveform-progress","#00f0b5"),background:this.cssVar("--ap-waveform-bg","#020604"),style:this.waveformStyle,barWidth:this.waveformBarWidth,barSpacing:this.waveformBarSpacing,progress:this.playbackProgress})),this.showSpectrogram&&(k(this.spectrogramCanvas,t,i),k(this.spectrogramOverlay,t,i),k(this.spectrogramCursor,t,i),nt(this.spectrogramCanvas,this.spectrogram,{colorMap:this.colorMap,background:this.cssVar("--ap-bg","#ffffff"),tickColor:this.cssVar("--ap-spectrogram-tick","rgba(255, 255, 255, 0.42)")}),this.drawSpectrogramOverlay()),this.drawCursors()}drawCursors(){var a;const t=((a=this.audio)==null?void 0:a.currentTime)??0,r=this.duration,i=this.cssVar("--ap-cursor","#ff0000"),s=this.cssVar("--ap-cursor-shadow","rgba(0, 0, 0, 0.45)");this.showWaveform&&this.waveformStyle==="waveform"&&z(this.waveformCanvas,this.waveformPeaks,{color:this.cssVar("--ap-waveform","rgba(0, 214, 163, 0.34)"),playedColor:this.cssVar("--ap-waveform-played","#00f0b5"),centerColor:this.cssVar("--ap-waveform-center","rgba(0, 92, 58, 0.7)"),progressColor:this.cssVar("--ap-waveform-progress","#00f0b5"),background:this.cssVar("--ap-waveform-bg","#020604"),style:this.waveformStyle,barWidth:this.waveformBarWidth,barSpacing:this.waveformBarSpacing,progress:this.playbackProgress}),this.drawSpectrogramOverlay(),this.clearCursor(this.waveformCursor),this.clearCursor(this.spectrogramCursor),this.showWaveform&&D(this.waveformCursor,t,r,i,s),this.showSpectrogram&&D(this.spectrogramCursor,t,r,i,s)}clearCursor(t){const r=t.getContext("2d");if(!r)return;const i=typeof r.getTransform=="function"?r.getTransform():void 0,s=Math.abs((i==null?void 0:i.a)??1)||1,a=Math.abs((i==null?void 0:i.d)??1)||1,n=Math.max(t.clientWidth,t.width/s),h=Math.max(t.clientHeight,t.height/a);r.clearRect(0,0,n,h)}drawSpectrogramOverlay(){const t=this.spectrogramOverlay.getContext("2d");if(!t)return;const r=this.spectrogramOverlay.clientWidth,i=this.spectrogramOverlay.clientHeight;if(t.clearRect(0,0,r,i),!this.showSpectrogram||!this.spectrogram)return;const s=r*this.playbackProgress,a=1-this.cssNumberVar("--ap-spectrogram-unplayed-opacity",.48);s<r&&(t.fillStyle=`rgba(0, 0, 0, ${Math.max(0,Math.min(1,a))})`,t.fillRect(s,0,r-s,i))}startAnimation(){this.stopAnimation();const t=()=>{this.updateTimeLabels(),this.drawCursors(),this.animationFrame=requestAnimationFrame(t)};this.animationFrame=requestAnimationFrame(t)}stopAnimation(){this.animationFrame&&(cancelAnimationFrame(this.animationFrame),this.animationFrame=0)}get duration(){var t,r;return((t=this.audio)==null?void 0:t.duration)||((r=this.audioBuffer)==null?void 0:r.duration)||0}get playbackProgress(){var r;const t=this.duration;return!Number.isFinite(t)||t<=0?0:Math.max(0,Math.min(1,(((r=this.audio)==null?void 0:r.currentTime)??0)/t))}dispatchTypedEvent(t){var i;const r={currentTime:((i=this.audio)==null?void 0:i.currentTime)??0,duration:this.duration};this.dispatchEvent(new CustomEvent(t,{detail:r}))}handleError(t,r){this.button.disabled=!0,this.setStatus("");const i={message:r instanceof Error?`${t} ${r.message}`:t,cause:r};this.errorEl.textContent=i.message,this.errorEl.classList.remove("hidden"),this.dispatchEvent(new CustomEvent("error",{detail:i}))}clearError(){this.errorEl.textContent="",this.errorEl.classList.add("hidden")}setStatus(t){this.statusEl.textContent=t}getCanvasWidth(){return this.clientWidth||this.getBoundingClientRect().width||640}getPaneHeights(){if(!this.showWaveform&&!this.showSpectrogram)return{waveformHeight:0,spectrogramHeight:0};const t=this.hasAttribute("height"),r=this.hasAttribute("waveform-height"),i=this.hasAttribute("spectrogram-height");if(!t)return{waveformHeight:this.showWaveform?this.waveformHeight:0,spectrogramHeight:this.showSpectrogram?this.spectrogramHeight:0};const s=this.height;return this.showWaveform&&!this.showSpectrogram?{waveformHeight:r?this.waveformHeight:s,spectrogramHeight:0}:!this.showWaveform&&this.showSpectrogram?{waveformHeight:0,spectrogramHeight:i?this.spectrogramHeight:s}:r&&i?{waveformHeight:this.waveformHeight,spectrogramHeight:this.spectrogramHeight}:r?{waveformHeight:this.waveformHeight,spectrogramHeight:Math.max(1,s-this.waveformHeight)}:i?{waveformHeight:Math.max(1,s-this.spectrogramHeight),spectrogramHeight:this.spectrogramHeight}:{waveformHeight:Math.max(1,Math.round(s*(80/200))),spectrogramHeight:Math.max(1,s-Math.round(s*(80/200)))}}getNumberAttribute(t,r){const i=Number(this.getAttribute(t));return Number.isFinite(i)&&i>0?i:r}getOptionalNumberAttribute(t){if(!this.hasAttribute(t))return;const r=Number(this.getAttribute(t));return Number.isFinite(r)&&r>0?r:void 0}getBooleanAttribute(t,r){if(!this.hasAttribute(t))return r;const i=this.getAttribute(t);return i===""||i==="true"||i===t}setBooleanAttribute(t,r){r?this.setAttribute(t,""):this.setAttribute(t,"false")}cssVar(t,r){return getComputedStyle(this).getPropertyValue(t).trim()||r}cssNumberVar(t,r){const i=Number(getComputedStyle(this).getPropertyValue(t).trim());return Number.isFinite(i)?i:r}requireElement(t){const r=this.root.querySelector(t);if(!r)throw new Error(`Missing template element: ${t}`);return r}waitForAudioReady(t){return t.readyState>=HTMLMediaElement.HAVE_METADATA?Promise.resolve():new Promise((r,i)=>{const s=()=>{t.removeEventListener("loadedmetadata",a),t.removeEventListener("error",n)},a=()=>{s(),r()},n=()=>{s(),i(t.error??new Error("Audio metadata failed to load."))};t.addEventListener("loadedmetadata",a,{once:!0}),t.addEventListener("error",n,{once:!0}),t.load()})}revokeBlobUrl(){this.blobUrl&&(URL.revokeObjectURL(this.blobUrl),this.blobUrl=void 0)}}c(E,"observedAttributes",["src","height","waveform-height","spectrogram-height","show-waveform","show-spectrogram","show-controls","show-time","waveform-style","waveform-bar-width","waveform-bar-spacing","autoplay","fft-size","hop-size","window-type","min-db","max-db","color-map","channel"]);class V extends E{}customElements.get("wavegram-player")||customElements.define("wavegram-player",E),customElements.get("audio-preview-spectrogram")||customElements.define("audio-preview-spectrogram",V),b.AudioPreviewSpectrogram=V,b.Wavegram=E,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})}));
@@ -1 +1 @@
1
- {"version":3,"file":"drawCursor.d.ts","sourceRoot":"","sources":["../../src/render/drawCursor.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CACxB,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,SAAwB,GAClC,IAAI,CAuBN"}
1
+ {"version":3,"file":"drawCursor.d.ts","sourceRoot":"","sources":["../../src/render/drawCursor.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CACxB,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,SAAwB,GAClC,IAAI,CA0BN"}
@@ -1 +1 @@
1
- {"version":3,"file":"drawWaveform.d.ts","sourceRoot":"","sources":["../../src/render/drawWaveform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,OAAO,EAAE;IACP,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,IAAI,CAqCN"}
1
+ {"version":3,"file":"drawWaveform.d.ts","sourceRoot":"","sources":["../../src/render/drawWaveform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,OAAO,EAAE;IACP,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,IAAI,CAoCN"}
package/dist/types.d.ts CHANGED
@@ -11,6 +11,7 @@ export type SpectrogramData = {
11
11
  freqBins: number;
12
12
  timeFrames: number;
13
13
  sampleRate: number;
14
+ maxFrequencyHz: number;
14
15
  fftSize: number;
15
16
  hopSize: number;
16
17
  minDb: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AACjF,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,CAAC;AAC9C,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE9E,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,YAAY,CAAC;IAClB,GAAG,EAAE,YAAY,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,kBAAkB,GAAG;IAC1D,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AACjF,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,CAAC;AAC9C,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE9E,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,YAAY,CAAC;IAClB,GAAG,EAAE,YAAY,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,kBAAkB,GAAG;IAC1D,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wavegram",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Lightweight waveform and spectrogram Web Component for audio previews.",
5
5
  "type": "module",
6
6
  "license": "MIT",