@fjandin/react-shader 0.0.15 → 0.0.16

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ReactShader.d.ts","sourceRoot":"","sources":["../src/ReactShader.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAgC/C,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,QAAQ,EACR,MAAuB,EACvB,QAAQ,EACR,UAAkB,EAClB,SAAa,EACb,OAAO,EACP,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,EACT,YAAY,GACb,EAAE,gBAAgB,2CA0DlB"}
1
+ {"version":3,"file":"ReactShader.d.ts","sourceRoot":"","sources":["../src/ReactShader.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAiC/C,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,QAAQ,EACR,MAAuB,EACvB,QAAQ,EACR,UAAkB,EAClB,SAAa,EACb,OAAO,EACP,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,EACT,YAAY,GACb,EAAE,gBAAgB,2CA0DlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../../src/example/frontend.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,aAAa,CAAA;AAiHpB,wBAAgB,GAAG,4CAwGlB"}
1
+ {"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../../src/example/frontend.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,aAAa,CAAA;AAkHpB,wBAAgB,GAAG,4CAiJlB"}
@@ -0,0 +1,3 @@
1
+ import type { UseAudioOptions, UseAudioReturn } from "../types";
2
+ export declare function useAudio(options?: UseAudioOptions): UseAudioReturn;
3
+ //# sourceMappingURL=useAudio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAudio.d.ts","sourceRoot":"","sources":["../../src/hooks/useAudio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqC,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AA6DlG,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,cAAc,CAsMtE"}
package/dist/index.cjs CHANGED
@@ -29,6 +29,7 @@ var __export = (target, all) => {
29
29
  // src/index.ts
30
30
  var exports_src = {};
31
31
  __export(exports_src, {
32
+ useAudio: () => useAudio,
32
33
  generateUtilsFunction: () => generateUtilsFunction,
33
34
  generateSimplexNoiseFunction: () => generateSimplexNoiseFunction,
34
35
  generateSceneCirclesFunction: () => generateSceneCirclesFunction,
@@ -38,11 +39,219 @@ __export(exports_src, {
38
39
  });
39
40
  module.exports = __toCommonJS(exports_src);
40
41
 
42
+ // src/hooks/useAudio.ts
43
+ var import_react = require("react");
44
+ var DEFAULT_FFT_SIZE = 2048;
45
+ var DEFAULT_SMOOTHING_TIME_CONSTANT = 0.8;
46
+ var DEFAULT_SMOOTHING = 0.9;
47
+ var NUM_BANDS = 16;
48
+ var MIN_FREQ = 20;
49
+ var MAX_FREQ = 20000;
50
+ var DEFAULT_BANDS = {
51
+ low: [20, 250],
52
+ mid: [250, 4000],
53
+ high: [4000, 20000]
54
+ };
55
+ var EMPTY_BANDS = Array(NUM_BANDS).fill(0);
56
+ function hzToBin(hz, sampleRate, fftSize) {
57
+ const binFrequency = sampleRate / fftSize;
58
+ return Math.round(hz / binFrequency);
59
+ }
60
+ function calculateBandLevel(data, startBin, endBin) {
61
+ if (startBin >= endBin || startBin >= data.length)
62
+ return 0;
63
+ const clampedStart = Math.max(0, startBin);
64
+ const clampedEnd = Math.min(data.length, endBin);
65
+ let sum = 0;
66
+ for (let i = clampedStart;i < clampedEnd; i++) {
67
+ sum += data[i];
68
+ }
69
+ const count = clampedEnd - clampedStart;
70
+ return count > 0 ? sum / count / 255 : 0;
71
+ }
72
+ function lerp(a, b, t) {
73
+ return a + (b - a) * t;
74
+ }
75
+ function getLogFrequencyBands() {
76
+ const logMin = Math.log10(MIN_FREQ);
77
+ const logMax = Math.log10(MAX_FREQ);
78
+ const step = (logMax - logMin) / NUM_BANDS;
79
+ const frequencies = [];
80
+ for (let i = 0;i <= NUM_BANDS; i++) {
81
+ frequencies.push(10 ** (logMin + step * i));
82
+ }
83
+ return frequencies;
84
+ }
85
+ var LOG_FREQ_BANDS = getLogFrequencyBands();
86
+ function useAudio(options = {}) {
87
+ const {
88
+ source = "microphone",
89
+ mediaElement = null,
90
+ fftSize = DEFAULT_FFT_SIZE,
91
+ smoothingTimeConstant = DEFAULT_SMOOTHING_TIME_CONSTANT,
92
+ smoothing = DEFAULT_SMOOTHING,
93
+ frequencyBands = {}
94
+ } = options;
95
+ const bands = {
96
+ low: frequencyBands.low ?? DEFAULT_BANDS.low,
97
+ mid: frequencyBands.mid ?? DEFAULT_BANDS.mid,
98
+ high: frequencyBands.high ?? DEFAULT_BANDS.high
99
+ };
100
+ const [state, setState] = import_react.useState("disconnected");
101
+ const [error, setError] = import_react.useState(null);
102
+ const [isRunning, setIsRunning] = import_react.useState(false);
103
+ const [levels, setLevels] = import_react.useState({ low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] });
104
+ const [frequencyData, setFrequencyData] = import_react.useState(null);
105
+ const audioStateRef = import_react.useRef(null);
106
+ const animationFrameRef = import_react.useRef(0);
107
+ const dataArrayRef = import_react.useRef(null);
108
+ const smoothedLevelsRef = import_react.useRef({ low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] });
109
+ const analyze = import_react.useCallback(() => {
110
+ const audioState = audioStateRef.current;
111
+ if (!audioState)
112
+ return;
113
+ const { analyser } = audioState;
114
+ const dataArray = dataArrayRef.current;
115
+ if (!dataArray)
116
+ return;
117
+ analyser.getByteFrequencyData(dataArray);
118
+ const sampleRate = audioState.context.sampleRate;
119
+ const fftBins = analyser.fftSize;
120
+ const lowBins = [
121
+ hzToBin(bands.low[0], sampleRate, fftBins),
122
+ hzToBin(bands.low[1], sampleRate, fftBins)
123
+ ];
124
+ const midBins = [
125
+ hzToBin(bands.mid[0], sampleRate, fftBins),
126
+ hzToBin(bands.mid[1], sampleRate, fftBins)
127
+ ];
128
+ const highBins = [
129
+ hzToBin(bands.high[0], sampleRate, fftBins),
130
+ hzToBin(bands.high[1], sampleRate, fftBins)
131
+ ];
132
+ const rawBands = [];
133
+ for (let i = 0;i < NUM_BANDS; i++) {
134
+ const startBin = hzToBin(LOG_FREQ_BANDS[i], sampleRate, fftBins);
135
+ const endBin = hzToBin(LOG_FREQ_BANDS[i + 1], sampleRate, fftBins);
136
+ rawBands.push(calculateBandLevel(dataArray, startBin, endBin));
137
+ }
138
+ const rawLevels = {
139
+ low: calculateBandLevel(dataArray, lowBins[0], lowBins[1]),
140
+ mid: calculateBandLevel(dataArray, midBins[0], midBins[1]),
141
+ high: calculateBandLevel(dataArray, highBins[0], highBins[1]),
142
+ bands: rawBands
143
+ };
144
+ const t = 1 - smoothing;
145
+ const prev = smoothedLevelsRef.current;
146
+ const smoothedBands = rawBands.map((raw, i) => lerp(prev.bands[i] ?? 0, raw, t));
147
+ const smoothedLevels = {
148
+ low: lerp(prev.low, rawLevels.low, t),
149
+ mid: lerp(prev.mid, rawLevels.mid, t),
150
+ high: lerp(prev.high, rawLevels.high, t),
151
+ bands: smoothedBands
152
+ };
153
+ smoothedLevelsRef.current = smoothedLevels;
154
+ setLevels(smoothedLevels);
155
+ const dataCopy = new Uint8Array(dataArray.length);
156
+ dataCopy.set(dataArray);
157
+ setFrequencyData(dataCopy);
158
+ animationFrameRef.current = requestAnimationFrame(analyze);
159
+ }, [bands.low, bands.mid, bands.high, smoothing]);
160
+ const start = import_react.useCallback(async () => {
161
+ if (audioStateRef.current)
162
+ return;
163
+ setState("connecting");
164
+ setError(null);
165
+ try {
166
+ const AudioContextClass = window.AudioContext || window.webkitAudioContext;
167
+ if (!AudioContextClass) {
168
+ throw new Error("AudioContext not supported");
169
+ }
170
+ const context = new AudioContextClass;
171
+ if (context.state === "suspended") {
172
+ await context.resume();
173
+ }
174
+ const analyser = context.createAnalyser();
175
+ analyser.fftSize = fftSize;
176
+ analyser.smoothingTimeConstant = smoothingTimeConstant;
177
+ let audioSource;
178
+ let stream;
179
+ if (source === "microphone") {
180
+ stream = await navigator.mediaDevices.getUserMedia({ audio: true });
181
+ audioSource = context.createMediaStreamSource(stream);
182
+ } else if (source === "display") {
183
+ stream = await navigator.mediaDevices.getDisplayMedia({
184
+ video: true,
185
+ audio: true
186
+ });
187
+ const audioTracks = stream.getAudioTracks();
188
+ if (audioTracks.length === 0) {
189
+ for (const track of stream.getTracks()) {
190
+ track.stop();
191
+ }
192
+ throw new Error("No audio track available. Make sure to share a tab with audio enabled.");
193
+ }
194
+ audioSource = context.createMediaStreamSource(stream);
195
+ } else if (source === "element" && mediaElement) {
196
+ audioSource = context.createMediaElementSource(mediaElement);
197
+ audioSource.connect(context.destination);
198
+ } else {
199
+ throw new Error("Invalid audio source configuration");
200
+ }
201
+ audioSource.connect(analyser);
202
+ audioStateRef.current = {
203
+ context,
204
+ analyser,
205
+ source: audioSource,
206
+ stream
207
+ };
208
+ dataArrayRef.current = new Uint8Array(analyser.frequencyBinCount);
209
+ setState("connected");
210
+ setIsRunning(true);
211
+ animationFrameRef.current = requestAnimationFrame(analyze);
212
+ } catch (err) {
213
+ const audioError = err instanceof Error ? err : new Error(String(err));
214
+ setError(audioError);
215
+ setState("error");
216
+ setIsRunning(false);
217
+ }
218
+ }, [source, mediaElement, fftSize, smoothingTimeConstant, analyze]);
219
+ const stop = import_react.useCallback(() => {
220
+ cancelAnimationFrame(animationFrameRef.current);
221
+ const audioState = audioStateRef.current;
222
+ if (audioState) {
223
+ audioState.source.disconnect();
224
+ if (audioState.stream) {
225
+ for (const track of audioState.stream.getTracks()) {
226
+ track.stop();
227
+ }
228
+ }
229
+ audioState.analyser.disconnect();
230
+ audioState.context.close();
231
+ audioStateRef.current = null;
232
+ }
233
+ dataArrayRef.current = null;
234
+ smoothedLevelsRef.current = { low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] };
235
+ setState("disconnected");
236
+ setIsRunning(false);
237
+ setLevels({ low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] });
238
+ setFrequencyData(null);
239
+ }, []);
240
+ return {
241
+ levels,
242
+ frequencyData,
243
+ state,
244
+ error,
245
+ start,
246
+ stop,
247
+ isRunning
248
+ };
249
+ }
41
250
  // src/ReactShader.tsx
42
- var import_react2 = require("react");
251
+ var import_react3 = require("react");
43
252
 
44
253
  // src/hooks/useWebGL.ts
45
- var import_react = require("react");
254
+ var import_react2 = require("react");
46
255
 
47
256
  // src/utils/shader.ts
48
257
  function compileShader(gl, type, source) {
@@ -407,29 +616,29 @@ function cleanupWebGL(gl, state) {
407
616
  gl.deleteProgram(state.program);
408
617
  }
409
618
  function useWebGL(options) {
410
- const canvasRef = import_react.useRef(null);
411
- const stateRef = import_react.useRef(null);
412
- const animationFrameRef = import_react.useRef(0);
413
- const elapsedTimeRef = import_react.useRef(0);
414
- const lastFrameTimeRef = import_react.useRef(0);
415
- const mouseRef = import_react.useRef([0, 0]);
416
- const mouseNormalizedRef = import_react.useRef([0, 0]);
417
- const mouseLeftDownRef = import_react.useRef(false);
418
- const canvasRectRef = import_react.useRef(null);
419
- const contextLostRef = import_react.useRef(false);
420
- const uniformsRef = import_react.useRef(options.uniforms);
421
- const onErrorRef = import_react.useRef(options.onError);
422
- const onFrameRef = import_react.useRef(options.onFrame);
423
- const onClickRef = import_react.useRef(options.onClick);
424
- const onMouseDownRef = import_react.useRef(options.onMouseDown);
425
- const onMouseUpRef = import_react.useRef(options.onMouseUp);
426
- const onMouseMoveRef = import_react.useRef(options.onMouseMove);
427
- const onMouseWheelRef = import_react.useRef(options.onMouseWheel);
428
- const timeScaleRef = import_react.useRef(options.timeScale ?? 1);
429
- const vertexRef = import_react.useRef(options.vertex);
430
- const fragmentRef = import_react.useRef(options.fragment);
431
- const dprRef = import_react.useRef(window.devicePixelRatio || 1);
432
- const defaultUniformsRef = import_react.useRef({
619
+ const canvasRef = import_react2.useRef(null);
620
+ const stateRef = import_react2.useRef(null);
621
+ const animationFrameRef = import_react2.useRef(0);
622
+ const elapsedTimeRef = import_react2.useRef(0);
623
+ const lastFrameTimeRef = import_react2.useRef(0);
624
+ const mouseRef = import_react2.useRef([0, 0]);
625
+ const mouseNormalizedRef = import_react2.useRef([0, 0]);
626
+ const mouseLeftDownRef = import_react2.useRef(false);
627
+ const canvasRectRef = import_react2.useRef(null);
628
+ const contextLostRef = import_react2.useRef(false);
629
+ const uniformsRef = import_react2.useRef(options.uniforms);
630
+ const onErrorRef = import_react2.useRef(options.onError);
631
+ const onFrameRef = import_react2.useRef(options.onFrame);
632
+ const onClickRef = import_react2.useRef(options.onClick);
633
+ const onMouseDownRef = import_react2.useRef(options.onMouseDown);
634
+ const onMouseUpRef = import_react2.useRef(options.onMouseUp);
635
+ const onMouseMoveRef = import_react2.useRef(options.onMouseMove);
636
+ const onMouseWheelRef = import_react2.useRef(options.onMouseWheel);
637
+ const timeScaleRef = import_react2.useRef(options.timeScale ?? 1);
638
+ const vertexRef = import_react2.useRef(options.vertex);
639
+ const fragmentRef = import_react2.useRef(options.fragment);
640
+ const dprRef = import_react2.useRef(window.devicePixelRatio || 1);
641
+ const defaultUniformsRef = import_react2.useRef({
433
642
  iTime: 0,
434
643
  iMouse: [0, 0],
435
644
  iMouseNormalized: [0, 0],
@@ -447,7 +656,7 @@ function useWebGL(options) {
447
656
  timeScaleRef.current = options.timeScale ?? 1;
448
657
  vertexRef.current = options.vertex;
449
658
  fragmentRef.current = options.fragment;
450
- const render = import_react.useCallback((time) => {
659
+ const render = import_react2.useCallback((time) => {
451
660
  if (contextLostRef.current)
452
661
  return;
453
662
  const state = stateRef.current;
@@ -499,7 +708,7 @@ function useWebGL(options) {
499
708
  }
500
709
  animationFrameRef.current = requestAnimationFrame(render);
501
710
  }, []);
502
- import_react.useEffect(() => {
711
+ import_react2.useEffect(() => {
503
712
  const canvas = canvasRef.current;
504
713
  if (!canvas)
505
714
  return;
@@ -547,7 +756,7 @@ function useWebGL(options) {
547
756
  }
548
757
  };
549
758
  }, [render]);
550
- import_react.useEffect(() => {
759
+ import_react2.useEffect(() => {
551
760
  const canvas = canvasRef.current;
552
761
  if (!canvas)
553
762
  return;
@@ -649,6 +858,7 @@ function useWebGL(options) {
649
858
  // src/ReactShader.tsx
650
859
  var jsx_dev_runtime = require("react/jsx-dev-runtime");
651
860
  var DEFAULT_VERTEX = `#version 300 es
861
+ precision highp float;
652
862
  in vec2 a_position;
653
863
 
654
864
  void main() {
@@ -687,12 +897,12 @@ function ReactShader({
687
897
  onMouseUp,
688
898
  onMouseWheel
689
899
  }) {
690
- const [error, setError] = import_react2.useState(null);
691
- const handleError = import_react2.useCallback((err) => {
900
+ const [error, setError] = import_react3.useState(null);
901
+ const handleError = import_react3.useCallback((err) => {
692
902
  setError(err.message);
693
903
  console.error("ReactShader error:", err);
694
904
  }, []);
695
- import_react2.useEffect(() => {
905
+ import_react3.useEffect(() => {
696
906
  setError(null);
697
907
  }, [fragment, vertex]);
698
908
  const { canvasRef } = useWebGL({
@@ -708,7 +918,7 @@ function ReactShader({
708
918
  onMouseWheel,
709
919
  timeScale
710
920
  });
711
- const containerStyle = import_react2.useMemo(() => fullscreen ? FULLSCREEN_CONTAINER_STYLE : DEFAULT_CONTAINER_STYLE, [fullscreen]);
921
+ const containerStyle = import_react3.useMemo(() => fullscreen ? FULLSCREEN_CONTAINER_STYLE : DEFAULT_CONTAINER_STYLE, [fullscreen]);
712
922
  if (error) {
713
923
  return /* @__PURE__ */ jsx_dev_runtime.jsxDEV("div", {
714
924
  className,
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
+ export { useAudio } from "./hooks/useAudio";
1
2
  export { ReactShader } from "./ReactShader";
2
3
  export { generateColorPaletteFunction } from "./shaders/color-palette";
3
4
  export { generateDistortionRippleFunction } from "./shaders/distortion-ripple";
4
5
  export { generateSceneCirclesFunction } from "./shaders/scene-circles";
5
6
  export { generateSimplexNoiseFunction } from "./shaders/simplex-noise";
6
7
  export { generateUtilsFunction } from "./shaders/utils";
7
- export type { DefaultUniforms, FloatArray, FrameInfo, ReactShaderProps, TextureMagFilter, TextureMinFilter, TextureOptions, TextureSource, TextureWrap, UniformValue, Vec2, Vec2Array, Vec3, Vec3Array, Vec4, Vec4Array, } from "./types";
8
+ export type { AudioConnectionState, AudioLevels, AudioSourceType, DefaultUniforms, FloatArray, FrameInfo, ReactShaderProps, TextureMagFilter, TextureMinFilter, TextureOptions, TextureSource, TextureWrap, UniformValue, UseAudioOptions, UseAudioReturn, Vec2, Vec2Array, Vec3, Vec3Array, Vec4, Vec4Array, } from "./types";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EACV,eAAe,EACf,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,GACV,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,eAAe,EACf,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,SAAS,GACV,MAAM,SAAS,CAAA"}
package/dist/index.js CHANGED
@@ -1,8 +1,216 @@
1
+ // src/hooks/useAudio.ts
2
+ import { useCallback, useRef, useState } from "react";
3
+ var DEFAULT_FFT_SIZE = 2048;
4
+ var DEFAULT_SMOOTHING_TIME_CONSTANT = 0.8;
5
+ var DEFAULT_SMOOTHING = 0.9;
6
+ var NUM_BANDS = 16;
7
+ var MIN_FREQ = 20;
8
+ var MAX_FREQ = 20000;
9
+ var DEFAULT_BANDS = {
10
+ low: [20, 250],
11
+ mid: [250, 4000],
12
+ high: [4000, 20000]
13
+ };
14
+ var EMPTY_BANDS = Array(NUM_BANDS).fill(0);
15
+ function hzToBin(hz, sampleRate, fftSize) {
16
+ const binFrequency = sampleRate / fftSize;
17
+ return Math.round(hz / binFrequency);
18
+ }
19
+ function calculateBandLevel(data, startBin, endBin) {
20
+ if (startBin >= endBin || startBin >= data.length)
21
+ return 0;
22
+ const clampedStart = Math.max(0, startBin);
23
+ const clampedEnd = Math.min(data.length, endBin);
24
+ let sum = 0;
25
+ for (let i = clampedStart;i < clampedEnd; i++) {
26
+ sum += data[i];
27
+ }
28
+ const count = clampedEnd - clampedStart;
29
+ return count > 0 ? sum / count / 255 : 0;
30
+ }
31
+ function lerp(a, b, t) {
32
+ return a + (b - a) * t;
33
+ }
34
+ function getLogFrequencyBands() {
35
+ const logMin = Math.log10(MIN_FREQ);
36
+ const logMax = Math.log10(MAX_FREQ);
37
+ const step = (logMax - logMin) / NUM_BANDS;
38
+ const frequencies = [];
39
+ for (let i = 0;i <= NUM_BANDS; i++) {
40
+ frequencies.push(10 ** (logMin + step * i));
41
+ }
42
+ return frequencies;
43
+ }
44
+ var LOG_FREQ_BANDS = getLogFrequencyBands();
45
+ function useAudio(options = {}) {
46
+ const {
47
+ source = "microphone",
48
+ mediaElement = null,
49
+ fftSize = DEFAULT_FFT_SIZE,
50
+ smoothingTimeConstant = DEFAULT_SMOOTHING_TIME_CONSTANT,
51
+ smoothing = DEFAULT_SMOOTHING,
52
+ frequencyBands = {}
53
+ } = options;
54
+ const bands = {
55
+ low: frequencyBands.low ?? DEFAULT_BANDS.low,
56
+ mid: frequencyBands.mid ?? DEFAULT_BANDS.mid,
57
+ high: frequencyBands.high ?? DEFAULT_BANDS.high
58
+ };
59
+ const [state, setState] = useState("disconnected");
60
+ const [error, setError] = useState(null);
61
+ const [isRunning, setIsRunning] = useState(false);
62
+ const [levels, setLevels] = useState({ low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] });
63
+ const [frequencyData, setFrequencyData] = useState(null);
64
+ const audioStateRef = useRef(null);
65
+ const animationFrameRef = useRef(0);
66
+ const dataArrayRef = useRef(null);
67
+ const smoothedLevelsRef = useRef({ low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] });
68
+ const analyze = useCallback(() => {
69
+ const audioState = audioStateRef.current;
70
+ if (!audioState)
71
+ return;
72
+ const { analyser } = audioState;
73
+ const dataArray = dataArrayRef.current;
74
+ if (!dataArray)
75
+ return;
76
+ analyser.getByteFrequencyData(dataArray);
77
+ const sampleRate = audioState.context.sampleRate;
78
+ const fftBins = analyser.fftSize;
79
+ const lowBins = [
80
+ hzToBin(bands.low[0], sampleRate, fftBins),
81
+ hzToBin(bands.low[1], sampleRate, fftBins)
82
+ ];
83
+ const midBins = [
84
+ hzToBin(bands.mid[0], sampleRate, fftBins),
85
+ hzToBin(bands.mid[1], sampleRate, fftBins)
86
+ ];
87
+ const highBins = [
88
+ hzToBin(bands.high[0], sampleRate, fftBins),
89
+ hzToBin(bands.high[1], sampleRate, fftBins)
90
+ ];
91
+ const rawBands = [];
92
+ for (let i = 0;i < NUM_BANDS; i++) {
93
+ const startBin = hzToBin(LOG_FREQ_BANDS[i], sampleRate, fftBins);
94
+ const endBin = hzToBin(LOG_FREQ_BANDS[i + 1], sampleRate, fftBins);
95
+ rawBands.push(calculateBandLevel(dataArray, startBin, endBin));
96
+ }
97
+ const rawLevels = {
98
+ low: calculateBandLevel(dataArray, lowBins[0], lowBins[1]),
99
+ mid: calculateBandLevel(dataArray, midBins[0], midBins[1]),
100
+ high: calculateBandLevel(dataArray, highBins[0], highBins[1]),
101
+ bands: rawBands
102
+ };
103
+ const t = 1 - smoothing;
104
+ const prev = smoothedLevelsRef.current;
105
+ const smoothedBands = rawBands.map((raw, i) => lerp(prev.bands[i] ?? 0, raw, t));
106
+ const smoothedLevels = {
107
+ low: lerp(prev.low, rawLevels.low, t),
108
+ mid: lerp(prev.mid, rawLevels.mid, t),
109
+ high: lerp(prev.high, rawLevels.high, t),
110
+ bands: smoothedBands
111
+ };
112
+ smoothedLevelsRef.current = smoothedLevels;
113
+ setLevels(smoothedLevels);
114
+ const dataCopy = new Uint8Array(dataArray.length);
115
+ dataCopy.set(dataArray);
116
+ setFrequencyData(dataCopy);
117
+ animationFrameRef.current = requestAnimationFrame(analyze);
118
+ }, [bands.low, bands.mid, bands.high, smoothing]);
119
+ const start = useCallback(async () => {
120
+ if (audioStateRef.current)
121
+ return;
122
+ setState("connecting");
123
+ setError(null);
124
+ try {
125
+ const AudioContextClass = window.AudioContext || window.webkitAudioContext;
126
+ if (!AudioContextClass) {
127
+ throw new Error("AudioContext not supported");
128
+ }
129
+ const context = new AudioContextClass;
130
+ if (context.state === "suspended") {
131
+ await context.resume();
132
+ }
133
+ const analyser = context.createAnalyser();
134
+ analyser.fftSize = fftSize;
135
+ analyser.smoothingTimeConstant = smoothingTimeConstant;
136
+ let audioSource;
137
+ let stream;
138
+ if (source === "microphone") {
139
+ stream = await navigator.mediaDevices.getUserMedia({ audio: true });
140
+ audioSource = context.createMediaStreamSource(stream);
141
+ } else if (source === "display") {
142
+ stream = await navigator.mediaDevices.getDisplayMedia({
143
+ video: true,
144
+ audio: true
145
+ });
146
+ const audioTracks = stream.getAudioTracks();
147
+ if (audioTracks.length === 0) {
148
+ for (const track of stream.getTracks()) {
149
+ track.stop();
150
+ }
151
+ throw new Error("No audio track available. Make sure to share a tab with audio enabled.");
152
+ }
153
+ audioSource = context.createMediaStreamSource(stream);
154
+ } else if (source === "element" && mediaElement) {
155
+ audioSource = context.createMediaElementSource(mediaElement);
156
+ audioSource.connect(context.destination);
157
+ } else {
158
+ throw new Error("Invalid audio source configuration");
159
+ }
160
+ audioSource.connect(analyser);
161
+ audioStateRef.current = {
162
+ context,
163
+ analyser,
164
+ source: audioSource,
165
+ stream
166
+ };
167
+ dataArrayRef.current = new Uint8Array(analyser.frequencyBinCount);
168
+ setState("connected");
169
+ setIsRunning(true);
170
+ animationFrameRef.current = requestAnimationFrame(analyze);
171
+ } catch (err) {
172
+ const audioError = err instanceof Error ? err : new Error(String(err));
173
+ setError(audioError);
174
+ setState("error");
175
+ setIsRunning(false);
176
+ }
177
+ }, [source, mediaElement, fftSize, smoothingTimeConstant, analyze]);
178
+ const stop = useCallback(() => {
179
+ cancelAnimationFrame(animationFrameRef.current);
180
+ const audioState = audioStateRef.current;
181
+ if (audioState) {
182
+ audioState.source.disconnect();
183
+ if (audioState.stream) {
184
+ for (const track of audioState.stream.getTracks()) {
185
+ track.stop();
186
+ }
187
+ }
188
+ audioState.analyser.disconnect();
189
+ audioState.context.close();
190
+ audioStateRef.current = null;
191
+ }
192
+ dataArrayRef.current = null;
193
+ smoothedLevelsRef.current = { low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] };
194
+ setState("disconnected");
195
+ setIsRunning(false);
196
+ setLevels({ low: 0, mid: 0, high: 0, bands: [...EMPTY_BANDS] });
197
+ setFrequencyData(null);
198
+ }, []);
199
+ return {
200
+ levels,
201
+ frequencyData,
202
+ state,
203
+ error,
204
+ start,
205
+ stop,
206
+ isRunning
207
+ };
208
+ }
1
209
  // src/ReactShader.tsx
2
- import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState } from "react";
210
+ import { useCallback as useCallback3, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
3
211
 
4
212
  // src/hooks/useWebGL.ts
5
- import { useCallback, useEffect, useRef } from "react";
213
+ import { useCallback as useCallback2, useEffect, useRef as useRef2 } from "react";
6
214
 
7
215
  // src/utils/shader.ts
8
216
  function compileShader(gl, type, source) {
@@ -367,29 +575,29 @@ function cleanupWebGL(gl, state) {
367
575
  gl.deleteProgram(state.program);
368
576
  }
369
577
  function useWebGL(options) {
370
- const canvasRef = useRef(null);
371
- const stateRef = useRef(null);
372
- const animationFrameRef = useRef(0);
373
- const elapsedTimeRef = useRef(0);
374
- const lastFrameTimeRef = useRef(0);
375
- const mouseRef = useRef([0, 0]);
376
- const mouseNormalizedRef = useRef([0, 0]);
377
- const mouseLeftDownRef = useRef(false);
378
- const canvasRectRef = useRef(null);
379
- const contextLostRef = useRef(false);
380
- const uniformsRef = useRef(options.uniforms);
381
- const onErrorRef = useRef(options.onError);
382
- const onFrameRef = useRef(options.onFrame);
383
- const onClickRef = useRef(options.onClick);
384
- const onMouseDownRef = useRef(options.onMouseDown);
385
- const onMouseUpRef = useRef(options.onMouseUp);
386
- const onMouseMoveRef = useRef(options.onMouseMove);
387
- const onMouseWheelRef = useRef(options.onMouseWheel);
388
- const timeScaleRef = useRef(options.timeScale ?? 1);
389
- const vertexRef = useRef(options.vertex);
390
- const fragmentRef = useRef(options.fragment);
391
- const dprRef = useRef(window.devicePixelRatio || 1);
392
- const defaultUniformsRef = useRef({
578
+ const canvasRef = useRef2(null);
579
+ const stateRef = useRef2(null);
580
+ const animationFrameRef = useRef2(0);
581
+ const elapsedTimeRef = useRef2(0);
582
+ const lastFrameTimeRef = useRef2(0);
583
+ const mouseRef = useRef2([0, 0]);
584
+ const mouseNormalizedRef = useRef2([0, 0]);
585
+ const mouseLeftDownRef = useRef2(false);
586
+ const canvasRectRef = useRef2(null);
587
+ const contextLostRef = useRef2(false);
588
+ const uniformsRef = useRef2(options.uniforms);
589
+ const onErrorRef = useRef2(options.onError);
590
+ const onFrameRef = useRef2(options.onFrame);
591
+ const onClickRef = useRef2(options.onClick);
592
+ const onMouseDownRef = useRef2(options.onMouseDown);
593
+ const onMouseUpRef = useRef2(options.onMouseUp);
594
+ const onMouseMoveRef = useRef2(options.onMouseMove);
595
+ const onMouseWheelRef = useRef2(options.onMouseWheel);
596
+ const timeScaleRef = useRef2(options.timeScale ?? 1);
597
+ const vertexRef = useRef2(options.vertex);
598
+ const fragmentRef = useRef2(options.fragment);
599
+ const dprRef = useRef2(window.devicePixelRatio || 1);
600
+ const defaultUniformsRef = useRef2({
393
601
  iTime: 0,
394
602
  iMouse: [0, 0],
395
603
  iMouseNormalized: [0, 0],
@@ -407,7 +615,7 @@ function useWebGL(options) {
407
615
  timeScaleRef.current = options.timeScale ?? 1;
408
616
  vertexRef.current = options.vertex;
409
617
  fragmentRef.current = options.fragment;
410
- const render = useCallback((time) => {
618
+ const render = useCallback2((time) => {
411
619
  if (contextLostRef.current)
412
620
  return;
413
621
  const state = stateRef.current;
@@ -609,6 +817,7 @@ function useWebGL(options) {
609
817
  // src/ReactShader.tsx
610
818
  import { jsxDEV } from "react/jsx-dev-runtime";
611
819
  var DEFAULT_VERTEX = `#version 300 es
820
+ precision highp float;
612
821
  in vec2 a_position;
613
822
 
614
823
  void main() {
@@ -647,8 +856,8 @@ function ReactShader({
647
856
  onMouseUp,
648
857
  onMouseWheel
649
858
  }) {
650
- const [error, setError] = useState(null);
651
- const handleError = useCallback2((err) => {
859
+ const [error, setError] = useState2(null);
860
+ const handleError = useCallback3((err) => {
652
861
  setError(err.message);
653
862
  console.error("ReactShader error:", err);
654
863
  }, []);
@@ -966,6 +1175,7 @@ function generateUtilsFunction() {
966
1175
  `;
967
1176
  }
968
1177
  export {
1178
+ useAudio,
969
1179
  generateUtilsFunction,
970
1180
  generateSimplexNoiseFunction,
971
1181
  generateSceneCirclesFunction,
package/dist/types.d.ts CHANGED
@@ -47,4 +47,33 @@ export interface DefaultUniforms {
47
47
  iMouseLeftDown: number;
48
48
  iResolution: Vec2;
49
49
  }
50
+ export interface AudioLevels {
51
+ low: number;
52
+ mid: number;
53
+ high: number;
54
+ bands: number[];
55
+ }
56
+ export type AudioSourceType = "microphone" | "element" | "display";
57
+ export type AudioConnectionState = "disconnected" | "connecting" | "connected" | "error";
58
+ export interface UseAudioOptions {
59
+ source?: AudioSourceType;
60
+ mediaElement?: HTMLAudioElement | HTMLVideoElement | null;
61
+ fftSize?: number;
62
+ smoothingTimeConstant?: number;
63
+ smoothing?: number;
64
+ frequencyBands?: Partial<{
65
+ low: [number, number];
66
+ mid: [number, number];
67
+ high: [number, number];
68
+ }>;
69
+ }
70
+ export interface UseAudioReturn {
71
+ levels: AudioLevels;
72
+ frequencyData: Uint8Array<ArrayBuffer> | null;
73
+ state: AudioConnectionState;
74
+ error: Error | null;
75
+ start: () => Promise<void>;
76
+ stop: () => void;
77
+ isRunning: boolean;
78
+ }
50
79
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AACnC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC3C,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAEnD,MAAM,MAAM,UAAU,GAAG,MAAM,EAAE,CAAA;AACjC,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAC9B,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAC9B,MAAM,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;AAE9B,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,iBAAiB,GACjB,gBAAgB,GAChB,WAAW,GACX,SAAS,GACT,eAAe,CAAA;AAEnB,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;AACvD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAC9D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEnD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,aAAa,CAAA;IACrB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,UAAU,GACV,SAAS,GACT,SAAS,GACT,SAAS,GACT,aAAa,GACb,cAAc,CAAA;AAElB,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvB,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,aAAa,EAAE,OAAO,CAAA;CACvB;AACD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACrC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,IAAI,CAAA;IACZ,gBAAgB,EAAE,IAAI,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,IAAI,CAAA;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjandin/react-shader",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "React component for rendering WebGL shaders",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",