@lucaismyname/ginger 0.0.31 → 0.0.34
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 +105 -5
- package/dist/client.cjs +1 -1
- package/dist/client.js +37 -36
- package/dist/client.js.map +1 -1
- package/dist/equalizer/index.cjs +1 -1
- package/dist/equalizer/index.cjs.map +1 -1
- package/dist/equalizer/index.js +16 -15
- package/dist/equalizer/index.js.map +1 -1
- package/dist/hooks/useNextTrackPrefetch.d.ts +3 -0
- package/dist/hooks/useNextTrackPrefetch.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +37 -36
- package/dist/index.js.map +1 -1
- package/dist/liveAudioGraph-0cpHD_Ic.cjs +2 -0
- package/dist/liveAudioGraph-0cpHD_Ic.cjs.map +1 -0
- package/dist/liveAudioGraph-DvPaxBCP.js +105 -0
- package/dist/liveAudioGraph-DvPaxBCP.js.map +1 -0
- package/dist/remote/index.cjs +2 -0
- package/dist/remote/index.cjs.map +1 -0
- package/dist/remote/index.d.ts +5 -0
- package/dist/remote/index.d.ts.map +1 -0
- package/dist/remote/index.js +168 -0
- package/dist/remote/index.js.map +1 -0
- package/dist/remote/remoteProtocol.d.ts +28 -0
- package/dist/remote/remoteProtocol.d.ts.map +1 -0
- package/dist/remote/useGingerRemote.d.ts +35 -0
- package/dist/remote/useGingerRemote.d.ts.map +1 -0
- package/dist/remote/useGingerRemote.test.d.ts +2 -0
- package/dist/remote/useGingerRemote.test.d.ts.map +1 -0
- package/dist/remote/validateGingerInitPayloadDev.d.ts +7 -0
- package/dist/remote/validateGingerInitPayloadDev.d.ts.map +1 -0
- package/dist/remote/validateGingerInitPayloadDev.test.d.ts +2 -0
- package/dist/remote/validateGingerInitPayloadDev.test.d.ts.map +1 -0
- package/dist/spatial/index.cjs +2 -0
- package/dist/spatial/index.cjs.map +1 -0
- package/dist/spatial/index.d.ts +3 -0
- package/dist/spatial/index.d.ts.map +1 -0
- package/dist/spatial/index.js +59 -0
- package/dist/spatial/index.js.map +1 -0
- package/dist/spatial/useGingerSpatialAudio.d.ts +34 -0
- package/dist/spatial/useGingerSpatialAudio.d.ts.map +1 -0
- package/dist/spatial/useGingerSpatialAudio.test.d.ts +2 -0
- package/dist/spatial/useGingerSpatialAudio.test.d.ts.map +1 -0
- package/dist/testing/mockWebAudio.d.ts +14 -0
- package/dist/testing/mockWebAudio.d.ts.map +1 -1
- package/dist/transcript/index.cjs +8 -0
- package/dist/transcript/index.cjs.map +1 -0
- package/dist/transcript/index.d.ts +5 -0
- package/dist/transcript/index.d.ts.map +1 -0
- package/dist/transcript/index.js +99 -0
- package/dist/transcript/index.js.map +1 -0
- package/dist/transcript/parseTranscript.d.ts +27 -0
- package/dist/transcript/parseTranscript.d.ts.map +1 -0
- package/dist/transcript/parseTranscript.test.d.ts +2 -0
- package/dist/transcript/parseTranscript.test.d.ts.map +1 -0
- package/dist/transcript/useGingerTranscriptSync.d.ts +23 -0
- package/dist/transcript/useGingerTranscriptSync.d.ts.map +1 -0
- package/dist/useGinger-BXgia32v.cjs +2 -0
- package/dist/useGinger-BXgia32v.cjs.map +1 -0
- package/dist/useGinger-hpp2pAGY.js +48 -0
- package/dist/useGinger-hpp2pAGY.js.map +1 -0
- package/dist/useGingerChapterProgress-BdaalJvX.cjs +2 -0
- package/dist/useGingerChapterProgress-BdaalJvX.cjs.map +1 -0
- package/dist/{useGingerChapterProgress-DLYdGytK.js → useGingerChapterProgress-CZdv-HiI.js} +23 -22
- package/dist/useGingerChapterProgress-CZdv-HiI.js.map +1 -0
- package/dist/waveform/analyzeAudioFile.d.ts.map +1 -1
- package/dist/waveform/getAudioContextConstructor.d.ts +6 -0
- package/dist/waveform/getAudioContextConstructor.d.ts.map +1 -0
- package/dist/waveform/index.cjs +1 -1
- package/dist/waveform/index.cjs.map +1 -1
- package/dist/waveform/index.js +162 -153
- package/dist/waveform/index.js.map +1 -1
- package/dist/waveform/useAudioFileAnalysis.d.ts +1 -0
- package/dist/waveform/useAudioFileAnalysis.d.ts.map +1 -1
- package/dist/waveform/useAudioPeaks.d.ts.map +1 -1
- package/package.json +17 -2
- package/dist/liveAudioGraph-CmEsdLgZ.js +0 -150
- package/dist/liveAudioGraph-CmEsdLgZ.js.map +0 -1
- package/dist/liveAudioGraph-D1BXMv_u.cjs +0 -2
- package/dist/liveAudioGraph-D1BXMv_u.cjs.map +0 -1
- package/dist/useGingerChapterProgress-BOqUimE7.cjs +0 -2
- package/dist/useGingerChapterProgress-BOqUimE7.cjs.map +0 -1
- package/dist/useGingerChapterProgress-DLYdGytK.js.map +0 -1
package/dist/waveform/index.js
CHANGED
|
@@ -1,233 +1,242 @@
|
|
|
1
|
-
import { useState as
|
|
2
|
-
function
|
|
3
|
-
|
|
1
|
+
import { useState as p, useEffect as y } from "react";
|
|
2
|
+
function x() {
|
|
3
|
+
return typeof window > "u" ? null : window.AudioContext ?? window.webkitAudioContext ?? null;
|
|
4
|
+
}
|
|
5
|
+
function v(n, t = 64) {
|
|
6
|
+
const [a, o] = p({
|
|
4
7
|
peaks: [],
|
|
5
8
|
isLoading: !1,
|
|
6
9
|
error: null
|
|
7
10
|
});
|
|
8
|
-
return
|
|
9
|
-
if (!
|
|
10
|
-
|
|
11
|
+
return y(() => {
|
|
12
|
+
if (!n) {
|
|
13
|
+
o({ peaks: [], isLoading: !1, error: null });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (typeof window > "u") {
|
|
17
|
+
o({ peaks: [], isLoading: !1, error: null });
|
|
11
18
|
return;
|
|
12
19
|
}
|
|
13
|
-
let
|
|
14
|
-
return
|
|
20
|
+
let r = !1;
|
|
21
|
+
return o((e) => ({ ...e, isLoading: !0, error: null })), (async () => {
|
|
15
22
|
try {
|
|
16
|
-
const
|
|
17
|
-
if (!
|
|
18
|
-
throw new Error(`Fetch failed: ${
|
|
19
|
-
const l = await
|
|
23
|
+
const e = await fetch(n);
|
|
24
|
+
if (!e.ok)
|
|
25
|
+
throw new Error(`Fetch failed: ${e.status} ${e.statusText}`);
|
|
26
|
+
const l = await e.arrayBuffer(), s = x();
|
|
27
|
+
if (!s)
|
|
28
|
+
throw new Error("Web Audio API is not available");
|
|
29
|
+
const h = new s();
|
|
20
30
|
try {
|
|
21
|
-
const f = (await
|
|
22
|
-
for (let
|
|
23
|
-
let
|
|
24
|
-
const
|
|
25
|
-
for (let
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
const f = (await h.decodeAudioData(l)).getChannelData(0), i = Math.max(1, Math.floor(f.length / t)), w = [];
|
|
32
|
+
for (let u = 0; u < t; u += 1) {
|
|
33
|
+
let g = 0;
|
|
34
|
+
const m = u * i, d = Math.min(f.length, m + i);
|
|
35
|
+
for (let M = m; M < d; M += 1)
|
|
36
|
+
g = Math.max(g, Math.abs(f[M] ?? 0));
|
|
37
|
+
w.push(g);
|
|
28
38
|
}
|
|
29
|
-
|
|
39
|
+
r || o({ peaks: w, isLoading: !1, error: null });
|
|
30
40
|
} finally {
|
|
31
|
-
await
|
|
41
|
+
await h.close().catch(() => {
|
|
32
42
|
});
|
|
33
43
|
}
|
|
34
|
-
} catch (
|
|
35
|
-
|
|
44
|
+
} catch (e) {
|
|
45
|
+
r || o({
|
|
36
46
|
peaks: [],
|
|
37
47
|
isLoading: !1,
|
|
38
|
-
error:
|
|
48
|
+
error: e instanceof Error ? e.message : "Failed to decode peaks"
|
|
39
49
|
});
|
|
40
50
|
}
|
|
41
51
|
})(), () => {
|
|
42
|
-
|
|
52
|
+
r = !0;
|
|
43
53
|
};
|
|
44
|
-
}, [t,
|
|
54
|
+
}, [t, n]), a;
|
|
45
55
|
}
|
|
46
|
-
function
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
56
|
+
function C(n, t) {
|
|
57
|
+
const a = n.length;
|
|
58
|
+
if (a !== t.length || a < 2 || a & a - 1)
|
|
49
59
|
throw new Error("fftInPlace: length must be equal powers of 2 >= 2");
|
|
50
|
-
let
|
|
51
|
-
for (let
|
|
52
|
-
if (
|
|
53
|
-
const l =
|
|
54
|
-
|
|
60
|
+
let o = 0;
|
|
61
|
+
for (let r = 0; r < a - 1; r += 1) {
|
|
62
|
+
if (r < o) {
|
|
63
|
+
const l = n[r], s = t[r];
|
|
64
|
+
n[r] = n[o], t[r] = t[o], n[o] = l, t[o] = s;
|
|
55
65
|
}
|
|
56
|
-
let
|
|
57
|
-
for (;
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
let e = a >> 1;
|
|
67
|
+
for (; e <= o; )
|
|
68
|
+
o -= e, e >>= 1;
|
|
69
|
+
o += e;
|
|
60
70
|
}
|
|
61
|
-
for (let
|
|
62
|
-
const
|
|
63
|
-
for (let
|
|
64
|
-
let
|
|
65
|
-
const
|
|
66
|
-
for (let
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
const M =
|
|
70
|
-
|
|
71
|
+
for (let r = 2; r <= a; r <<= 1) {
|
|
72
|
+
const e = -2 * Math.PI / r, l = Math.cos(e), s = Math.sin(e);
|
|
73
|
+
for (let h = 0; h < a; h += r) {
|
|
74
|
+
let c = 1, f = 0;
|
|
75
|
+
const i = r >> 1;
|
|
76
|
+
for (let w = 0; w < i; w += 1) {
|
|
77
|
+
const u = h + w, g = u + i, m = c * n[g] - f * t[g], d = c * t[g] + f * n[g];
|
|
78
|
+
n[g] = n[u] - m, t[g] = t[u] - d, n[u] = n[u] + m, t[u] = t[u] + d;
|
|
79
|
+
const M = c * l - f * s, A = c * s + f * l;
|
|
80
|
+
c = M, f = A;
|
|
71
81
|
}
|
|
72
82
|
}
|
|
73
83
|
}
|
|
74
84
|
}
|
|
75
|
-
function
|
|
76
|
-
const t =
|
|
85
|
+
function L(n) {
|
|
86
|
+
const t = n.length;
|
|
77
87
|
if (t < 2 || t & t - 1)
|
|
78
88
|
throw new Error("realFftMagnitudes: length must be a power of 2 >= 2");
|
|
79
|
-
const
|
|
80
|
-
for (let
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
for (let
|
|
84
|
-
|
|
85
|
-
return
|
|
89
|
+
const a = new Float64Array(t), o = new Float64Array(t);
|
|
90
|
+
for (let e = 0; e < t; e += 1) a[e] = n[e];
|
|
91
|
+
C(a, o);
|
|
92
|
+
const r = new Float64Array(t >> 1);
|
|
93
|
+
for (let e = 0; e < t >> 1; e += 1)
|
|
94
|
+
r[e] = Math.hypot(a[e], o[e]);
|
|
95
|
+
return r;
|
|
86
96
|
}
|
|
87
|
-
function
|
|
88
|
-
const t = new Float64Array(
|
|
89
|
-
if (
|
|
97
|
+
function F(n) {
|
|
98
|
+
const t = new Float64Array(n);
|
|
99
|
+
if (n === 1)
|
|
90
100
|
return t[0] = 1, t;
|
|
91
|
-
const
|
|
92
|
-
for (let
|
|
93
|
-
t[
|
|
101
|
+
const a = n - 1;
|
|
102
|
+
for (let o = 0; o < n; o += 1)
|
|
103
|
+
t[o] = 0.5 * (1 - Math.cos(2 * Math.PI * o / a));
|
|
94
104
|
return t;
|
|
95
105
|
}
|
|
96
|
-
function
|
|
97
|
-
const t = 2 ** Math.round(Math.log2(
|
|
106
|
+
function k(n) {
|
|
107
|
+
const t = 2 ** Math.round(Math.log2(n));
|
|
98
108
|
return Math.min(8192, Math.max(32, t));
|
|
99
109
|
}
|
|
100
|
-
function
|
|
101
|
-
const { numberOfChannels: t, length:
|
|
110
|
+
function b(n) {
|
|
111
|
+
const { numberOfChannels: t, length: a } = n;
|
|
102
112
|
if (t === 1)
|
|
103
|
-
return
|
|
104
|
-
const
|
|
105
|
-
for (let
|
|
106
|
-
const l =
|
|
107
|
-
for (let s = 0; s <
|
|
108
|
-
|
|
113
|
+
return n.getChannelData(0);
|
|
114
|
+
const o = new Float32Array(a), r = 1 / t;
|
|
115
|
+
for (let e = 0; e < t; e += 1) {
|
|
116
|
+
const l = n.getChannelData(e);
|
|
117
|
+
for (let s = 0; s < a; s += 1)
|
|
118
|
+
o[s] += l[s] * r;
|
|
109
119
|
}
|
|
110
|
-
return
|
|
120
|
+
return o;
|
|
111
121
|
}
|
|
112
|
-
function
|
|
113
|
-
if (t === "mix") return
|
|
114
|
-
const
|
|
115
|
-
return
|
|
122
|
+
function E(n, t) {
|
|
123
|
+
if (t === "mix") return b(n);
|
|
124
|
+
const a = Math.max(0, Math.min(n.numberOfChannels - 1, t));
|
|
125
|
+
return n.getChannelData(a);
|
|
116
126
|
}
|
|
117
|
-
function
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
127
|
+
function B(n, t, a) {
|
|
128
|
+
const o = [], r = n.length;
|
|
129
|
+
if (r === 0) {
|
|
120
130
|
for (let l = 0; l < t; l += 1)
|
|
121
|
-
|
|
122
|
-
return
|
|
131
|
+
o.push(Array.from({ length: a }, () => 0));
|
|
132
|
+
return o;
|
|
123
133
|
}
|
|
124
|
-
const
|
|
134
|
+
const e = r / t;
|
|
125
135
|
for (let l = 0; l < t; l += 1) {
|
|
126
|
-
const s = [],
|
|
127
|
-
for (let
|
|
128
|
-
const
|
|
136
|
+
const s = [], h = Math.floor(l * e), c = Math.floor((l + 1) * e), i = Math.max(1, c - h) / a;
|
|
137
|
+
for (let w = 0; w < a; w += 1) {
|
|
138
|
+
const u = Math.floor(h + w * i), g = Math.min(c, Math.floor(h + (w + 1) * i));
|
|
129
139
|
let m = 0;
|
|
130
|
-
for (let
|
|
131
|
-
m = Math.max(m, Math.abs(
|
|
140
|
+
for (let d = u; d < g; d += 1)
|
|
141
|
+
m = Math.max(m, Math.abs(n[d] ?? 0));
|
|
132
142
|
s.push(m);
|
|
133
143
|
}
|
|
134
|
-
|
|
144
|
+
o.push(s);
|
|
135
145
|
}
|
|
136
|
-
return
|
|
146
|
+
return o;
|
|
137
147
|
}
|
|
138
|
-
function S(
|
|
139
|
-
const
|
|
140
|
-
let
|
|
141
|
-
const l =
|
|
148
|
+
function S(n, t, a, o) {
|
|
149
|
+
const r = [];
|
|
150
|
+
let e = 1e-12;
|
|
151
|
+
const l = n.length, s = k(a), h = s >> 1, c = Math.min(o, h), f = F(s);
|
|
142
152
|
if (l < s) {
|
|
143
|
-
for (let
|
|
144
|
-
|
|
145
|
-
return { rows:
|
|
153
|
+
for (let i = 0; i < t; i += 1)
|
|
154
|
+
r.push(Array.from({ length: c }, () => 0));
|
|
155
|
+
return { rows: r, maxMag: 1 };
|
|
146
156
|
}
|
|
147
|
-
for (let
|
|
148
|
-
const
|
|
149
|
-
for (let
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
for (let
|
|
153
|
-
const M = d
|
|
154
|
-
m.push(M),
|
|
157
|
+
for (let i = 0; i < t; i += 1) {
|
|
158
|
+
const w = t <= 1 ? 0 : Math.min(Math.floor(i * (l - s) / (t - 1)), l - s), u = new Float64Array(s);
|
|
159
|
+
for (let d = 0; d < s; d += 1)
|
|
160
|
+
u[d] = (n[w + d] ?? 0) * (f[d] ?? 0);
|
|
161
|
+
const g = L(u), m = [];
|
|
162
|
+
for (let d = 0; d < c; d += 1) {
|
|
163
|
+
const M = g[d] ?? 0;
|
|
164
|
+
m.push(M), e = Math.max(e, M);
|
|
155
165
|
}
|
|
156
|
-
|
|
166
|
+
r.push(m);
|
|
157
167
|
}
|
|
158
|
-
return { rows:
|
|
168
|
+
return { rows: r, maxMag: e };
|
|
159
169
|
}
|
|
160
|
-
function
|
|
161
|
-
const
|
|
162
|
-
duration:
|
|
163
|
-
sampleRate:
|
|
164
|
-
amplitudeGrid:
|
|
170
|
+
function P(n, t = {}) {
|
|
171
|
+
const a = Math.max(1, t.timeSlices ?? 128), o = Math.max(1, t.samplesPerSlice ?? 8), r = !!t.spectrogram, e = t.fftSize ?? 1024, l = Math.max(1, t.frequencyBins ?? 256), s = t.channel ?? 0, h = E(n, s), c = B(h, a, o), f = {
|
|
172
|
+
duration: n.duration,
|
|
173
|
+
sampleRate: n.sampleRate,
|
|
174
|
+
amplitudeGrid: c
|
|
165
175
|
};
|
|
166
|
-
if (
|
|
167
|
-
const { rows:
|
|
168
|
-
|
|
176
|
+
if (r) {
|
|
177
|
+
const { rows: i, maxMag: w } = S(h, a, e, l), u = w > 0 ? 1 / w : 1;
|
|
178
|
+
f.spectrogram = i.map((g) => g.map((m) => m * u));
|
|
169
179
|
}
|
|
170
|
-
return
|
|
180
|
+
return f;
|
|
171
181
|
}
|
|
172
|
-
async function z(
|
|
173
|
-
const
|
|
174
|
-
if (!
|
|
175
|
-
throw new Error(`Fetch failed: ${
|
|
176
|
-
const
|
|
177
|
-
if (!
|
|
182
|
+
async function z(n, t = {}) {
|
|
183
|
+
const a = await fetch(n);
|
|
184
|
+
if (!a.ok)
|
|
185
|
+
throw new Error(`Fetch failed: ${a.status} ${a.statusText}`);
|
|
186
|
+
const o = await a.arrayBuffer(), r = x();
|
|
187
|
+
if (!r)
|
|
178
188
|
throw new Error("Web Audio API is not available");
|
|
179
|
-
const
|
|
189
|
+
const e = new r();
|
|
180
190
|
try {
|
|
181
|
-
const l = await
|
|
182
|
-
return
|
|
191
|
+
const l = await e.decodeAudioData(o.slice(0));
|
|
192
|
+
return P(l, t);
|
|
183
193
|
} finally {
|
|
184
|
-
await
|
|
194
|
+
await e.close();
|
|
185
195
|
}
|
|
186
196
|
}
|
|
187
|
-
function
|
|
188
|
-
const
|
|
197
|
+
function D(n, t = {}) {
|
|
198
|
+
const { timeSlices: a, samplesPerSlice: o, spectrogram: r, fftSize: e, frequencyBins: l, channel: s } = t, [h, c] = p({
|
|
189
199
|
data: null,
|
|
190
200
|
isLoading: !1,
|
|
191
201
|
error: null
|
|
192
202
|
});
|
|
193
|
-
return
|
|
194
|
-
if (!
|
|
195
|
-
|
|
203
|
+
return y(() => {
|
|
204
|
+
if (!n) {
|
|
205
|
+
c({ data: null, isLoading: !1, error: null });
|
|
196
206
|
return;
|
|
197
207
|
}
|
|
198
208
|
if (typeof window > "u") {
|
|
199
|
-
|
|
209
|
+
c({ data: null, isLoading: !1, error: null });
|
|
200
210
|
return;
|
|
201
211
|
}
|
|
202
|
-
let
|
|
203
|
-
return
|
|
212
|
+
let f = !1;
|
|
213
|
+
return c((i) => ({ ...i, isLoading: !0, error: null })), (async () => {
|
|
204
214
|
try {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
215
|
+
const i = await z(n, {
|
|
216
|
+
timeSlices: a,
|
|
217
|
+
samplesPerSlice: o,
|
|
218
|
+
spectrogram: r,
|
|
219
|
+
fftSize: e,
|
|
220
|
+
frequencyBins: l,
|
|
221
|
+
channel: s
|
|
222
|
+
});
|
|
223
|
+
f || c({ data: i, isLoading: !1, error: null });
|
|
224
|
+
} catch (i) {
|
|
225
|
+
f || c({
|
|
209
226
|
data: null,
|
|
210
227
|
isLoading: !1,
|
|
211
|
-
error:
|
|
228
|
+
error: i instanceof Error ? i.message : "Failed to analyze audio file"
|
|
212
229
|
});
|
|
213
230
|
}
|
|
214
231
|
})(), () => {
|
|
215
|
-
|
|
232
|
+
f = !0;
|
|
216
233
|
};
|
|
217
|
-
}, [
|
|
218
|
-
a,
|
|
219
|
-
t.timeSlices,
|
|
220
|
-
t.samplesPerSlice,
|
|
221
|
-
t.spectrogram,
|
|
222
|
-
t.fftSize,
|
|
223
|
-
t.frequencyBins,
|
|
224
|
-
t.channel
|
|
225
|
-
]), r;
|
|
234
|
+
}, [n, a, o, r, e, l, s]), h;
|
|
226
235
|
}
|
|
227
236
|
export {
|
|
228
|
-
|
|
237
|
+
P as analyzeAudioBuffer,
|
|
229
238
|
z as analyzeAudioFile,
|
|
230
|
-
|
|
231
|
-
|
|
239
|
+
D as useAudioFileAnalysis,
|
|
240
|
+
v as useAudioPeaks
|
|
232
241
|
};
|
|
233
242
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/waveform/useAudioPeaks.ts","../../src/internal/fft.ts","../../src/waveform/analyzeAudioFile.ts","../../src/waveform/useAudioFileAnalysis.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type UseAudioPeaksState = {\n peaks: number[];\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioPeaks(\n fileUrl: string | null | undefined,\n buckets = 64,\n): UseAudioPeaksState {\n const [state, setState] = useState<UseAudioPeaksState>({\n peaks: [],\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n void (async () => {\n try {\n const response = await fetch(fileUrl);\n if (!response.ok)\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n const buffer = await response.arrayBuffer();\n const audioContext = new AudioContext();\n try {\n const audioBuffer = await audioContext.decodeAudioData(buffer);\n const channel = audioBuffer.getChannelData(0);\n const step = Math.max(1, Math.floor(channel.length / buckets));\n const peaks: number[] = [];\n for (let i = 0; i < buckets; i += 1) {\n let max = 0;\n const start = i * step;\n const end = Math.min(channel.length, start + step);\n for (let j = start; j < end; j += 1) {\n max = Math.max(max, Math.abs(channel[j] ?? 0));\n }\n peaks.push(max);\n }\n if (!cancelled) {\n setState({ peaks, isLoading: false, error: null });\n }\n } finally {\n await audioContext.close().catch(() => {});\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n peaks: [],\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to decode peaks\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [buckets, fileUrl]);\n\n return state;\n}\n","/** In-place radix-2 Cooley–Tukey FFT; `length` must be a power of 2 and >= 2. */\nexport function fftInPlace(re: Float64Array, im: Float64Array): void {\n const n = re.length;\n if (n !== im.length || n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"fftInPlace: length must be equal powers of 2 >= 2\");\n }\n\n let j = 0;\n for (let i = 0; i < n - 1; i += 1) {\n if (i < j) {\n const tr = re[i]!;\n const ti = im[i]!;\n re[i] = re[j]!;\n im[i] = im[j]!;\n re[j] = tr;\n im[j] = ti;\n }\n let k = n >> 1;\n while (k <= j) {\n j -= k;\n k >>= 1;\n }\n j += k;\n }\n\n for (let len = 2; len <= n; len <<= 1) {\n const ang = (-2 * Math.PI) / len;\n const wlenR = Math.cos(ang);\n const wlenI = Math.sin(ang);\n for (let i = 0; i < n; i += len) {\n let wr = 1;\n let wi = 0;\n const half = len >> 1;\n for (let k = 0; k < half; k += 1) {\n const u = i + k;\n const v = u + half;\n const tr = wr * re[v]! - wi * im[v]!;\n const ti = wr * im[v]! + wi * re[v]!;\n re[v] = re[u]! - tr;\n im[v] = im[u]! - ti;\n re[u] = re[u]! + tr;\n im[u] = im[u]! + ti;\n const nwr = wr * wlenR - wi * wlenI;\n const nwi = wr * wlenI + wi * wlenR;\n wr = nwr;\n wi = nwi;\n }\n }\n }\n}\n\n/** Magnitude spectrum for real input: length `n` (power of 2). Returns `n/2` magnitudes for bins 0..n/2-1. */\nexport function realFftMagnitudes(samples: Float64Array): Float64Array {\n const n = samples.length;\n if (n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"realFftMagnitudes: length must be a power of 2 >= 2\");\n }\n const re = new Float64Array(n);\n const im = new Float64Array(n);\n for (let i = 0; i < n; i += 1) re[i] = samples[i]!;\n fftInPlace(re, im);\n const out = new Float64Array(n >> 1);\n for (let k = 0; k < n >> 1; k += 1) {\n out[k] = Math.hypot(re[k]!, im[k]!);\n }\n return out;\n}\n\nexport function hanningWindow(length: number): Float64Array {\n const w = new Float64Array(length);\n if (length === 1) {\n w[0] = 1;\n return w;\n }\n const denom = length - 1;\n for (let i = 0; i < length; i += 1) {\n w[i] = 0.5 * (1 - Math.cos((2 * Math.PI * i) / denom));\n }\n return w;\n}\n\nexport function clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(8192, Math.max(32, p));\n}\n","import { clampFftSize, hanningWindow, realFftMagnitudes } from \"../internal/fft\";\n\nexport type AnalyzeAudioFileOptions = {\n /** Number of time rows in the amplitude grid (and spectrogram if enabled). Default 128. */\n timeSlices?: number;\n /** Sub-buckets per time slice for the amplitude grid. Default 8. */\n samplesPerSlice?: number;\n /** When true, include `spectrogram` using windowed FFT per time slice. Default false. */\n spectrogram?: boolean;\n /** FFT length for spectrogram (power of 2). Default 1024. */\n fftSize?: number;\n /** Number of frequency bins to keep per row (first bins; capped by fftSize/2). Default 256. */\n frequencyBins?: number;\n /** Channel index, or `\"mix\"` for equal mix of all channels. Default 0. */\n channel?: number | \"mix\";\n};\n\nexport type AudioFileAnalysis = {\n duration: number;\n sampleRate: number;\n /** Peak amplitudes in [0, 1]: `timeSlices` rows × `samplesPerSlice` columns. */\n amplitudeGrid: number[][];\n /** Optional magnitude spectrogram rows, each length `frequencyBins`, normalized to [0, 1] globally. */\n spectrogram?: number[][];\n};\n\nfunction mixChannels(buffer: AudioBuffer): Float32Array {\n const { numberOfChannels, length } = buffer;\n if (numberOfChannels === 1) {\n return buffer.getChannelData(0);\n }\n const out = new Float32Array(length);\n const scale = 1 / numberOfChannels;\n for (let c = 0; c < numberOfChannels; c += 1) {\n const ch = buffer.getChannelData(c);\n for (let i = 0; i < length; i += 1) {\n out[i] += ch[i]! * scale;\n }\n }\n return out;\n}\n\nfunction getChannel(buffer: AudioBuffer, channel: number | \"mix\"): Float32Array {\n if (channel === \"mix\") return mixChannels(buffer);\n const idx = Math.max(0, Math.min(buffer.numberOfChannels - 1, channel));\n return buffer.getChannelData(idx);\n}\n\nfunction buildAmplitudeGrid(\n channel: Float32Array,\n timeSlices: number,\n samplesPerSlice: number,\n): number[][] {\n const grid: number[][] = [];\n const len = channel.length;\n if (len === 0) {\n for (let t = 0; t < timeSlices; t += 1) {\n grid.push(Array.from({ length: samplesPerSlice }, () => 0));\n }\n return grid;\n }\n\n const segmentLen = len / timeSlices;\n\n for (let t = 0; t < timeSlices; t += 1) {\n const row: number[] = [];\n const segStart = Math.floor(t * segmentLen);\n const segEnd = Math.floor((t + 1) * segmentLen);\n const segLen = Math.max(1, segEnd - segStart);\n const subLen = segLen / samplesPerSlice;\n\n for (let s = 0; s < samplesPerSlice; s += 1) {\n const a = Math.floor(segStart + s * subLen);\n const b = Math.min(segEnd, Math.floor(segStart + (s + 1) * subLen));\n let peak = 0;\n for (let i = a; i < b; i += 1) {\n peak = Math.max(peak, Math.abs(channel[i] ?? 0));\n }\n row.push(peak);\n }\n grid.push(row);\n }\n return grid;\n}\n\nfunction buildSpectrogram(\n channel: Float32Array,\n timeSlices: number,\n fftSize: number,\n frequencyBins: number,\n): { rows: number[][]; maxMag: number } {\n const rows: number[][] = [];\n let maxMag = 1e-12;\n const len = channel.length;\n const n = clampFftSize(fftSize);\n const half = n >> 1;\n const bins = Math.min(frequencyBins, half);\n const window = hanningWindow(n);\n\n if (len < n) {\n for (let t = 0; t < timeSlices; t += 1) {\n rows.push(Array.from({ length: bins }, () => 0));\n }\n return { rows, maxMag: 1 };\n }\n\n for (let t = 0; t < timeSlices; t += 1) {\n const start =\n timeSlices <= 1 ? 0 : Math.min(Math.floor((t * (len - n)) / (timeSlices - 1)), len - n);\n const frame = new Float64Array(n);\n for (let i = 0; i < n; i += 1) {\n frame[i] = (channel[start + i] ?? 0) * (window[i] ?? 0);\n }\n const mags = realFftMagnitudes(frame);\n const row: number[] = [];\n for (let k = 0; k < bins; k += 1) {\n const v = mags[k] ?? 0;\n row.push(v);\n maxMag = Math.max(maxMag, v);\n }\n rows.push(row);\n }\n\n return { rows, maxMag };\n}\n\n/**\n * Decodes an `AudioBuffer` into visualization-friendly grids (no network).\n */\nexport function analyzeAudioBuffer(\n buffer: AudioBuffer,\n options: AnalyzeAudioFileOptions = {},\n): AudioFileAnalysis {\n const timeSlices = Math.max(1, options.timeSlices ?? 128);\n const samplesPerSlice = Math.max(1, options.samplesPerSlice ?? 8);\n const wantSpec = Boolean(options.spectrogram);\n const fftSize = options.fftSize ?? 1024;\n const frequencyBins = Math.max(1, options.frequencyBins ?? 256);\n const channel = options.channel ?? 0;\n\n const data = getChannel(buffer, channel);\n const amplitudeGrid = buildAmplitudeGrid(data, timeSlices, samplesPerSlice);\n\n const result: AudioFileAnalysis = {\n duration: buffer.duration,\n sampleRate: buffer.sampleRate,\n amplitudeGrid,\n };\n\n if (wantSpec) {\n const { rows, maxMag } = buildSpectrogram(data, timeSlices, fftSize, frequencyBins);\n const norm = maxMag > 0 ? 1 / maxMag : 1;\n result.spectrogram = rows.map((row) => row.map((v) => v * norm));\n }\n\n return result;\n}\n\n/**\n * Fetches a URL, decodes audio to an `AudioBuffer`, runs {@link analyzeAudioBuffer}, then closes the temporary `AudioContext`.\n */\nexport async function analyzeAudioFile(\n fileUrl: string,\n options: AnalyzeAudioFileOptions = {},\n): Promise<AudioFileAnalysis> {\n const response = await fetch(fileUrl);\n if (!response.ok) {\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n }\n const raw = await response.arrayBuffer();\n const Context =\n window.AudioContext ??\n (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const buffer = await audioContext.decodeAudioData(raw.slice(0));\n return analyzeAudioBuffer(buffer, options);\n } finally {\n await audioContext.close();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport {\n type AnalyzeAudioFileOptions,\n type AudioFileAnalysis,\n analyzeAudioFile,\n} from \"./analyzeAudioFile\";\n\nexport type UseAudioFileAnalysisState = {\n data: AudioFileAnalysis | null;\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioFileAnalysis(\n fileUrl: string | null | undefined,\n options: AnalyzeAudioFileOptions = {},\n): UseAudioFileAnalysisState {\n const [state, setState] = useState<UseAudioFileAnalysisState>({\n data: null,\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n\n void (async () => {\n try {\n const data = await analyzeAudioFile(fileUrl, options);\n if (!cancelled) {\n setState({ data, isLoading: false, error: null });\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to analyze audio file\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n fileUrl,\n options.timeSlices,\n options.samplesPerSlice,\n options.spectrogram,\n options.fftSize,\n options.frequencyBins,\n options.channel,\n ]);\n\n return state;\n}\n"],"names":["useAudioPeaks","fileUrl","buckets","state","setState","useState","useEffect","cancelled","prev","response","buffer","audioContext","channel","step","peaks","i","max","start","end","j","error","fftInPlace","re","im","n","tr","ti","k","len","ang","wlenR","wlenI","wr","wi","half","u","v","nwr","nwi","realFftMagnitudes","samples","out","hanningWindow","length","w","denom","clampFftSize","p","mixChannels","numberOfChannels","scale","c","ch","getChannel","idx","buildAmplitudeGrid","timeSlices","samplesPerSlice","grid","t","segmentLen","row","segStart","segEnd","subLen","s","a","b","peak","buildSpectrogram","fftSize","frequencyBins","rows","maxMag","bins","window","frame","mags","analyzeAudioBuffer","options","wantSpec","data","amplitudeGrid","result","norm","analyzeAudioFile","raw","Context","useAudioFileAnalysis"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/waveform/getAudioContextConstructor.ts","../../src/waveform/useAudioPeaks.ts","../../src/internal/fft.ts","../../src/waveform/analyzeAudioFile.ts","../../src/waveform/useAudioFileAnalysis.ts"],"sourcesContent":["/**\n * Resolves the runtime `AudioContext` constructor, including legacy `webkitAudioContext` (Safari).\n * Returns `null` when `window` is unavailable or Web Audio is not implemented.\n */\nexport function getAudioContextConstructor():\n | (new (\n contextOptions?: AudioContextOptions,\n ) => AudioContext)\n | null {\n if (typeof window === \"undefined\") return null;\n const C =\n window.AudioContext ??\n (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n return C ?? null;\n}\n","import { useEffect, useState } from \"react\";\nimport { getAudioContextConstructor } from \"./getAudioContextConstructor\";\n\nexport type UseAudioPeaksState = {\n peaks: number[];\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioPeaks(\n fileUrl: string | null | undefined,\n buckets = 64,\n): UseAudioPeaksState {\n const [state, setState] = useState<UseAudioPeaksState>({\n peaks: [],\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n void (async () => {\n try {\n const response = await fetch(fileUrl);\n if (!response.ok)\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n const buffer = await response.arrayBuffer();\n const Context = getAudioContextConstructor();\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const audioBuffer = await audioContext.decodeAudioData(buffer);\n const channel = audioBuffer.getChannelData(0);\n const step = Math.max(1, Math.floor(channel.length / buckets));\n const peaks: number[] = [];\n for (let i = 0; i < buckets; i += 1) {\n let max = 0;\n const start = i * step;\n const end = Math.min(channel.length, start + step);\n for (let j = start; j < end; j += 1) {\n max = Math.max(max, Math.abs(channel[j] ?? 0));\n }\n peaks.push(max);\n }\n if (!cancelled) {\n setState({ peaks, isLoading: false, error: null });\n }\n } finally {\n await audioContext.close().catch(() => {});\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n peaks: [],\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to decode peaks\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [buckets, fileUrl]);\n\n return state;\n}\n","/** In-place radix-2 Cooley–Tukey FFT; `length` must be a power of 2 and >= 2. */\nexport function fftInPlace(re: Float64Array, im: Float64Array): void {\n const n = re.length;\n if (n !== im.length || n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"fftInPlace: length must be equal powers of 2 >= 2\");\n }\n\n let j = 0;\n for (let i = 0; i < n - 1; i += 1) {\n if (i < j) {\n const tr = re[i]!;\n const ti = im[i]!;\n re[i] = re[j]!;\n im[i] = im[j]!;\n re[j] = tr;\n im[j] = ti;\n }\n let k = n >> 1;\n while (k <= j) {\n j -= k;\n k >>= 1;\n }\n j += k;\n }\n\n for (let len = 2; len <= n; len <<= 1) {\n const ang = (-2 * Math.PI) / len;\n const wlenR = Math.cos(ang);\n const wlenI = Math.sin(ang);\n for (let i = 0; i < n; i += len) {\n let wr = 1;\n let wi = 0;\n const half = len >> 1;\n for (let k = 0; k < half; k += 1) {\n const u = i + k;\n const v = u + half;\n const tr = wr * re[v]! - wi * im[v]!;\n const ti = wr * im[v]! + wi * re[v]!;\n re[v] = re[u]! - tr;\n im[v] = im[u]! - ti;\n re[u] = re[u]! + tr;\n im[u] = im[u]! + ti;\n const nwr = wr * wlenR - wi * wlenI;\n const nwi = wr * wlenI + wi * wlenR;\n wr = nwr;\n wi = nwi;\n }\n }\n }\n}\n\n/** Magnitude spectrum for real input: length `n` (power of 2). Returns `n/2` magnitudes for bins 0..n/2-1. */\nexport function realFftMagnitudes(samples: Float64Array): Float64Array {\n const n = samples.length;\n if (n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"realFftMagnitudes: length must be a power of 2 >= 2\");\n }\n const re = new Float64Array(n);\n const im = new Float64Array(n);\n for (let i = 0; i < n; i += 1) re[i] = samples[i]!;\n fftInPlace(re, im);\n const out = new Float64Array(n >> 1);\n for (let k = 0; k < n >> 1; k += 1) {\n out[k] = Math.hypot(re[k]!, im[k]!);\n }\n return out;\n}\n\nexport function hanningWindow(length: number): Float64Array {\n const w = new Float64Array(length);\n if (length === 1) {\n w[0] = 1;\n return w;\n }\n const denom = length - 1;\n for (let i = 0; i < length; i += 1) {\n w[i] = 0.5 * (1 - Math.cos((2 * Math.PI * i) / denom));\n }\n return w;\n}\n\nexport function clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(8192, Math.max(32, p));\n}\n","import { clampFftSize, hanningWindow, realFftMagnitudes } from \"../internal/fft\";\nimport { getAudioContextConstructor } from \"./getAudioContextConstructor\";\n\nexport type AnalyzeAudioFileOptions = {\n /** Number of time rows in the amplitude grid (and spectrogram if enabled). Default 128. */\n timeSlices?: number;\n /** Sub-buckets per time slice for the amplitude grid. Default 8. */\n samplesPerSlice?: number;\n /** When true, include `spectrogram` using windowed FFT per time slice. Default false. */\n spectrogram?: boolean;\n /** FFT length for spectrogram (power of 2). Default 1024. */\n fftSize?: number;\n /** Number of frequency bins to keep per row (first bins; capped by fftSize/2). Default 256. */\n frequencyBins?: number;\n /** Channel index, or `\"mix\"` for equal mix of all channels. Default 0. */\n channel?: number | \"mix\";\n};\n\nexport type AudioFileAnalysis = {\n duration: number;\n sampleRate: number;\n /** Peak amplitudes in [0, 1]: `timeSlices` rows × `samplesPerSlice` columns. */\n amplitudeGrid: number[][];\n /** Optional magnitude spectrogram rows, each length `frequencyBins`, normalized to [0, 1] globally. */\n spectrogram?: number[][];\n};\n\nfunction mixChannels(buffer: AudioBuffer): Float32Array {\n const { numberOfChannels, length } = buffer;\n if (numberOfChannels === 1) {\n return buffer.getChannelData(0);\n }\n const out = new Float32Array(length);\n const scale = 1 / numberOfChannels;\n for (let c = 0; c < numberOfChannels; c += 1) {\n const ch = buffer.getChannelData(c);\n for (let i = 0; i < length; i += 1) {\n out[i] += ch[i]! * scale;\n }\n }\n return out;\n}\n\nfunction getChannel(buffer: AudioBuffer, channel: number | \"mix\"): Float32Array {\n if (channel === \"mix\") return mixChannels(buffer);\n const idx = Math.max(0, Math.min(buffer.numberOfChannels - 1, channel));\n return buffer.getChannelData(idx);\n}\n\nfunction buildAmplitudeGrid(\n channel: Float32Array,\n timeSlices: number,\n samplesPerSlice: number,\n): number[][] {\n const grid: number[][] = [];\n const len = channel.length;\n if (len === 0) {\n for (let t = 0; t < timeSlices; t += 1) {\n grid.push(Array.from({ length: samplesPerSlice }, () => 0));\n }\n return grid;\n }\n\n const segmentLen = len / timeSlices;\n\n for (let t = 0; t < timeSlices; t += 1) {\n const row: number[] = [];\n const segStart = Math.floor(t * segmentLen);\n const segEnd = Math.floor((t + 1) * segmentLen);\n const segLen = Math.max(1, segEnd - segStart);\n const subLen = segLen / samplesPerSlice;\n\n for (let s = 0; s < samplesPerSlice; s += 1) {\n const a = Math.floor(segStart + s * subLen);\n const b = Math.min(segEnd, Math.floor(segStart + (s + 1) * subLen));\n let peak = 0;\n for (let i = a; i < b; i += 1) {\n peak = Math.max(peak, Math.abs(channel[i] ?? 0));\n }\n row.push(peak);\n }\n grid.push(row);\n }\n return grid;\n}\n\nfunction buildSpectrogram(\n channel: Float32Array,\n timeSlices: number,\n fftSize: number,\n frequencyBins: number,\n): { rows: number[][]; maxMag: number } {\n const rows: number[][] = [];\n let maxMag = 1e-12;\n const len = channel.length;\n const n = clampFftSize(fftSize);\n const half = n >> 1;\n const bins = Math.min(frequencyBins, half);\n const window = hanningWindow(n);\n\n if (len < n) {\n for (let t = 0; t < timeSlices; t += 1) {\n rows.push(Array.from({ length: bins }, () => 0));\n }\n return { rows, maxMag: 1 };\n }\n\n for (let t = 0; t < timeSlices; t += 1) {\n const start =\n timeSlices <= 1 ? 0 : Math.min(Math.floor((t * (len - n)) / (timeSlices - 1)), len - n);\n const frame = new Float64Array(n);\n for (let i = 0; i < n; i += 1) {\n frame[i] = (channel[start + i] ?? 0) * (window[i] ?? 0);\n }\n const mags = realFftMagnitudes(frame);\n const row: number[] = [];\n for (let k = 0; k < bins; k += 1) {\n const v = mags[k] ?? 0;\n row.push(v);\n maxMag = Math.max(maxMag, v);\n }\n rows.push(row);\n }\n\n return { rows, maxMag };\n}\n\n/**\n * Decodes an `AudioBuffer` into visualization-friendly grids (no network).\n */\nexport function analyzeAudioBuffer(\n buffer: AudioBuffer,\n options: AnalyzeAudioFileOptions = {},\n): AudioFileAnalysis {\n const timeSlices = Math.max(1, options.timeSlices ?? 128);\n const samplesPerSlice = Math.max(1, options.samplesPerSlice ?? 8);\n const wantSpec = Boolean(options.spectrogram);\n const fftSize = options.fftSize ?? 1024;\n const frequencyBins = Math.max(1, options.frequencyBins ?? 256);\n const channel = options.channel ?? 0;\n\n const data = getChannel(buffer, channel);\n const amplitudeGrid = buildAmplitudeGrid(data, timeSlices, samplesPerSlice);\n\n const result: AudioFileAnalysis = {\n duration: buffer.duration,\n sampleRate: buffer.sampleRate,\n amplitudeGrid,\n };\n\n if (wantSpec) {\n const { rows, maxMag } = buildSpectrogram(data, timeSlices, fftSize, frequencyBins);\n const norm = maxMag > 0 ? 1 / maxMag : 1;\n result.spectrogram = rows.map((row) => row.map((v) => v * norm));\n }\n\n return result;\n}\n\n/**\n * Fetches a URL, decodes audio to an `AudioBuffer`, runs {@link analyzeAudioBuffer}, then closes the temporary `AudioContext`.\n */\nexport async function analyzeAudioFile(\n fileUrl: string,\n options: AnalyzeAudioFileOptions = {},\n): Promise<AudioFileAnalysis> {\n const response = await fetch(fileUrl);\n if (!response.ok) {\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n }\n const raw = await response.arrayBuffer();\n const Context = getAudioContextConstructor();\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const buffer = await audioContext.decodeAudioData(raw.slice(0));\n return analyzeAudioBuffer(buffer, options);\n } finally {\n await audioContext.close();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport {\n type AnalyzeAudioFileOptions,\n type AudioFileAnalysis,\n analyzeAudioFile,\n} from \"./analyzeAudioFile\";\n\nexport type UseAudioFileAnalysisState = {\n data: AudioFileAnalysis | null;\n isLoading: boolean;\n error: string | null;\n};\n\n/** When extending {@link AnalyzeAudioFileOptions}, thread new fields through the destructuring below and the effect dependency array. */\nexport function useAudioFileAnalysis(\n fileUrl: string | null | undefined,\n options: AnalyzeAudioFileOptions = {},\n): UseAudioFileAnalysisState {\n const { timeSlices, samplesPerSlice, spectrogram, fftSize, frequencyBins, channel } = options;\n\n const [state, setState] = useState<UseAudioFileAnalysisState>({\n data: null,\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n\n void (async () => {\n try {\n const data = await analyzeAudioFile(fileUrl, {\n timeSlices,\n samplesPerSlice,\n spectrogram,\n fftSize,\n frequencyBins,\n channel,\n });\n if (!cancelled) {\n setState({ data, isLoading: false, error: null });\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to analyze audio file\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [fileUrl, timeSlices, samplesPerSlice, spectrogram, fftSize, frequencyBins, channel]);\n\n return state;\n}\n"],"names":["getAudioContextConstructor","useAudioPeaks","fileUrl","buckets","state","setState","useState","useEffect","cancelled","prev","response","buffer","Context","audioContext","channel","step","peaks","i","max","start","end","j","error","fftInPlace","re","im","n","tr","ti","k","len","ang","wlenR","wlenI","wr","wi","half","v","nwr","nwi","realFftMagnitudes","samples","out","hanningWindow","length","w","denom","clampFftSize","p","mixChannels","numberOfChannels","scale","c","ch","getChannel","idx","buildAmplitudeGrid","timeSlices","samplesPerSlice","grid","t","segmentLen","row","segStart","segEnd","subLen","s","a","b","peak","buildSpectrogram","fftSize","frequencyBins","rows","maxMag","bins","window","frame","mags","analyzeAudioBuffer","options","wantSpec","data","amplitudeGrid","result","norm","analyzeAudioFile","raw","useAudioFileAnalysis","spectrogram"],"mappings":"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"}
|
|
@@ -4,5 +4,6 @@ export type UseAudioFileAnalysisState = {
|
|
|
4
4
|
isLoading: boolean;
|
|
5
5
|
error: string | null;
|
|
6
6
|
};
|
|
7
|
+
/** When extending {@link AnalyzeAudioFileOptions}, thread new fields through the destructuring below and the effect dependency array. */
|
|
7
8
|
export declare function useAudioFileAnalysis(fileUrl: string | null | undefined, options?: AnalyzeAudioFileOptions): UseAudioFileAnalysisState;
|
|
8
9
|
//# sourceMappingURL=useAudioFileAnalysis.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioFileAnalysis.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioFileAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,GAAE,uBAA4B,GACpC,yBAAyB,
|
|
1
|
+
{"version":3,"file":"useAudioFileAnalysis.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioFileAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,yIAAyI;AACzI,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,GAAE,uBAA4B,GACpC,yBAAyB,CAoD3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioPeaks.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioPeaks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAudioPeaks.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioPeaks.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,SAAK,GACX,kBAAkB,CAkEpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lucaismyname/ginger",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.34",
|
|
4
4
|
"description": "A headless & batteries-included React audio-player primitive",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"LICENSE",
|
|
10
10
|
"README.md"
|
|
11
11
|
],
|
|
12
|
-
"main": "./dist/index.cjs",
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
13
|
"module": "./dist/index.js",
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"exports": {
|
|
@@ -42,6 +42,21 @@
|
|
|
42
42
|
"types": "./dist/equalizer/index.d.ts",
|
|
43
43
|
"import": "./dist/equalizer/index.js",
|
|
44
44
|
"require": "./dist/equalizer/index.cjs"
|
|
45
|
+
},
|
|
46
|
+
"./spatial": {
|
|
47
|
+
"types": "./dist/spatial/index.d.ts",
|
|
48
|
+
"import": "./dist/spatial/index.js",
|
|
49
|
+
"require": "./dist/spatial/index.cjs"
|
|
50
|
+
},
|
|
51
|
+
"./transcript": {
|
|
52
|
+
"types": "./dist/transcript/index.d.ts",
|
|
53
|
+
"import": "./dist/transcript/index.js",
|
|
54
|
+
"require": "./dist/transcript/index.cjs"
|
|
55
|
+
},
|
|
56
|
+
"./remote": {
|
|
57
|
+
"types": "./dist/remote/index.d.ts",
|
|
58
|
+
"import": "./dist/remote/index.js",
|
|
59
|
+
"require": "./dist/remote/index.cjs"
|
|
45
60
|
}
|
|
46
61
|
},
|
|
47
62
|
"scripts": {
|