Fabriwin commited on
Commit
0122e20
·
verified ·
1 Parent(s): 0fcc469

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1031 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Audio Dimension
3
- emoji: 🔥
4
- colorFrom: yellow
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: audio-dimension
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1031 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Maximalist 3D Audio Visualization</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.min.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/EffectComposer.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/RenderPass.js"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/ShaderPass.js"></script>
13
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/UnrealBloomPass.js"></script>
14
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/CopyShader.js"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/LuminosityHighPassShader.js"></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/SSAOPass.js"></script>
17
+ <style>
18
+ body {
19
+ margin: 0;
20
+ overflow: hidden;
21
+ background: #000;
22
+ color: white;
23
+ font-family: 'Arial', sans-serif;
24
+ }
25
+ #canvas-container {
26
+ position: absolute;
27
+ width: 100%;
28
+ height: 100%;
29
+ }
30
+ #ui {
31
+ position: absolute;
32
+ bottom: 20px;
33
+ left: 20px;
34
+ z-index: 100;
35
+ background: rgba(0, 0, 0, 0.5);
36
+ padding: 15px;
37
+ border-radius: 10px;
38
+ backdrop-filter: blur(5px);
39
+ }
40
+ #audio-controls {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: 10px;
44
+ }
45
+ #file-input {
46
+ display: none;
47
+ }
48
+ .control-btn {
49
+ background: rgba(255, 255, 255, 0.1);
50
+ border: 1px solid rgba(255, 255, 255, 0.2);
51
+ color: white;
52
+ padding: 8px 15px;
53
+ border-radius: 5px;
54
+ cursor: pointer;
55
+ transition: all 0.3s;
56
+ }
57
+ .control-btn:hover {
58
+ background: rgba(255, 255, 255, 0.2);
59
+ }
60
+ .slider-container {
61
+ margin-top: 10px;
62
+ }
63
+ .slider-container label {
64
+ display: block;
65
+ margin-bottom: 5px;
66
+ font-size: 12px;
67
+ }
68
+ .slider {
69
+ width: 100%;
70
+ }
71
+ #loading {
72
+ position: absolute;
73
+ top: 0;
74
+ left: 0;
75
+ width: 100%;
76
+ height: 100%;
77
+ background: #000;
78
+ display: flex;
79
+ justify-content: center;
80
+ align-items: center;
81
+ z-index: 1000;
82
+ flex-direction: column;
83
+ }
84
+ .spinner {
85
+ width: 50px;
86
+ height: 50px;
87
+ border: 5px solid rgba(255, 255, 255, 0.1);
88
+ border-radius: 50%;
89
+ border-top-color: #4f46e5;
90
+ animation: spin 1s ease-in-out infinite;
91
+ margin-bottom: 20px;
92
+ }
93
+ @keyframes spin {
94
+ to { transform: rotate(360deg); }
95
+ }
96
+ #visual-presets {
97
+ margin-top: 15px;
98
+ }
99
+ .preset-btn {
100
+ background: rgba(255, 255, 255, 0.05);
101
+ border: 1px solid rgba(255, 255, 255, 0.1);
102
+ color: white;
103
+ padding: 5px 10px;
104
+ border-radius: 3px;
105
+ cursor: pointer;
106
+ margin-right: 5px;
107
+ font-size: 12px;
108
+ transition: all 0.2s;
109
+ }
110
+ .preset-btn:hover {
111
+ background: rgba(255, 255, 255, 0.2);
112
+ }
113
+ .preset-btn.active {
114
+ background: #4f46e5;
115
+ border-color: #4f46e5;
116
+ }
117
+ </style>
118
+ </head>
119
+ <body>
120
+ <div id="loading">
121
+ <div class="spinner"></div>
122
+ <div>Loading 3D visualization engine...</div>
123
+ </div>
124
+
125
+ <div id="canvas-container"></div>
126
+
127
+ <div id="ui">
128
+ <div id="audio-controls">
129
+ <button id="play-btn" class="control-btn">Play</button>
130
+ <button id="pause-btn" class="control-btn">Pause</button>
131
+ <button id="file-btn" class="control-btn">Load Audio</button>
132
+ <input type="file" id="file-input" accept="audio/*">
133
+ <button id="mic-btn" class="control-btn">Use Microphone</button>
134
+ </div>
135
+
136
+ <div class="slider-container">
137
+ <label for="volume-slider">Volume</label>
138
+ <input type="range" id="volume-slider" class="slider" min="0" max="1" step="0.01" value="0.7">
139
+ </div>
140
+
141
+ <div class="slider-container">
142
+ <label for="bass-slider">Bass Intensity</label>
143
+ <input type="range" id="bass-slider" class="slider" min="0" max="2" step="0.1" value="1">
144
+ </div>
145
+
146
+ <div class="slider-container">
147
+ <label for="mid-slider">Mid Intensity</label>
148
+ <input type="range" id="mid-slider" class="slider" min="0" max="2" step="0.1" value="1">
149
+ </div>
150
+
151
+ <div class="slider-container">
152
+ <label for="high-slider">High Intensity</label>
153
+ <input type="range" id="high-slider" class="slider" min="0" max="2" step="0.1" value="1">
154
+ </div>
155
+
156
+ <div id="visual-presets">
157
+ <div style="margin-bottom: 5px; font-size: 12px;">Visual Presets:</div>
158
+ <button class="preset-btn active" data-preset="default">Neon Geometry</button>
159
+ <button class="preset-btn" data-preset="crystalline">Crystalline</button>
160
+ <button class="preset-btn" data-preset="organic">Organic</button>
161
+ <button class="preset-btn" data-preset="wireframe">Wireframe</button>
162
+ </div>
163
+ </div>
164
+
165
+ <script>
166
+ // Wait for everything to load
167
+ document.addEventListener('DOMContentLoaded', () => {
168
+ setTimeout(() => {
169
+ document.getElementById('loading').style.display = 'none';
170
+ init();
171
+ }, 1500);
172
+ });
173
+
174
+ let scene, camera, renderer, composer, bloomPass, audioContext, analyser, dataArray;
175
+ let bassGroup, midGroup, highGroup, particleSystem, wireframeStructures = [];
176
+ let audioSource, isPlaying = false, currentPreset = 'default';
177
+ let cameraTargets = [];
178
+ let currentCameraTarget = 0;
179
+ let lastCameraChange = 0;
180
+ let cameraControls;
181
+ let clock = new THREE.Clock();
182
+
183
+ // Frequency ranges
184
+ const BASS_RANGE = [20, 140];
185
+ const MID_RANGE = [140, 2000];
186
+ const HIGH_RANGE = [2000, 20000];
187
+
188
+ // Color palettes for different presets
189
+ const colorPalettes = {
190
+ default: {
191
+ bass: [0x4f46e5, 0x8b5cf6, 0xa78bfa],
192
+ mid: [0xec4899, 0xf472b6, 0xf9a8d4],
193
+ high: [0x10b981, 0x34d399, 0x6ee7b7],
194
+ particles: [0xffffff, 0xfacc15, 0xf472b6],
195
+ wireframe: 0x4f46e5,
196
+ ambient: 0x111827
197
+ },
198
+ crystalline: {
199
+ bass: [0x3b82f6, 0x60a5fa, 0x93c5fd],
200
+ mid: [0x06b6d4, 0x22d3ee, 0x67e8f9],
201
+ high: [0xa855f7, 0xc084fc, 0xd8b4fe],
202
+ particles: [0xffffff, 0xe0e7ff, 0xbfdbfe],
203
+ wireframe: 0x3b82f6,
204
+ ambient: 0x0c1a32
205
+ },
206
+ organic: {
207
+ bass: [0x10b981, 0x34d399, 0x6ee7b7],
208
+ mid: [0xf59e0b, 0xfbbf24, 0xfcd34d],
209
+ high: [0xef4444, 0xf87171, 0xfca5a5],
210
+ particles: [0xffffff, 0xfef3c7, 0xfecaca],
211
+ wireframe: 0x10b981,
212
+ ambient: 0x1c1917
213
+ },
214
+ wireframe: {
215
+ bass: [0xffffff, 0xe5e7eb, 0xd1d5db],
216
+ mid: [0xffffff, 0xe5e7eb, 0xd1d5db],
217
+ high: [0xffffff, 0xe5e7eb, 0xd1d5db],
218
+ particles: [0xffffff, 0xe5e7eb, 0xd1d5db],
219
+ wireframe: 0xffffff,
220
+ ambient: 0x000000
221
+ }
222
+ };
223
+
224
+ function init() {
225
+ // Create scene
226
+ scene = new THREE.Scene();
227
+ scene.background = new THREE.Color(0x000000);
228
+ scene.fog = new THREE.FogExp2(0x000000, 0.002);
229
+
230
+ // Create camera
231
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
232
+ camera.position.set(0, 0, 30);
233
+
234
+ // Create renderer with antialiasing
235
+ renderer = new THREE.WebGLRenderer({ antialias: true });
236
+ renderer.setPixelRatio(window.devicePixelRatio);
237
+ renderer.setSize(window.innerWidth, window.innerHeight);
238
+ renderer.shadowMap.enabled = true;
239
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
240
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
241
+ renderer.toneMappingExposure = 1.5;
242
+ document.getElementById('canvas-container').appendChild(renderer.domElement);
243
+
244
+ // Post-processing setup
245
+ composer = new THREE.EffectComposer(renderer);
246
+ const renderPass = new THREE.RenderPass(scene, camera);
247
+ composer.addPass(renderPass);
248
+
249
+ bloomPass = new THREE.UnrealBloomPass(
250
+ new THREE.Vector2(window.innerWidth, window.innerHeight),
251
+ 1.5, 0.4, 0.85
252
+ );
253
+ composer.addPass(bloomPass);
254
+
255
+ // Camera controls
256
+ cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
257
+ cameraControls.enableDamping = true;
258
+ cameraControls.dampingFactor = 0.05;
259
+ cameraControls.screenSpacePanning = false;
260
+ cameraControls.maxPolarAngle = Math.PI;
261
+ cameraControls.minDistance = 10;
262
+ cameraControls.maxDistance = 100;
263
+
264
+ // Setup lights
265
+ setupLights();
266
+
267
+ // Create audio visualizer elements
268
+ createVisualizerElements();
269
+
270
+ // Setup camera targets
271
+ setupCameraTargets();
272
+
273
+ // Setup event listeners
274
+ setupEventListeners();
275
+
276
+ // Start animation loop
277
+ animate();
278
+
279
+ // Initialize Web Audio API
280
+ initAudio();
281
+ }
282
+
283
+ function setupLights() {
284
+ // Ambient light
285
+ const ambientLight = new THREE.AmbientLight(colorPalettes[currentPreset].ambient, 0.2);
286
+ scene.add(ambientLight);
287
+
288
+ // Directional light
289
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
290
+ directionalLight.position.set(1, 1, 1);
291
+ directionalLight.castShadow = true;
292
+ directionalLight.shadow.mapSize.width = 2048;
293
+ directionalLight.shadow.mapSize.height = 2048;
294
+ directionalLight.shadow.camera.near = 0.5;
295
+ directionalLight.shadow.camera.far = 500;
296
+ directionalLight.shadow.camera.left = -50;
297
+ directionalLight.shadow.camera.right = 50;
298
+ directionalLight.shadow.camera.top = 50;
299
+ directionalLight.shadow.camera.bottom = -50;
300
+ scene.add(directionalLight);
301
+
302
+ // Point lights
303
+ const pointLight1 = new THREE.PointLight(0xff00ff, 1, 50);
304
+ pointLight1.position.set(20, 20, 20);
305
+ scene.add(pointLight1);
306
+
307
+ const pointLight2 = new THREE.PointLight(0x00ffff, 1, 50);
308
+ pointLight2.position.set(-20, -20, 20);
309
+ scene.add(pointLight2);
310
+
311
+ // Hemisphere light
312
+ const hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.5);
313
+ scene.add(hemisphereLight);
314
+ }
315
+
316
+ function createVisualizerElements() {
317
+ // Create groups for different frequency ranges
318
+ bassGroup = new THREE.Group();
319
+ midGroup = new THREE.Group();
320
+ highGroup = new THREE.Group();
321
+ scene.add(bassGroup, midGroup, highGroup);
322
+
323
+ // Create bass elements (large geometric forms)
324
+ createBassElements();
325
+
326
+ // Create mid elements (medium geometric forms)
327
+ createMidElements();
328
+
329
+ // Create high elements (small geometric forms and particles)
330
+ createHighElements();
331
+
332
+ // Create particle system
333
+ createParticleSystem();
334
+
335
+ // Create wireframe structures
336
+ createWireframeStructures();
337
+
338
+ // Create floating crystalline structures
339
+ createCrystallineStructures();
340
+
341
+ // Create organic morphing forms
342
+ createOrganicForms();
343
+ }
344
+
345
+ function createBassElements() {
346
+ // Large central dodecahedron
347
+ const geometry = new THREE.DodecahedronGeometry(5, 0);
348
+ const material = new THREE.MeshPhysicalMaterial({
349
+ color: colorPalettes[currentPreset].bass[0],
350
+ metalness: 0.8,
351
+ roughness: 0.2,
352
+ clearcoat: 1,
353
+ clearcoatRoughness: 0.1,
354
+ transmission: 0.5,
355
+ ior: 1.5,
356
+ envMapIntensity: 1,
357
+ emissive: colorPalettes[currentPreset].bass[0],
358
+ emissiveIntensity: 0.2
359
+ });
360
+ const mesh = new THREE.Mesh(geometry, material);
361
+ mesh.castShadow = true;
362
+ mesh.receiveShadow = true;
363
+ bassGroup.add(mesh);
364
+
365
+ // Surrounding icosahedrons
366
+ for (let i = 0; i < 6; i++) {
367
+ const angle = (i / 6) * Math.PI * 2;
368
+ const radius = 8 + Math.random() * 2;
369
+ const x = Math.cos(angle) * radius;
370
+ const y = Math.sin(angle) * radius;
371
+
372
+ const geo = new THREE.IcosahedronGeometry(2 + Math.random(), 1);
373
+ const mat = new THREE.MeshPhysicalMaterial({
374
+ color: colorPalettes[currentPreset].bass[1 + Math.floor(Math.random() * 2)],
375
+ metalness: 0.7,
376
+ roughness: 0.3,
377
+ clearcoat: 0.5,
378
+ emissive: colorPalettes[currentPreset].bass[1 + Math.floor(Math.random() * 2)],
379
+ emissiveIntensity: 0.1
380
+ });
381
+ const icosa = new THREE.Mesh(geo, mat);
382
+ icosa.position.set(x, y, 0);
383
+ icosa.castShadow = true;
384
+ icosa.receiveShadow = true;
385
+ bassGroup.add(icosa);
386
+ }
387
+ }
388
+
389
+ function createMidElements() {
390
+ // Torus knots
391
+ for (let i = 0; i < 12; i++) {
392
+ const angle = (i / 12) * Math.PI * 2;
393
+ const radius = 12 + Math.random() * 3;
394
+ const x = Math.cos(angle) * radius;
395
+ const y = Math.sin(angle) * radius;
396
+ const z = (Math.random() - 0.5) * 10;
397
+
398
+ const geo = new THREE.TorusKnotGeometry(
399
+ 1 + Math.random() * 0.5,
400
+ 0.3 + Math.random() * 0.2,
401
+ 100, 16
402
+ );
403
+ const mat = new THREE.MeshPhysicalMaterial({
404
+ color: colorPalettes[currentPreset].mid[i % colorPalettes[currentPreset].mid.length],
405
+ metalness: 0.6,
406
+ roughness: 0.4,
407
+ clearcoat: 0.7,
408
+ emissive: colorPalettes[currentPreset].mid[i % colorPalettes[currentPreset].mid.length],
409
+ emissiveIntensity: 0.2
410
+ });
411
+ const torus = new THREE.Mesh(geo, mat);
412
+ torus.position.set(x, y, z);
413
+ torus.castShadow = true;
414
+ torus.receiveShadow = true;
415
+ midGroup.add(torus);
416
+ }
417
+ }
418
+
419
+ function createHighElements() {
420
+ // Small spheres
421
+ for (let i = 0; i < 24; i++) {
422
+ const angle = (i / 24) * Math.PI * 2;
423
+ const radius = 15 + Math.random() * 5;
424
+ const x = Math.cos(angle) * radius;
425
+ const y = Math.sin(angle) * radius;
426
+ const z = (Math.random() - 0.5) * 15;
427
+
428
+ const geo = new THREE.SphereGeometry(0.5 + Math.random() * 0.3, 16, 16);
429
+ const mat = new THREE.MeshPhysicalMaterial({
430
+ color: colorPalettes[currentPreset].high[i % colorPalettes[currentPreset].high.length],
431
+ metalness: 0.5,
432
+ roughness: 0.5,
433
+ clearcoat: 0.8,
434
+ emissive: colorPalettes[currentPreset].high[i % colorPalettes[currentPreset].high.length],
435
+ emissiveIntensity: 0.3
436
+ });
437
+ const sphere = new THREE.Mesh(geo, mat);
438
+ sphere.position.set(x, y, z);
439
+ sphere.castShadow = true;
440
+ sphere.receiveShadow = true;
441
+ highGroup.add(sphere);
442
+ }
443
+ }
444
+
445
+ function createParticleSystem() {
446
+ const particleCount = 2000;
447
+ const particles = new THREE.BufferGeometry();
448
+ const positions = new Float32Array(particleCount * 3);
449
+ const colors = new Float32Array(particleCount * 3);
450
+ const sizes = new Float32Array(particleCount);
451
+
452
+ for (let i = 0; i < particleCount; i++) {
453
+ // Positions
454
+ const radius = 5 + Math.random() * 20;
455
+ const theta = Math.random() * Math.PI * 2;
456
+ const phi = Math.acos(2 * Math.random() - 1);
457
+
458
+ positions[i * 3] = radius * Math.sin(phi) * Math.cos(theta);
459
+ positions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
460
+ positions[i * 3 + 2] = radius * Math.cos(phi);
461
+
462
+ // Colors
463
+ const colorIndex = Math.floor(Math.random() * colorPalettes[currentPreset].particles.length);
464
+ const color = new THREE.Color(colorPalettes[currentPreset].particles[colorIndex]);
465
+ colors[i * 3] = color.r;
466
+ colors[i * 3 + 1] = color.g;
467
+ colors[i * 3 + 2] = color.b;
468
+
469
+ // Sizes
470
+ sizes[i] = 0.1 + Math.random() * 0.5;
471
+ }
472
+
473
+ particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
474
+ particles.setAttribute('color', new THREE.BufferAttribute(colors, 3));
475
+ particles.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
476
+
477
+ const particleMaterial = new THREE.PointsMaterial({
478
+ size: 0.2,
479
+ vertexColors: true,
480
+ transparent: true,
481
+ opacity: 0.8,
482
+ blending: THREE.AdditiveBlending,
483
+ sizeAttenuation: true
484
+ });
485
+
486
+ particleSystem = new THREE.Points(particles, particleMaterial);
487
+ scene.add(particleSystem);
488
+ }
489
+
490
+ function createWireframeStructures() {
491
+ // Create several complex wireframe structures
492
+ for (let i = 0; i < 5; i++) {
493
+ const group = new THREE.Group();
494
+
495
+ // Create a base shape
496
+ let geometry;
497
+ switch (i % 3) {
498
+ case 0:
499
+ geometry = new THREE.OctahedronGeometry(3 + Math.random() * 2, 1);
500
+ break;
501
+ case 1:
502
+ geometry = new THREE.TorusKnotGeometry(2 + Math.random(), 0.5, 100, 16);
503
+ break;
504
+ case 2:
505
+ geometry = new THREE.IcosahedronGeometry(3 + Math.random(), 1);
506
+ break;
507
+ }
508
+
509
+ // Convert to wireframe
510
+ const wireframe = new THREE.LineSegments(
511
+ new THREE.WireframeGeometry(geometry),
512
+ new THREE.LineBasicMaterial({
513
+ color: colorPalettes[currentPreset].wireframe,
514
+ transparent: true,
515
+ opacity: 0.6,
516
+ linewidth: 2
517
+ })
518
+ );
519
+
520
+ // Position randomly
521
+ wireframe.position.x = (Math.random() - 0.5) * 30;
522
+ wireframe.position.y = (Math.random() - 0.5) * 30;
523
+ wireframe.position.z = (Math.random() - 0.5) * 30;
524
+
525
+ // Random rotation
526
+ wireframe.rotation.x = Math.random() * Math.PI;
527
+ wireframe.rotation.y = Math.random() * Math.PI;
528
+
529
+ group.add(wireframe);
530
+ scene.add(group);
531
+ wireframeStructures.push(group);
532
+ }
533
+ }
534
+
535
+ function createCrystallineStructures() {
536
+ // Create several crystalline structures
537
+ for (let i = 0; i < 8; i++) {
538
+ const group = new THREE.Group();
539
+
540
+ // Create a cluster of crystals
541
+ const crystalCount = 3 + Math.floor(Math.random() * 5);
542
+ for (let j = 0; j < crystalCount; j++) {
543
+ const height = 1 + Math.random() * 2;
544
+ const radius = 0.3 + Math.random() * 0.5;
545
+ const sides = 4 + Math.floor(Math.random() * 3) * 2; // 4, 6 or 8 sides
546
+
547
+ const geometry = new THREE.CylinderGeometry(
548
+ 0, radius, height, sides, 1, true
549
+ );
550
+
551
+ const material = new THREE.MeshPhysicalMaterial({
552
+ color: 0xffffff,
553
+ metalness: 0.1,
554
+ roughness: 0.1,
555
+ transmission: 0.9,
556
+ ior: 1.5,
557
+ thickness: 0.5,
558
+ envMapIntensity: 1,
559
+ emissive: colorPalettes[currentPreset].high[i % colorPalettes[currentPreset].high.length],
560
+ emissiveIntensity: 0.3
561
+ });
562
+
563
+ const crystal = new THREE.Mesh(geometry, material);
564
+
565
+ // Position within cluster
566
+ crystal.position.x = (Math.random() - 0.5) * 3;
567
+ crystal.position.y = (Math.random() - 0.5) * 3;
568
+ crystal.position.z = (Math.random() - 0.5) * 3;
569
+
570
+ // Rotate randomly
571
+ crystal.rotation.x = Math.random() * Math.PI;
572
+ crystal.rotation.y = Math.random() * Math.PI;
573
+ crystal.rotation.z = Math.random() * Math.PI;
574
+
575
+ group.add(crystal);
576
+ }
577
+
578
+ // Position cluster in scene
579
+ group.position.x = (Math.random() - 0.5) * 40;
580
+ group.position.y = (Math.random() - 0.5) * 40;
581
+ group.position.z = (Math.random() - 0.5) * 40;
582
+
583
+ scene.add(group);
584
+ wireframeStructures.push(group); // Reuse same array for simplicity
585
+ }
586
+ }
587
+
588
+ function createOrganicForms() {
589
+ // Create several organic-looking forms
590
+ for (let i = 0; i < 4; i++) {
591
+ const group = new THREE.Group();
592
+
593
+ // Create a blob-like shape
594
+ const geometry = new THREE.SphereGeometry(
595
+ 1.5 + Math.random(),
596
+ 32, 32
597
+ );
598
+
599
+ // Displace vertices to create organic shape
600
+ const positionAttribute = geometry.getAttribute('position');
601
+ const vertex = new THREE.Vector3();
602
+
603
+ for (let j = 0; j < positionAttribute.count; j++) {
604
+ vertex.fromBufferAttribute(positionAttribute, j);
605
+ vertex.normalize();
606
+
607
+ const radius = 1 + Math.random() * 0.5;
608
+ vertex.multiplyScalar(radius);
609
+
610
+ positionAttribute.setXYZ(j, vertex.x, vertex.y, vertex.z);
611
+ }
612
+
613
+ geometry.computeVertexNormals();
614
+
615
+ const material = new THREE.MeshPhysicalMaterial({
616
+ color: colorPalettes[currentPreset].mid[i % colorPalettes[currentPreset].mid.length],
617
+ metalness: 0.3,
618
+ roughness: 0.7,
619
+ clearcoat: 0.5,
620
+ transmission: 0.3,
621
+ emissive: colorPalettes[currentPreset].mid[i % colorPalettes[currentPreset].mid.length],
622
+ emissiveIntensity: 0.2
623
+ });
624
+
625
+ const blob = new THREE.Mesh(geometry, material);
626
+
627
+ // Position in scene
628
+ blob.position.x = (Math.random() - 0.5) * 30;
629
+ blob.position.y = (Math.random() - 0.5) * 30;
630
+ blob.position.z = (Math.random() - 0.5) * 30;
631
+
632
+ group.add(blob);
633
+ scene.add(group);
634
+ wireframeStructures.push(group); // Reuse same array for simplicity
635
+ }
636
+ }
637
+
638
+ function setupCameraTargets() {
639
+ // Create several interesting camera positions and look-at points
640
+ cameraTargets = [
641
+ { position: new THREE.Vector3(0, 0, 30), lookAt: new THREE.Vector3(0, 0, 0) },
642
+ { position: new THREE.Vector3(20, 10, 20), lookAt: new THREE.Vector3(0, 0, 0) },
643
+ { position: new THREE.Vector3(-15, 15, 25), lookAt: new THREE.Vector3(0, 5, 0) },
644
+ { position: new THREE.Vector3(0, 25, 15), lookAt: new THREE.Vector3(0, 0, 0) },
645
+ { position: new THREE.Vector3(30, 0, 0), lookAt: new THREE.Vector3(0, 0, 0) },
646
+ { position: new THREE.Vector3(-20, -10, 20), lookAt: new THREE.Vector3(0, 0, 0) }
647
+ ];
648
+ }
649
+
650
+ function setupEventListeners() {
651
+ // Window resize
652
+ window.addEventListener('resize', onWindowResize);
653
+
654
+ // Audio controls
655
+ document.getElementById('play-btn').addEventListener('click', playAudio);
656
+ document.getElementById('pause-btn').addEventListener('click', pauseAudio);
657
+ document.getElementById('file-btn').addEventListener('click', () => document.getElementById('file-input').click());
658
+ document.getElementById('mic-btn').addEventListener('click', useMicrophone);
659
+ document.getElementById('file-input').addEventListener('change', handleFileSelect);
660
+
661
+ // Sliders
662
+ document.getElementById('volume-slider').addEventListener('input', (e) => {
663
+ if (audioSource) audioSource.gain.value = e.target.value;
664
+ });
665
+
666
+ // Preset buttons
667
+ document.querySelectorAll('.preset-btn').forEach(btn => {
668
+ btn.addEventListener('click', () => {
669
+ currentPreset = btn.dataset.preset;
670
+ document.querySelectorAll('.preset-btn').forEach(b => b.classList.remove('active'));
671
+ btn.classList.add('active');
672
+ updateMaterials();
673
+ });
674
+ });
675
+ }
676
+
677
+ function initAudio() {
678
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
679
+ analyser = audioContext.createAnalyser();
680
+ analyser.fftSize = 2048;
681
+ dataArray = new Uint8Array(analyser.frequencyBinCount);
682
+ }
683
+
684
+ function playAudio() {
685
+ if (!isPlaying && audioSource) {
686
+ audioSource.connect(analyser);
687
+ analyser.connect(audioContext.destination);
688
+ isPlaying = true;
689
+ }
690
+ }
691
+
692
+ function pauseAudio() {
693
+ if (isPlaying && audioSource) {
694
+ audioSource.disconnect();
695
+ isPlaying = false;
696
+ }
697
+ }
698
+
699
+ function useMicrophone() {
700
+ navigator.mediaDevices.getUserMedia({ audio: true, video: false })
701
+ .then(stream => {
702
+ if (audioSource) audioSource.disconnect();
703
+ audioSource = audioContext.createMediaStreamSource(stream);
704
+ audioSource.connect(analyser);
705
+ analyser.connect(audioContext.destination);
706
+
707
+ // Create gain node for volume control
708
+ const gainNode = audioContext.createGain();
709
+ audioSource.disconnect();
710
+ audioSource.connect(gainNode);
711
+ gainNode.connect(analyser);
712
+ audioSource = gainNode;
713
+
714
+ // Set initial volume
715
+ gainNode.gain.value = document.getElementById('volume-slider').value;
716
+
717
+ isPlaying = true;
718
+ })
719
+ .catch(err => {
720
+ console.error('Error accessing microphone:', err);
721
+ alert('Could not access microphone. Please check permissions.');
722
+ });
723
+ }
724
+
725
+ function handleFileSelect(event) {
726
+ const file = event.target.files[0];
727
+ if (!file) return;
728
+
729
+ const reader = new FileReader();
730
+ reader.onload = function(e) {
731
+ audioContext.decodeAudioData(e.target.result)
732
+ .then(buffer => {
733
+ if (audioSource) audioSource.disconnect();
734
+
735
+ audioSource = audioContext.createBufferSource();
736
+ audioSource.buffer = buffer;
737
+
738
+ // Create gain node for volume control
739
+ const gainNode = audioContext.createGain();
740
+ audioSource.connect(gainNode);
741
+ gainNode.connect(analyser);
742
+ audioSource = gainNode;
743
+
744
+ // Set initial volume
745
+ gainNode.gain.value = document.getElementById('volume-slider').value;
746
+
747
+ audioSource.loop = true;
748
+ audioSource.start();
749
+ isPlaying = true;
750
+ })
751
+ .catch(err => {
752
+ console.error('Error decoding audio file:', err);
753
+ alert('Error loading audio file. Please try a different file.');
754
+ });
755
+ };
756
+ reader.readAsArrayBuffer(file);
757
+ }
758
+
759
+ function updateMaterials() {
760
+ // Update all materials based on current preset
761
+ scene.traverse(obj => {
762
+ if (obj.isMesh) {
763
+ if (obj.material instanceof THREE.MeshPhysicalMaterial) {
764
+ // Determine which color palette to use based on which group the object is in
765
+ let palette;
766
+ if (bassGroup.children.includes(obj)) palette = colorPalettes[currentPreset].bass;
767
+ else if (midGroup.children.includes(obj)) palette = colorPalettes[currentPreset].mid;
768
+ else if (highGroup.children.includes(obj)) palette = colorPalettes[currentPreset].high;
769
+ else palette = colorPalettes[currentPreset].mid; // Default
770
+
771
+ // Select a color from the palette
772
+ const colorIndex = Math.floor(Math.random() * palette.length);
773
+ const color = palette[colorIndex];
774
+
775
+ // Update material properties
776
+ obj.material.color.setHex(color);
777
+ obj.material.emissive.setHex(color);
778
+ }
779
+ } else if (obj.isLine) {
780
+ obj.material.color.setHex(colorPalettes[currentPreset].wireframe);
781
+ }
782
+ });
783
+
784
+ // Update particle colors
785
+ if (particleSystem) {
786
+ const colors = particleSystem.geometry.attributes.color;
787
+ for (let i = 0; i < colors.count; i++) {
788
+ const colorIndex = Math.floor(Math.random() * colorPalettes[currentPreset].particles.length);
789
+ const color = new THREE.Color(colorPalettes[currentPreset].particles[colorIndex]);
790
+ colors.setXYZ(i, color.r, color.g, color.b);
791
+ }
792
+ colors.needsUpdate = true;
793
+ }
794
+
795
+ // Update ambient light
796
+ scene.traverse(obj => {
797
+ if (obj.isAmbientLight) {
798
+ obj.color.setHex(colorPalettes[currentPreset].ambient);
799
+ }
800
+ });
801
+ }
802
+
803
+ function onWindowResize() {
804
+ camera.aspect = window.innerWidth / window.innerHeight;
805
+ camera.updateProjectionMatrix();
806
+ renderer.setSize(window.innerWidth, window.innerHeight);
807
+ composer.setSize(window.innerWidth, window.innerHeight);
808
+ }
809
+
810
+ function animate() {
811
+ requestAnimationFrame(animate);
812
+
813
+ const delta = clock.getDelta();
814
+ const time = clock.getElapsedTime();
815
+
816
+ // Update audio analyzer data if playing
817
+ if (isPlaying && analyser) {
818
+ analyser.getByteFrequencyData(dataArray);
819
+
820
+ // Calculate frequency ranges
821
+ const bassData = getFrequencyRangeValue(dataArray, BASS_RANGE);
822
+ const midData = getFrequencyRangeValue(dataArray, MID_RANGE);
823
+ const highData = getFrequencyRangeValue(dataArray, HIGH_RANGE);
824
+ const overallVolume = getOverallVolume(dataArray);
825
+
826
+ // Apply intensity multipliers from sliders
827
+ const bassIntensity = document.getElementById('bass-slider').value;
828
+ const midIntensity = document.getElementById('mid-slider').value;
829
+ const highIntensity = document.getElementById('high-slider').value;
830
+
831
+ // Update visual elements based on audio data
832
+ updateBassElements(bassData * bassIntensity, time);
833
+ updateMidElements(midData * midIntensity, time);
834
+ updateHighElements(highData * highIntensity, time);
835
+ updateParticleSystem(highData * highIntensity, time);
836
+ updateWireframeStructures(overallVolume, time);
837
+
838
+ // Update bloom effect based on overall volume
839
+ bloomPass.strength = 1 + overallVolume * 2;
840
+ }
841
+
842
+ // Rotate groups slowly
843
+ bassGroup.rotation.y += 0.001;
844
+ midGroup.rotation.y -= 0.0005;
845
+ highGroup.rotation.x += 0.0003;
846
+
847
+ // Move camera between targets periodically
848
+ if (time - lastCameraChange > 8) {
849
+ lastCameraChange = time;
850
+ currentCameraTarget = (currentCameraTarget + 1) % cameraTargets.length;
851
+ }
852
+
853
+ // Smooth camera transition
854
+ const target = cameraTargets[currentCameraTarget];
855
+ camera.position.lerp(target.position, 0.01);
856
+ cameraControls.target.lerp(target.lookAt, 0.01);
857
+
858
+ // Update camera controls
859
+ cameraControls.update();
860
+
861
+ // Render scene with post-processing
862
+ composer.render();
863
+ }
864
+
865
+ function getFrequencyRangeValue(dataArray, [lowFreq, highFreq]) {
866
+ const sampleRate = audioContext.sampleRate;
867
+ const binCount = analyser.frequencyBinCount;
868
+
869
+ const lowIndex = Math.round(lowFreq / (sampleRate / 2) * binCount);
870
+ const highIndex = Math.round(highFreq / (sampleRate / 2) * binCount);
871
+
872
+ let total = 0;
873
+ let count = 0;
874
+
875
+ for (let i = lowIndex; i <= highIndex; i++) {
876
+ total += dataArray[i];
877
+ count++;
878
+ }
879
+
880
+ return count > 0 ? total / count / 255 : 0;
881
+ }
882
+
883
+ function getOverallVolume(dataArray) {
884
+ let total = 0;
885
+ for (let i = 0; i < dataArray.length; i++) {
886
+ total += dataArray[i];
887
+ }
888
+ return total / dataArray.length / 255;
889
+ }
890
+
891
+ function updateBassElements(intensity, time) {
892
+ bassGroup.children.forEach((child, i) => {
893
+ if (i === 0) {
894
+ // Main central shape - scale with bass
895
+ const scale = 1 + intensity * 0.5;
896
+ child.scale.set(scale, scale, scale);
897
+
898
+ // Pulsing emissive
899
+ child.material.emissiveIntensity = 0.2 + intensity * 0.8;
900
+ } else {
901
+ // Surrounding shapes - move outward with bass
902
+ const angle = (i / (bassGroup.children.length - 1)) * Math.PI * 2;
903
+ const baseRadius = 8;
904
+ const radius = baseRadius + intensity * 5;
905
+
906
+ child.position.x = Math.cos(angle + time * 0.2) * radius;
907
+ child.position.y = Math.sin(angle + time * 0.2) * radius;
908
+
909
+ // Rotate
910
+ child.rotation.x += 0.01;
911
+ child.rotation.y += 0.01;
912
+
913
+ // Scale slightly
914
+ const scale = 1 + intensity * 0.3;
915
+ child.scale.set(scale, scale, scale);
916
+ }
917
+ });
918
+ }
919
+
920
+ function updateMidElements(intensity, time) {
921
+ midGroup.children.forEach((child, i) => {
922
+ // Move in circular patterns
923
+ const angle = (i / midGroup.children.length) * Math.PI * 2;
924
+ const baseRadius = 12;
925
+ const radius = baseRadius + intensity * 3;
926
+
927
+ child.position.x = Math.cos(angle + time * 0.3) * radius;
928
+ child.position.y = Math.sin(angle + time * 0.3) * radius;
929
+
930
+ // Rotate
931
+ child.rotation.x += 0.02;
932
+ child.rotation.z += 0.01;
933
+
934
+ // Scale
935
+ const scale = 1 + intensity * 0.2;
936
+ child.scale.set(scale, scale, scale);
937
+
938
+ // Pulsing emissive
939
+ child.material.emissiveIntensity = 0.2 + intensity * 0.6;
940
+ });
941
+ }
942
+
943
+ function updateHighElements(intensity, time) {
944
+ highGroup.children.forEach((child, i) => {
945
+ // Move in more complex patterns
946
+ const angle = (i / highGroup.children.length) * Math.PI * 2;
947
+ const baseRadius = 15;
948
+ const radius = baseRadius + intensity * 4;
949
+ const height = Math.sin(time * 0.5 + i) * 5;
950
+
951
+ child.position.x = Math.cos(angle + time * 0.4) * radius;
952
+ child.position.y = Math.sin(angle + time * 0.4) * radius;
953
+ child.position.z = height;
954
+
955
+ // Scale
956
+ const scale = 1 + intensity * 0.4;
957
+ child.scale.set(scale, scale, scale);
958
+
959
+ // Pulsing emissive
960
+ child.material.emissiveIntensity = 0.3 + intensity * 0.7;
961
+ });
962
+ }
963
+
964
+ function updateParticleSystem(intensity, time) {
965
+ const particles = particleSystem.geometry.attributes.position;
966
+ const originalPositions = particleSystem.geometry.attributes.originalPosition || particles;
967
+
968
+ // Store original positions if not already done
969
+ if (!particleSystem.geometry.attributes.originalPosition) {
970
+ const origPos = new Float32Array(particles.count * 3);
971
+ for (let i = 0; i < particles.count * 3; i++) {
972
+ origPos[i] = particles.array[i];
973
+ }
974
+ particleSystem.geometry.setAttribute(
975
+ 'originalPosition',
976
+ new THREE.BufferAttribute(origPos, 3)
977
+ );
978
+ }
979
+
980
+ // Update particle positions based on audio
981
+ for (let i = 0; i < particles.count; i++) {
982
+ const ix = i * 3;
983
+ const iy = i * 3 + 1;
984
+ const iz = i * 3 + 2;
985
+
986
+ // Get original position
987
+ const ox = originalPositions.array[ix];
988
+ const oy = originalPositions.array[iy];
989
+ const oz = originalPositions.array[iz];
990
+
991
+ // Calculate displacement based on audio
992
+ const displacement = intensity * 5;
993
+ const noise = Math.sin(time * 2 + i * 0.1) * displacement;
994
+
995
+ // Apply displacement
996
+ particles.array[ix] = ox + noise * 0.3;
997
+ particles.array[iy] = oy + noise * 0.3;
998
+ particles.array[iz] = oz + noise * 0.3;
999
+ }
1000
+
1001
+ particles.needsUpdate = true;
1002
+
1003
+ // Rotate particle system
1004
+ particleSystem.rotation.y += 0.001;
1005
+ }
1006
+
1007
+ function updateWireframeStructures(intensity, time) {
1008
+ wireframeStructures.forEach((group, i) => {
1009
+ // Float up and down slowly
1010
+ group.position.y += Math.sin(time * 0.1 + i) * 0.02;
1011
+
1012
+ // Rotate
1013
+ group.rotation.x += 0.005;
1014
+ group.rotation.y += 0.007;
1015
+ group.rotation.z += 0.003;
1016
+
1017
+ // Scale slightly with audio
1018
+ const scale = 1 + intensity * 0.5;
1019
+ group.scale.set(scale, scale, scale);
1020
+
1021
+ // Update line opacity based on audio
1022
+ group.children.forEach(child => {
1023
+ if (child.isLine) {
1024
+ child.material.opacity = 0.4 + intensity * 0.6;
1025
+ }
1026
+ });
1027
+ });
1028
+ }
1029
+ </script>
1030
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Fabriwin/audio-dimension" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1031
+ </html>