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.
- package/LICENSE +21 -0
- package/README.md +198 -0
- package/dist/assets/spectrogram.worker-Burn7NUr.js +1 -0
- package/dist/audio/decodeAudio.d.ts +2 -0
- package/dist/audio/decodeAudio.d.ts.map +1 -0
- package/dist/audio/loadAudio.d.ts +2 -0
- package/dist/audio/loadAudio.d.ts.map +1 -0
- package/dist/audio/playback.d.ts +2 -0
- package/dist/audio/playback.d.ts.map +1 -0
- package/dist/audio/spectrogram.d.ts +8 -0
- package/dist/audio/spectrogram.d.ts.map +1 -0
- package/dist/audio/waveform.d.ts +4 -0
- package/dist/audio/waveform.d.ts.map +1 -0
- package/dist/component/Wavegram.d.ts +108 -0
- package/dist/component/Wavegram.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +1024 -0
- package/dist/index.umd.js +191 -0
- package/dist/render/canvas.d.ts +2 -0
- package/dist/render/canvas.d.ts.map +1 -0
- package/dist/render/colorMap.d.ts +4 -0
- package/dist/render/colorMap.d.ts.map +1 -0
- package/dist/render/drawCursor.d.ts +2 -0
- package/dist/render/drawCursor.d.ts.map +1 -0
- package/dist/render/drawSpectrogram.d.ts +8 -0
- package/dist/render/drawSpectrogram.d.ts.map +1 -0
- package/dist/render/drawWaveform.d.ts +13 -0
- package/dist/render/drawWaveform.d.ts.map +1 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/clamp.d.ts +2 -0
- package/dist/utils/clamp.d.ts.map +1 -0
- package/dist/utils/formatTime.d.ts +2 -0
- package/dist/utils/formatTime.d.ts.map +1 -0
- package/dist/utils/resample.d.ts +2 -0
- package/dist/utils/resample.d.ts.map +1 -0
- package/dist/worker/spectrogram.worker.d.ts +2 -0
- package/dist/worker/spectrogram.worker.d.ts.map +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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
|
+
}
|