kolaslab commited on
Commit
797cfe7
1 Parent(s): d1bc016

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +208 -157
index.html CHANGED
@@ -3,285 +3,336 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>3D Audio Spectrum Analyzer</title>
7
  <style>
 
 
 
 
 
 
 
 
8
  * {
9
  margin: 0;
10
  padding: 0;
11
  box-sizing: border-box;
12
- font-family: Arial, sans-serif;
13
  }
14
 
15
  body {
16
- background: #1a1a1a;
17
- color: #fff;
 
18
  }
19
 
20
- .container {
21
- max-width: 1200px;
22
- margin: 0 auto;
 
23
  padding: 20px;
 
24
  }
25
 
26
- .header {
27
- text-align: center;
28
- padding: 20px 0;
 
 
 
 
29
  }
30
 
31
- .controls {
32
  display: grid;
33
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
34
  gap: 20px;
35
- margin: 20px 0;
36
- }
37
-
38
- .control-panel {
39
- background: #2a2a2a;
40
- padding: 20px;
41
- border-radius: 8px;
42
  }
43
 
44
- .visualization {
45
  display: grid;
46
  grid-template-columns: 2fr 1fr;
47
  gap: 20px;
48
- margin: 20px 0;
 
 
 
 
 
 
49
  }
50
 
51
  canvas {
52
  width: 100%;
53
- height: 400px;
54
- background: #2a2a2a;
55
  border-radius: 8px;
56
  }
57
 
58
- button {
59
- background: #4CAF50;
 
 
 
 
 
 
60
  color: white;
61
- padding: 10px 20px;
62
  border: none;
63
- border-radius: 4px;
 
64
  cursor: pointer;
65
- margin: 5px;
 
 
 
 
 
 
 
 
 
 
66
  }
67
 
68
- button:hover {
69
- background: #45a049;
70
  }
71
 
72
- input[type="number"] {
 
 
 
 
 
 
 
73
  width: 100%;
74
  padding: 8px;
75
- margin: 5px 0;
 
76
  border-radius: 4px;
77
- border: 1px solid #444;
78
- background: #333;
79
  color: white;
80
  }
81
 
82
- .device-status {
83
- background: #2a2a2a;
84
- padding: 20px;
85
- border-radius: 8px;
86
- margin-top: 20px;
87
  }
88
 
89
- .preset-container {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  display: grid;
91
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
92
  gap: 10px;
93
- margin: 20px 0;
94
  }
95
 
96
- .preset {
97
- background: #333;
98
  padding: 10px;
99
  border-radius: 4px;
100
  cursor: pointer;
 
101
  }
102
 
103
- .preset:hover {
104
- background: #444;
105
  }
106
  </style>
107
  </head>
108
  <body>
109
- <div class="container">
110
- <div class="header">
111
- <h1>3D Audio Spectrum Analyzer</h1>
112
- </div>
113
-
114
- <div class="controls">
115
  <div class="control-panel">
116
- <h3>Device Configuration</h3>
117
- <button id="startAnalysis">Start Analysis</button>
118
- <button id="stopAnalysis">Stop Analysis</button>
119
- <button id="calibrate">Calibrate Devices</button>
120
- <div>
121
- <label>Device Role:</label>
122
  <select id="deviceRole">
 
123
  <option value="left">Left Channel</option>
124
  <option value="right">Right Channel</option>
125
- <option value="center">Center Channel</option>
126
  </select>
127
  </div>
 
 
 
 
 
 
 
 
 
 
128
  </div>
 
129
 
 
130
  <div class="control-panel">
131
- <h3>Binaural Beat Generator</h3>
132
- <div>
133
- <label>Base Frequency (Hz):</label>
134
  <input type="number" id="baseFreq" value="432" min="20" max="1000">
135
  </div>
136
- <div>
137
- <label>Beat Frequency (Hz):</label>
138
  <input type="number" id="beatFreq" value="7" min="1" max="40">
139
  </div>
140
- <button id="startBinaural">Generate Binaural Beat</button>
141
- <button id="stopBinaural">Stop</button>
142
  </div>
143
- </div>
144
 
145
- <div class="visualization">
146
- <canvas id="spectrumCanvas"></canvas>
147
- <canvas id="3dRoomCanvas"></canvas>
148
- </div>
149
-
150
- <div class="preset-container">
151
- <div class="preset">
152
- <h4>Alpha Wave</h4>
153
- <p>8-12 Hz</p>
154
- </div>
155
- <div class="preset">
156
- <h4>Theta Wave</h4>
157
- <p>4-7 Hz</p>
158
- </div>
159
- <div class="preset">
160
- <h4>Delta Wave</h4>
161
- <p>0.5-4 Hz</p>
162
  </div>
163
- </div>
164
-
165
- <div class="device-status">
166
- <h3>Connected Devices</h3>
167
- <div id="deviceList"></div>
168
- </div>
169
  </div>
170
 
171
  <script>
172
- class AudioAnalyzer {
173
  constructor() {
174
  this.audioContext = null;
175
  this.analyser = null;
176
- this.oscillator = null;
177
- this.isPlaying = false;
 
 
 
 
 
178
  }
179
 
180
  async initialize() {
181
  try {
182
  this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
183
  this.analyser = this.audioContext.createAnalyser();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
185
  const source = this.audioContext.createMediaStreamSource(stream);
186
  source.connect(this.analyser);
187
- this.setupVisualization();
188
  } catch (error) {
189
- console.error('Error initializing audio:', error);
190
  }
191
  }
192
 
193
  generateBinauralBeat(baseFreq, beatFreq) {
194
- if (this.isPlaying) this.stopBinauralBeat();
195
 
196
  const leftOsc = this.audioContext.createOscillator();
197
  const rightOsc = this.audioContext.createOscillator();
198
- const leftGain = this.audioContext.createGain();
199
- const rightGain = this.audioContext.createGain();
200
- const merger = this.audioContext.createChannelMerger(2);
201
-
202
  leftOsc.frequency.value = baseFreq;
203
  rightOsc.frequency.value = baseFreq + beatFreq;
204
 
205
- leftOsc.connect(leftGain);
206
- rightOsc.connect(rightGain);
207
- leftGain.connect(merger, 0, 0);
208
- rightGain.connect(merger, 0, 1);
209
- merger.connect(this.audioContext.destination);
210
 
211
  leftOsc.start();
212
  rightOsc.start();
213
- this.oscillator = { left: leftOsc, right: rightOsc };
214
- this.isPlaying = true;
 
215
  }
216
 
217
  stopBinauralBeat() {
218
- if (this.oscillator) {
219
- this.oscillator.left.stop();
220
- this.oscillator.right.stop();
221
- this.isPlaying = false;
222
- }
223
  }
224
 
225
- setupVisualization() {
226
- const canvas = document.getElementById('spectrumCanvas');
227
  const ctx = canvas.getContext('2d');
228
- const width = canvas.width;
229
- const height = canvas.height;
230
 
231
  const draw = () => {
232
  requestAnimationFrame(draw);
233
- const dataArray = new Uint8Array(this.analyser.frequencyBinCount);
234
  this.analyser.getByteFrequencyData(dataArray);
 
 
 
235
 
236
- ctx.fillStyle = '#2a2a2a';
237
- ctx.fillRect(0, 0, width, height);
238
-
239
- const barWidth = width / dataArray.length;
240
  let x = 0;
241
 
242
- dataArray.forEach(value => {
243
- const barHeight = value * height / 255;
244
- ctx.fillStyle = `hsl(${value}, 100%, 50%)`;
245
- ctx.fillRect(x, height - barHeight, barWidth, barHeight);
246
- x += barWidth;
247
- });
 
 
 
248
  };
249
 
250
  draw();
251
  }
252
- }
253
 
254
- // Initialize application
255
- const analyzer = new AudioAnalyzer();
256
-
257
- document.getElementById('startAnalysis').addEventListener('click', () => analyzer.initialize());
258
- document.getElementById('startBinaural').addEventListener('click', () => {
259
- const baseFreq = parseFloat(document.getElementById('baseFreq').value);
260
- const beatFreq = parseFloat(document.getElementById('beatFreq').value);
261
- analyzer.generateBinauralBeat(baseFreq, beatFreq);
262
- });
263
- document.getElementById('stopBinaural').addEventListener('click', () => analyzer.stopBinauralBeat());
264
-
265
- // Setup room visualization
266
- const room3d = document.getElementById('3dRoomCanvas');
267
- const ctx3d = room3d.getContext('2d');
268
-
269
- function draw3dRoom() {
270
- // Basic 3D room visualization implementation would go here
271
- // This would require a more complex 3D rendering library for proper implementation
272
- ctx3d.fillStyle = '#2a2a2a';
273
- ctx3d.fillRect(0, 0, room3d.width, room3d.height);
274
- ctx3d.strokeStyle = '#4CAF50';
275
- ctx3d.beginPath();
276
- ctx3d.moveTo(50, 50);
277
- ctx3d.lineTo(room3d.width - 50, 50);
278
- ctx3d.lineTo(room3d.width - 50, room3d.height - 50);
279
- ctx3d.lineTo(50, room3d.height - 50);
280
- ctx3d.closePath();
281
- ctx3d.stroke();
282
  }
283
 
284
- draw3dRoom();
 
285
  </script>
286
  </body>
287
  </html><script async data-explicit-opt-in="true" data-cookie-opt-in="true" src="https://vercel.live/_next-live/feedback/feedback.js"></script>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Multi-Device Audio Analysis System</title>
7
  <style>
8
+ :root {
9
+ --primary: #2196F3;
10
+ --secondary: #4CAF50;
11
+ --bg-dark: #1a1a1a;
12
+ --bg-light: #2a2a2a;
13
+ --text: #ffffff;
14
+ }
15
+
16
  * {
17
  margin: 0;
18
  padding: 0;
19
  box-sizing: border-box;
20
+ font-family: 'Segoe UI', system-ui, sans-serif;
21
  }
22
 
23
  body {
24
+ background: var(--bg-dark);
25
+ color: var(--text);
26
+ min-height: 100vh;
27
  }
28
 
29
+ .app-container {
30
+ display: grid;
31
+ grid-template-columns: 300px 1fr;
32
+ gap: 20px;
33
  padding: 20px;
34
+ height: 100vh;
35
  }
36
 
37
+ .sidebar {
38
+ background: var(--bg-light);
39
+ border-radius: 12px;
40
+ padding: 20px;
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: 20px;
44
  }
45
 
46
+ .main-content {
47
  display: grid;
48
+ grid-template-rows: auto 1fr;
49
  gap: 20px;
 
 
 
 
 
 
 
50
  }
51
 
52
+ .visualization-container {
53
  display: grid;
54
  grid-template-columns: 2fr 1fr;
55
  gap: 20px;
56
+ }
57
+
58
+ .canvas-container {
59
+ background: var(--bg-light);
60
+ border-radius: 12px;
61
+ padding: 20px;
62
+ position: relative;
63
  }
64
 
65
  canvas {
66
  width: 100%;
67
+ height: 100%;
68
+ background: rgba(0,0,0,0.2);
69
  border-radius: 8px;
70
  }
71
 
72
+ .control-panel {
73
+ background: var(--bg-light);
74
+ border-radius: 12px;
75
+ padding: 20px;
76
+ }
77
+
78
+ .btn {
79
+ background: var(--primary);
80
  color: white;
 
81
  border: none;
82
+ padding: 12px 24px;
83
+ border-radius: 6px;
84
  cursor: pointer;
85
+ transition: opacity 0.2s;
86
+ width: 100%;
87
+ margin-bottom: 10px;
88
+ }
89
+
90
+ .btn:hover {
91
+ opacity: 0.9;
92
+ }
93
+
94
+ .btn.secondary {
95
+ background: var(--secondary);
96
  }
97
 
98
+ .input-group {
99
+ margin-bottom: 15px;
100
  }
101
 
102
+ .input-group label {
103
+ display: block;
104
+ margin-bottom: 5px;
105
+ color: #888;
106
+ }
107
+
108
+ input[type="number"],
109
+ select {
110
  width: 100%;
111
  padding: 8px;
112
+ background: rgba(255,255,255,0.1);
113
+ border: 1px solid rgba(255,255,255,0.2);
114
  border-radius: 4px;
 
 
115
  color: white;
116
  }
117
 
118
+ .device-list {
119
+ display: flex;
120
+ flex-direction: column;
121
+ gap: 10px;
 
122
  }
123
 
124
+ .device-item {
125
+ background: rgba(255,255,255,0.1);
126
+ padding: 10px;
127
+ border-radius: 4px;
128
+ display: flex;
129
+ justify-content: space-between;
130
+ align-items: center;
131
+ }
132
+
133
+ .status-indicator {
134
+ width: 10px;
135
+ height: 10px;
136
+ border-radius: 50%;
137
+ background: var(--secondary);
138
+ }
139
+
140
+ #frequencyDisplay {
141
+ position: absolute;
142
+ top: 10px;
143
+ right: 10px;
144
+ background: rgba(0,0,0,0.7);
145
+ padding: 5px 10px;
146
+ border-radius: 4px;
147
+ }
148
+
149
+ .preset-list {
150
  display: grid;
151
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
152
  gap: 10px;
 
153
  }
154
 
155
+ .preset-item {
156
+ background: rgba(255,255,255,0.1);
157
  padding: 10px;
158
  border-radius: 4px;
159
  cursor: pointer;
160
+ transition: background 0.2s;
161
  }
162
 
163
+ .preset-item:hover {
164
+ background: rgba(255,255,255,0.2);
165
  }
166
  </style>
167
  </head>
168
  <body>
169
+ <div class="app-container">
170
+ <aside class="sidebar">
 
 
 
 
171
  <div class="control-panel">
172
+ <h3>Device Settings</h3>
173
+ <div class="input-group">
174
+ <label>Device Role</label>
 
 
 
175
  <select id="deviceRole">
176
+ <option value="primary">Primary</option>
177
  <option value="left">Left Channel</option>
178
  <option value="right">Right Channel</option>
 
179
  </select>
180
  </div>
181
+ <button class="btn" id="startCapture">Start Capture</button>
182
+ <button class="btn secondary" id="calibrate">Calibrate</button>
183
+ </div>
184
+
185
+ <div class="device-list">
186
+ <h3>Connected Devices</h3>
187
+ <div class="device-item">
188
+ <span>This Device</span>
189
+ <div class="status-indicator"></div>
190
+ </div>
191
  </div>
192
+ </aside>
193
 
194
+ <main class="main-content">
195
  <div class="control-panel">
196
+ <h2>Binaural Beat Generator</h2>
197
+ <div class="input-group">
198
+ <label>Base Frequency (Hz)</label>
199
  <input type="number" id="baseFreq" value="432" min="20" max="1000">
200
  </div>
201
+ <div class="input-group">
202
+ <label>Beat Frequency (Hz)</label>
203
  <input type="number" id="beatFreq" value="7" min="1" max="40">
204
  </div>
205
+ <button class="btn" id="generateBeat">Generate Beat</button>
 
206
  </div>
 
207
 
208
+ <div class="visualization-container">
209
+ <div class="canvas-container">
210
+ <canvas id="spectrumAnalyzer"></canvas>
211
+ <div id="frequencyDisplay">0 Hz</div>
212
+ </div>
213
+ <div class="canvas-container">
214
+ <canvas id="roomAnalysis"></canvas>
215
+ </div>
 
 
 
 
 
 
 
 
 
216
  </div>
217
+ </main>
 
 
 
 
 
218
  </div>
219
 
220
  <script>
221
+ class AudioSystem {
222
  constructor() {
223
  this.audioContext = null;
224
  this.analyser = null;
225
+ this.gainNode = null;
226
+ this.oscillators = {};
227
+ this.isCapturing = false;
228
+ this.isGenerating = false;
229
+
230
+ this.initialize();
231
+ this.setupEventListeners();
232
  }
233
 
234
  async initialize() {
235
  try {
236
  this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
237
  this.analyser = this.audioContext.createAnalyser();
238
+ this.gainNode = this.audioContext.createGain();
239
+
240
+ this.analyser.fftSize = 2048;
241
+ this.gainNode.connect(this.audioContext.destination);
242
+ this.analyser.connect(this.gainNode);
243
+
244
+ await this.setupSpectrumVisualizer();
245
+ } catch (error) {
246
+ console.error('Audio initialization failed:', error);
247
+ }
248
+ }
249
+
250
+ async startCapture() {
251
+ if (this.isCapturing) return;
252
+
253
+ try {
254
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
255
  const source = this.audioContext.createMediaStreamSource(stream);
256
  source.connect(this.analyser);
257
+ this.isCapturing = true;
258
  } catch (error) {
259
+ console.error('Capture failed:', error);
260
  }
261
  }
262
 
263
  generateBinauralBeat(baseFreq, beatFreq) {
264
+ if (this.isGenerating) this.stopBinauralBeat();
265
 
266
  const leftOsc = this.audioContext.createOscillator();
267
  const rightOsc = this.audioContext.createOscillator();
268
+
 
 
 
269
  leftOsc.frequency.value = baseFreq;
270
  rightOsc.frequency.value = baseFreq + beatFreq;
271
 
272
+ const merger = this.audioContext.createChannelMerger(2);
273
+
274
+ leftOsc.connect(merger, 0, 0);
275
+ rightOsc.connect(merger, 0, 1);
276
+ merger.connect(this.gainNode);
277
 
278
  leftOsc.start();
279
  rightOsc.start();
280
+
281
+ this.oscillators = { left: leftOsc, right: rightOsc };
282
+ this.isGenerating = true;
283
  }
284
 
285
  stopBinauralBeat() {
286
+ if (!this.isGenerating) return;
287
+
288
+ Object.values(this.oscillators).forEach(osc => osc.stop());
289
+ this.oscillators = {};
290
+ this.isGenerating = false;
291
  }
292
 
293
+ async setupSpectrumVisualizer() {
294
+ const canvas = document.getElementById('spectrumAnalyzer');
295
  const ctx = canvas.getContext('2d');
296
+ const bufferLength = this.analyser.frequencyBinCount;
297
+ const dataArray = new Uint8Array(bufferLength);
298
 
299
  const draw = () => {
300
  requestAnimationFrame(draw);
301
+
302
  this.analyser.getByteFrequencyData(dataArray);
303
+
304
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
305
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
306
 
307
+ const barWidth = canvas.width / bufferLength;
 
 
 
308
  let x = 0;
309
 
310
+ for(let i = 0; i < bufferLength; i++) {
311
+ const barHeight = (dataArray[i] / 255) * canvas.height;
312
+
313
+ const hue = i / bufferLength * 360;
314
+ ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
315
+
316
+ ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
317
+ x += barWidth + 1;
318
+ }
319
  };
320
 
321
  draw();
322
  }
 
323
 
324
+ setupEventListeners() {
325
+ document.getElementById('startCapture').onclick = () => this.startCapture();
326
+ document.getElementById('generateBeat').onclick = () => {
327
+ const baseFreq = parseFloat(document.getElementById('baseFreq').value);
328
+ const beatFreq = parseFloat(document.getElementById('beatFreq').value);
329
+ this.generateBinauralBeat(baseFreq, beatFreq);
330
+ };
331
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  }
333
 
334
+ // Initialize the system
335
+ const audioSystem = new AudioSystem();
336
  </script>
337
  </body>
338
  </html><script async data-explicit-opt-in="true" data-cookie-opt-in="true" src="https://vercel.live/_next-live/feedback/feedback.js"></script>