wavegram 0.1.0

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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +198 -0
  3. package/dist/assets/spectrogram.worker-Burn7NUr.js +1 -0
  4. package/dist/audio/decodeAudio.d.ts +2 -0
  5. package/dist/audio/decodeAudio.d.ts.map +1 -0
  6. package/dist/audio/loadAudio.d.ts +2 -0
  7. package/dist/audio/loadAudio.d.ts.map +1 -0
  8. package/dist/audio/playback.d.ts +2 -0
  9. package/dist/audio/playback.d.ts.map +1 -0
  10. package/dist/audio/spectrogram.d.ts +8 -0
  11. package/dist/audio/spectrogram.d.ts.map +1 -0
  12. package/dist/audio/waveform.d.ts +4 -0
  13. package/dist/audio/waveform.d.ts.map +1 -0
  14. package/dist/component/Wavegram.d.ts +108 -0
  15. package/dist/component/Wavegram.d.ts.map +1 -0
  16. package/dist/index.d.ts +6 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.es.js +1024 -0
  19. package/dist/index.umd.js +191 -0
  20. package/dist/render/canvas.d.ts +2 -0
  21. package/dist/render/canvas.d.ts.map +1 -0
  22. package/dist/render/colorMap.d.ts +4 -0
  23. package/dist/render/colorMap.d.ts.map +1 -0
  24. package/dist/render/drawCursor.d.ts +2 -0
  25. package/dist/render/drawCursor.d.ts.map +1 -0
  26. package/dist/render/drawSpectrogram.d.ts +8 -0
  27. package/dist/render/drawSpectrogram.d.ts.map +1 -0
  28. package/dist/render/drawWaveform.d.ts +13 -0
  29. package/dist/render/drawWaveform.d.ts.map +1 -0
  30. package/dist/types.d.ts +50 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/utils/clamp.d.ts +2 -0
  33. package/dist/utils/clamp.d.ts.map +1 -0
  34. package/dist/utils/formatTime.d.ts +2 -0
  35. package/dist/utils/formatTime.d.ts.map +1 -0
  36. package/dist/utils/resample.d.ts +2 -0
  37. package/dist/utils/resample.d.ts.map +1 -0
  38. package/dist/worker/spectrogram.worker.d.ts +2 -0
  39. package/dist/worker/spectrogram.worker.d.ts.map +1 -0
  40. package/package.json +54 -0
@@ -0,0 +1,191 @@
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=`
2
+ <style>
3
+ :host {
4
+ --ap-bg: #ffffff;
5
+ --ap-fg: #222222;
6
+ --ap-muted: #666666;
7
+ --ap-waveform-bg: #020604;
8
+ --ap-waveform: rgba(0, 214, 163, 0.34);
9
+ --ap-waveform-played: #00f0b5;
10
+ --ap-waveform-center: rgba(0, 92, 58, 0.7);
11
+ --ap-waveform-progress: #00f0b5;
12
+ --ap-cursor: #00d7ff;
13
+ --ap-cursor-shadow: rgba(0, 0, 0, 0.45);
14
+ --ap-spectrogram-tick: rgba(255, 255, 255, 0.42);
15
+ --ap-spectrogram-unplayed-opacity: 0.48;
16
+ --ap-border: #dddddd;
17
+ --ap-button-bg: #f7f7f7;
18
+ --ap-button-border: #cfcfcf;
19
+ display: block;
20
+ box-sizing: border-box;
21
+ color: var(--ap-fg);
22
+ background: var(--ap-bg);
23
+ font: 13px/1.4 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
24
+ }
25
+
26
+ *, *::before, *::after {
27
+ box-sizing: border-box;
28
+ }
29
+
30
+ .root {
31
+ border: 1px solid var(--ap-border);
32
+ background: var(--ap-bg);
33
+ min-width: 180px;
34
+ }
35
+
36
+ .toolbar {
37
+ display: flex;
38
+ align-items: center;
39
+ gap: 10px;
40
+ padding: 8px;
41
+ border-bottom: 1px solid var(--ap-border);
42
+ min-height: 40px;
43
+ }
44
+
45
+ .toolbar.hidden {
46
+ display: none;
47
+ }
48
+
49
+ button {
50
+ appearance: none;
51
+ border: 1px solid var(--ap-button-border);
52
+ border-radius: 999px;
53
+ background: var(--ap-button-bg);
54
+ color: var(--ap-fg);
55
+ position: relative;
56
+ width: 30px;
57
+ min-width: 30px;
58
+ height: 30px;
59
+ padding: 0;
60
+ cursor: pointer;
61
+ font: inherit;
62
+ text-indent: -9999px;
63
+ overflow: hidden;
64
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
65
+ transition:
66
+ background 120ms ease,
67
+ border-color 120ms ease,
68
+ transform 120ms ease,
69
+ box-shadow 120ms ease;
70
+ }
71
+
72
+ button::before {
73
+ content: "";
74
+ position: absolute;
75
+ left: 50%;
76
+ top: 50%;
77
+ width: 0;
78
+ height: 0;
79
+ border-top: 7px solid transparent;
80
+ border-bottom: 7px solid transparent;
81
+ border-left: 10px solid currentColor;
82
+ transform: translate(-38%, -50%);
83
+ }
84
+
85
+ button[data-state="pause"]::before,
86
+ button[data-state="pause"]::after {
87
+ content: "";
88
+ position: absolute;
89
+ top: 50%;
90
+ width: 4px;
91
+ height: 14px;
92
+ border: 0;
93
+ background: currentColor;
94
+ border-radius: 1px;
95
+ transform: translateY(-50%);
96
+ }
97
+
98
+ button[data-state="pause"]::before {
99
+ left: calc(50% - 5px);
100
+ }
101
+
102
+ button[data-state="pause"]::after {
103
+ left: calc(50% + 1px);
104
+ }
105
+
106
+ button:hover:not(:disabled) {
107
+ transform: translateY(-1px);
108
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.12);
109
+ }
110
+
111
+ button:focus-visible {
112
+ outline: 2px solid var(--ap-cursor);
113
+ outline-offset: 2px;
114
+ }
115
+
116
+ button:disabled {
117
+ cursor: default;
118
+ opacity: 0.55;
119
+ }
120
+
121
+ .time {
122
+ font-variant-numeric: tabular-nums;
123
+ white-space: nowrap;
124
+ }
125
+
126
+ .status {
127
+ color: var(--ap-muted);
128
+ margin-left: auto;
129
+ overflow: hidden;
130
+ text-overflow: ellipsis;
131
+ white-space: nowrap;
132
+ }
133
+
134
+ .error {
135
+ color: #b00020;
136
+ padding: 8px;
137
+ border-bottom: 1px solid var(--ap-border);
138
+ overflow-wrap: anywhere;
139
+ }
140
+
141
+ .hidden {
142
+ display: none;
143
+ }
144
+
145
+ .visuals {
146
+ display: grid;
147
+ width: 100%;
148
+ }
149
+
150
+ .pane {
151
+ position: relative;
152
+ border-top: 1px solid var(--ap-border);
153
+ cursor: pointer;
154
+ user-select: none;
155
+ }
156
+
157
+ .pane:first-child {
158
+ border-top: 0;
159
+ }
160
+
161
+ canvas {
162
+ display: block;
163
+ width: 100%;
164
+ }
165
+
166
+ .cursor {
167
+ position: absolute;
168
+ inset: 0;
169
+ pointer-events: none;
170
+ }
171
+ </style>
172
+ <div class="root">
173
+ <div class="toolbar hidden">
174
+ <button type="button" aria-label="Play" disabled>Play</button>
175
+ <span class="time hidden"><span class="current">00:00.000</span> / <span class="duration">00:00.000</span></span>
176
+ <span class="status"></span>
177
+ </div>
178
+ <div class="error hidden" role="alert"></div>
179
+ <div class="visuals">
180
+ <div class="pane waveform-pane">
181
+ <canvas class="waveform"></canvas>
182
+ <canvas class="cursor waveform-cursor"></canvas>
183
+ </div>
184
+ <div class="pane spectrogram-pane">
185
+ <canvas class="spectrogram"></canvas>
186
+ <canvas class="cursor spectrogram-overlay"></canvas>
187
+ <canvas class="cursor spectrogram-cursor"></canvas>
188
+ </div>
189
+ </div>
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"})}));
@@ -0,0 +1,2 @@
1
+ export declare function configureCanvas(canvas: HTMLCanvasElement, width: number, height: number): CanvasRenderingContext2D;
2
+ //# sourceMappingURL=canvas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../src/render/canvas.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAYlH"}
@@ -0,0 +1,4 @@
1
+ import { ColorMapName } from '../types';
2
+ export type Rgb = [number, number, number];
3
+ export declare function colorMap(name: ColorMapName, value: number): Rgb;
4
+ //# sourceMappingURL=colorMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colorMap.d.ts","sourceRoot":"","sources":["../../src/render/colorMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAgB3C,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,CAuD/D"}
@@ -0,0 +1,2 @@
1
+ export declare function drawCursor(canvas: HTMLCanvasElement, currentTime: number, duration: number, color: string, shadowColor?: string): void;
2
+ //# sourceMappingURL=drawCursor.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,8 @@
1
+ import { ColorMapName, SpectrogramData } from '../types';
2
+ export declare function drawSpectrogram(canvas: HTMLCanvasElement, spectrogram: SpectrogramData | undefined, options: {
3
+ colorMap: ColorMapName;
4
+ background: string;
5
+ tickColor?: string;
6
+ }): void;
7
+ export declare function chooseFrequencyTickStep(nyquistHz: number, height: number): number;
8
+ //# sourceMappingURL=drawSpectrogram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drawSpectrogram.d.ts","sourceRoot":"","sources":["../../src/render/drawSpectrogram.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAI9D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,eAAe,GAAG,SAAS,EACxC,OAAO,EAAE;IACP,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACA,IAAI,CAqCN;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQjF"}
@@ -0,0 +1,13 @@
1
+ import { WaveformPeaks, WaveformStyle } from '../types';
2
+ export declare function drawWaveform(canvas: HTMLCanvasElement, peaks: WaveformPeaks | undefined, options: {
3
+ color: string;
4
+ playedColor?: string;
5
+ background: string;
6
+ centerColor?: string;
7
+ progressColor?: string;
8
+ style?: WaveformStyle;
9
+ barWidth?: number;
10
+ barSpacing?: number;
11
+ progress?: number;
12
+ }): void;
13
+ //# sourceMappingURL=drawWaveform.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,50 @@
1
+ export type WindowType = "hann" | "hamming" | "rectangular";
2
+ export type ColorMapName = "audition" | "gray" | "magma" | "viridis" | "inferno";
3
+ export type ChannelSelection = number | "mix";
4
+ export type WaveformStyle = "waveform" | "bars" | "lines" | "blocks" | "dots";
5
+ export type WaveformPeaks = {
6
+ min: Float32Array;
7
+ max: Float32Array;
8
+ };
9
+ export type SpectrogramData = {
10
+ values: Float32Array;
11
+ freqBins: number;
12
+ timeFrames: number;
13
+ sampleRate: number;
14
+ fftSize: number;
15
+ hopSize: number;
16
+ minDb: number;
17
+ maxDb: number;
18
+ };
19
+ export type SpectrogramOptions = {
20
+ fftSize: number;
21
+ hopSize: number;
22
+ windowType: WindowType;
23
+ minDb: number;
24
+ maxDb: number;
25
+ };
26
+ export type SpectrogramWorkerRequest = SpectrogramOptions & {
27
+ samples: Float32Array;
28
+ sampleRate: number;
29
+ };
30
+ export type PlayerEventDetail = {
31
+ currentTime: number;
32
+ duration: number;
33
+ };
34
+ export type PlayerErrorDetail = {
35
+ message: string;
36
+ cause?: unknown;
37
+ };
38
+ export type LoadProfileDetail = {
39
+ fetchMs: number;
40
+ audioReadyMs: number;
41
+ decodeMs: number;
42
+ waveformMs: number;
43
+ spectrogramMs?: number;
44
+ firstUsableMs: number;
45
+ totalMs?: number;
46
+ };
47
+ export type PlaybackProfileDetail = {
48
+ playToPlayingMs: number;
49
+ };
50
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,2 @@
1
+ export declare function clamp(value: number, min: number, max: number): number;
2
+ //# sourceMappingURL=clamp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clamp.d.ts","sourceRoot":"","sources":["../../src/utils/clamp.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE"}
@@ -0,0 +1,2 @@
1
+ export declare function formatTime(seconds: number): string;
2
+ //# sourceMappingURL=formatTime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatTime.d.ts","sourceRoot":"","sources":["../../src/utils/formatTime.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYlD"}
@@ -0,0 +1,2 @@
1
+ export declare function pickChannel(buffer: AudioBuffer, channel: number | "mix"): Float32Array;
2
+ //# sourceMappingURL=resample.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resample.d.ts","sourceRoot":"","sources":["../../src/utils/resample.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,YAAY,CAiBtF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=spectrogram.worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spectrogram.worker.d.ts","sourceRoot":"","sources":["../../src/worker/spectrogram.worker.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "wavegram",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight waveform and spectrogram Web Component for audio previews.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "taishi-n",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/taishi-n/wavegram.git"
11
+ },
12
+ "homepage": "https://github.com/taishi-n/wavegram#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/taishi-n/wavegram/issues"
15
+ },
16
+ "keywords": [
17
+ "audio",
18
+ "waveform",
19
+ "spectrogram",
20
+ "web-component",
21
+ "canvas",
22
+ "web-audio"
23
+ ],
24
+ "main": "dist/index.umd.js",
25
+ "module": "dist/index.es.js",
26
+ "types": "dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.es.js",
31
+ "default": "./dist/index.umd.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "scripts": {
40
+ "dev": "vite --host 127.0.0.1",
41
+ "build": "tsc -p tsconfig.build.json && vite build",
42
+ "test": "vitest run",
43
+ "test:e2e": "playwright test",
44
+ "typecheck": "tsc --noEmit"
45
+ },
46
+ "devDependencies": {
47
+ "@playwright/test": "^1.54.0",
48
+ "happy-dom": "^17.6.3",
49
+ "typescript": "^5.8.3",
50
+ "vite": "^6.3.5",
51
+ "vite-plugin-dts": "^4.5.4",
52
+ "vitest": "^3.2.4"
53
+ }
54
+ }