Jonwi0706 commited on
Commit
bd02e53
·
verified ·
1 Parent(s): b2dfba6

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +1148 -19
index.html CHANGED
@@ -1,19 +1,1148 @@
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, maximum-scale=1.0, user-scalable=no">
6
+ <title>InstrumentFromPhoto - AI-Powered Virtual Instruments</title>
7
+
8
+ <!-- Material Icons -->
9
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
11
+
12
+ <style>
13
+ :root {
14
+ --primary: #6750A4;
15
+ --primary-variant: #4F378B;
16
+ --secondary: #625B71;
17
+ --surface: #FFFBFE;
18
+ --surface-variant: #E7E0EC;
19
+ --background: #FEF7FF;
20
+ --error: #BA1A1A;
21
+ --on-primary: #FFFFFF;
22
+ --on-secondary: #FFFFFF;
23
+ --on-surface: #1C1B1F;
24
+ --on-surface-variant: #49454F;
25
+ --outline: #79747E;
26
+ --shadow: rgba(0, 0, 0, 0.12);
27
+ --elevation-1: 0 1px 2px rgba(0,0,0,0.16), 0 1px 3px rgba(0,0,0,0.23);
28
+ --elevation-2: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
29
+ --elevation-3: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
30
+ }
31
+
32
+ * {
33
+ margin: 0;
34
+ padding: 0;
35
+ box-sizing: border-box;
36
+ }
37
+
38
+ body {
39
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
40
+ background: var(--background);
41
+ color: var(--on-surface);
42
+ overflow-x: hidden;
43
+ position: relative;
44
+ min-height: 100vh;
45
+ }
46
+
47
+ .app-container {
48
+ display: flex;
49
+ flex-direction: column;
50
+ min-height: 100vh;
51
+ position: relative;
52
+ }
53
+
54
+ /* Header */
55
+ .header {
56
+ background: var(--primary);
57
+ color: var(--on-primary);
58
+ padding: 16px;
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: space-between;
62
+ box-shadow: var(--elevation-2);
63
+ position: sticky;
64
+ top: 0;
65
+ z-index: 100;
66
+ }
67
+
68
+ .header-title {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: 12px;
72
+ font-size: 20px;
73
+ font-weight: 600;
74
+ }
75
+
76
+ .header-actions {
77
+ display: flex;
78
+ gap: 8px;
79
+ }
80
+
81
+ .icon-button {
82
+ background: rgba(255, 255, 255, 0.12);
83
+ border: none;
84
+ border-radius: 20px;
85
+ width: 40px;
86
+ height: 40px;
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ cursor: pointer;
91
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
92
+ }
93
+
94
+ .icon-button:hover {
95
+ background: rgba(255, 255, 255, 0.24);
96
+ transform: scale(1.05);
97
+ }
98
+
99
+ /* Main Content */
100
+ .main-content {
101
+ flex: 1;
102
+ padding: 16px;
103
+ padding-bottom: 80px;
104
+ }
105
+
106
+ /* Camera View */
107
+ .camera-section {
108
+ display: none;
109
+ animation: fadeIn 0.3s ease-out;
110
+ }
111
+
112
+ .camera-section.active {
113
+ display: block;
114
+ }
115
+
116
+ @keyframes fadeIn {
117
+ from { opacity: 0; transform: translateY(10px); }
118
+ to { opacity: 1; transform: translateY(0); }
119
+ }
120
+
121
+ .camera-container {
122
+ background: var(--surface);
123
+ border-radius: 16px;
124
+ overflow: hidden;
125
+ box-shadow: var(--elevation-1);
126
+ margin-bottom: 16px;
127
+ }
128
+
129
+ #camera-view {
130
+ width: 100%;
131
+ height: 300px;
132
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ position: relative;
137
+ overflow: hidden;
138
+ }
139
+
140
+ .camera-placeholder {
141
+ text-align: center;
142
+ color: white;
143
+ }
144
+
145
+ .camera-placeholder .material-icons {
146
+ font-size: 64px;
147
+ margin-bottom: 16px;
148
+ }
149
+
150
+ .camera-controls {
151
+ display: flex;
152
+ gap: 12px;
153
+ padding: 16px;
154
+ background: var(--surface-variant);
155
+ }
156
+
157
+ .capture-button {
158
+ flex: 1;
159
+ background: var(--primary);
160
+ color: var(--on-primary);
161
+ border: none;
162
+ padding: 16px;
163
+ border-radius: 100px;
164
+ font-size: 16px;
165
+ font-weight: 500;
166
+ cursor: pointer;
167
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ gap: 8px;
172
+ }
173
+
174
+ .capture-button:hover {
175
+ background: var(--primary-variant);
176
+ transform: scale(1.02);
177
+ }
178
+
179
+ .capture-button:active {
180
+ transform: scale(0.98);
181
+ }
182
+
183
+ /* AI Processing */
184
+ .ai-processing {
185
+ display: none;
186
+ background: var(--surface);
187
+ border-radius: 16px;
188
+ padding: 24px;
189
+ text-align: center;
190
+ box-shadow: var(--elevation-1);
191
+ animation: pulse 2s infinite;
192
+ }
193
+
194
+ .ai-processing.active {
195
+ display: block;
196
+ }
197
+
198
+ @keyframes pulse {
199
+ 0%, 100% { opacity: 1; }
200
+ 50% { opacity: 0.7; }
201
+ }
202
+
203
+ .processing-icon {
204
+ font-size: 48px;
205
+ color: var(--primary);
206
+ animation: spin 2s linear infinite;
207
+ margin-bottom: 16px;
208
+ }
209
+
210
+ @keyframes spin {
211
+ from { transform: rotate(0deg); }
212
+ to { transform: rotate(360deg); }
213
+ }
214
+
215
+ /* Instrument Selection */
216
+ .instrument-selection {
217
+ display: none;
218
+ animation: slideUp 0.4s cubic-bezier(0.4, 0, 0.2, 1);
219
+ }
220
+
221
+ .instrument-selection.active {
222
+ display: block;
223
+ }
224
+
225
+ @keyframes slideUp {
226
+ from { opacity: 0; transform: translateY(20px); }
227
+ to { opacity: 1; transform: translateY(0); }
228
+ }
229
+
230
+ .detection-result {
231
+ background: var(--surface);
232
+ border-radius: 16px;
233
+ padding: 20px;
234
+ margin-bottom: 16px;
235
+ box-shadow: var(--elevation-1);
236
+ }
237
+
238
+ .detection-header {
239
+ display: flex;
240
+ align-items: center;
241
+ gap: 12px;
242
+ margin-bottom: 16px;
243
+ }
244
+
245
+ .detection-icon {
246
+ width: 48px;
247
+ height: 48px;
248
+ background: var(--primary);
249
+ border-radius: 12px;
250
+ display: flex;
251
+ align-items: center;
252
+ justify-content: center;
253
+ color: var(--on-primary);
254
+ }
255
+
256
+ .detection-info h3 {
257
+ font-size: 20px;
258
+ font-weight: 600;
259
+ margin-bottom: 4px;
260
+ }
261
+
262
+ .confidence-badge {
263
+ display: inline-block;
264
+ background: var(--surface-variant);
265
+ padding: 4px 12px;
266
+ border-radius: 100px;
267
+ font-size: 12px;
268
+ font-weight: 500;
269
+ color: var(--on-surface-variant);
270
+ }
271
+
272
+ .instrument-variants {
273
+ display: flex;
274
+ gap: 8px;
275
+ flex-wrap: wrap;
276
+ margin-top: 12px;
277
+ }
278
+
279
+ .variant-chip {
280
+ background: var(--surface-variant);
281
+ padding: 8px 16px;
282
+ border-radius: 100px;
283
+ font-size: 14px;
284
+ cursor: pointer;
285
+ transition: all 0.2s;
286
+ }
287
+
288
+ .variant-chip:hover {
289
+ background: var(--primary);
290
+ color: var(--on-primary);
291
+ }
292
+
293
+ /* Playable Interfaces */
294
+ .instrument-playground {
295
+ background: var(--surface);
296
+ border-radius: 16px;
297
+ padding: 20px;
298
+ box-shadow: var(--elevation-1);
299
+ min-height: 400px;
300
+ }
301
+
302
+ .playground-header {
303
+ display: flex;
304
+ justify-content: space-between;
305
+ align-items: center;
306
+ margin-bottom: 20px;
307
+ }
308
+
309
+ .playground-title {
310
+ font-size: 18px;
311
+ font-weight: 600;
312
+ }
313
+
314
+ .playground-controls {
315
+ display: flex;
316
+ gap: 8px;
317
+ }
318
+
319
+ .control-button {
320
+ background: var(--surface-variant);
321
+ border: none;
322
+ padding: 8px 16px;
323
+ border-radius: 100px;
324
+ font-size: 14px;
325
+ cursor: pointer;
326
+ transition: all 0.2s;
327
+ }
328
+
329
+ .control-button:hover {
330
+ background: var(--primary);
331
+ color: var(--on-primary);
332
+ }
333
+
334
+ /* Fretboard Renderer */
335
+ .fretboard-renderer {
336
+ width: 100%;
337
+ overflow-x: auto;
338
+ -webkit-overflow-scrolling: touch;
339
+ padding: 20px 0;
340
+ }
341
+
342
+ .fretboard {
343
+ display: flex;
344
+ flex-direction: column;
345
+ gap: 8px;
346
+ min-width: 600px;
347
+ }
348
+
349
+ .string {
350
+ display: flex;
351
+ align-items: center;
352
+ height: 40px;
353
+ position: relative;
354
+ background: linear-gradient(90deg, var(--outline) 0%, transparent 1px);
355
+ }
356
+
357
+ .string::before {
358
+ content: '';
359
+ position: absolute;
360
+ top: 50%;
361
+ left: 0;
362
+ right: 0;
363
+ height: 2px;
364
+ background: var(--secondary);
365
+ transform: translateY(-50%);
366
+ }
367
+
368
+ .fret {
369
+ flex: 1;
370
+ height: 40px;
371
+ border-right: 2px solid var(--outline);
372
+ position: relative;
373
+ cursor: pointer;
374
+ transition: all 0.1s;
375
+ }
376
+
377
+ .fret:hover {
378
+ background: rgba(103, 80, 164, 0.1);
379
+ }
380
+
381
+ .fret.active {
382
+ background: var(--primary);
383
+ animation: noteGlow 0.3s ease-out;
384
+ }
385
+
386
+ @keyframes noteGlow {
387
+ 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(103, 80, 164, 0.7); }
388
+ 100% { transform: scale(1.1); box-shadow: 0 0 0 10px rgba(103, 80, 164, 0); }
389
+ }
390
+
391
+ .fret-marker {
392
+ position: absolute;
393
+ top: 50%;
394
+ left: 50%;
395
+ transform: translate(-50%, -50%);
396
+ width: 8px;
397
+ height: 8px;
398
+ background: var(--on-surface-variant);
399
+ border-radius: 50%;
400
+ opacity: 0.3;
401
+ }
402
+
403
+ /* Pad Grid Renderer */
404
+ .pad-grid-renderer {
405
+ display: grid;
406
+ gap: 12px;
407
+ padding: 20px 0;
408
+ }
409
+
410
+ .pad-grid-4x4 {
411
+ grid-template-columns: repeat(4, 1fr);
412
+ }
413
+
414
+ .pad {
415
+ aspect-ratio: 1;
416
+ background: var(--surface-variant);
417
+ border-radius: 12px;
418
+ display: flex;
419
+ align-items: center;
420
+ justify-content: center;
421
+ font-size: 14px;
422
+ font-weight: 500;
423
+ color: var(--on-surface-variant);
424
+ cursor: pointer;
425
+ transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
426
+ position: relative;
427
+ overflow: hidden;
428
+ }
429
+
430
+ .pad::before {
431
+ content: '';
432
+ position: absolute;
433
+ top: 50%;
434
+ left: 50%;
435
+ width: 0;
436
+ height: 0;
437
+ background: var(--primary);
438
+ border-radius: 50%;
439
+ transform: translate(-50%, -50%);
440
+ transition: width 0.3s, height 0.3s;
441
+ }
442
+
443
+ .pad:hover {
444
+ transform: scale(0.95);
445
+ }
446
+
447
+ .pad.active {
448
+ background: var(--primary);
449
+ color: var(--on-primary);
450
+ transform: scale(0.92);
451
+ }
452
+
453
+ .pad.active::before {
454
+ width: 100px;
455
+ height: 100px;
456
+ }
457
+
458
+ /* Keyboard Renderer */
459
+ .keyboard-renderer {
460
+ padding: 20px 0;
461
+ overflow-x: auto;
462
+ -webkit-overflow-scrolling: touch;
463
+ }
464
+
465
+ .keyboard {
466
+ display: flex;
467
+ min-width: 400px;
468
+ height: 120px;
469
+ position: relative;
470
+ background: var(--surface-variant);
471
+ border-radius: 8px;
472
+ padding: 8px;
473
+ }
474
+
475
+ .key {
476
+ flex: 1;
477
+ background: var(--surface);
478
+ border: 1px solid var(--outline);
479
+ border-radius: 0 0 4px 4px;
480
+ cursor: pointer;
481
+ transition: all 0.1s;
482
+ position: relative;
483
+ margin: 0 1px;
484
+ }
485
+
486
+ .key:hover {
487
+ background: var(--surface-variant);
488
+ }
489
+
490
+ .key.active {
491
+ background: var(--primary);
492
+ transform: translateY(2px);
493
+ }
494
+
495
+ .key.black {
496
+ position: absolute;
497
+ width: 60%;
498
+ height: 65%;
499
+ background: var(--on-surface);
500
+ z-index: 2;
501
+ margin: 0 -30%;
502
+ }
503
+
504
+ .key.black.active {
505
+ background: var(--primary-variant);
506
+ }
507
+
508
+ /* Continuous Pitch Renderer */
509
+ .continuous-pitch-renderer {
510
+ height: 300px;
511
+ background: var(--surface-variant);
512
+ border-radius: 16px;
513
+ position: relative;
514
+ overflow: hidden;
515
+ cursor: crosshair;
516
+ touch-action: none;
517
+ }
518
+
519
+ .pitch-overlay {
520
+ position: absolute;
521
+ top: 0;
522
+ left: 0;
523
+ right: 0;
524
+ bottom: 0;
525
+ background: linear-gradient(
526
+ to bottom,
527
+ rgba(103, 80, 164, 0.1) 0%,
528
+ transparent 50%,
529
+ rgba(103, 80, 164, 0.1) 100%
530
+ );
531
+ }
532
+
533
+ .pitch-indicator {
534
+ position: absolute;
535
+ width: 20px;
536
+ height: 20px;
537
+ background: var(--primary);
538
+ border-radius: 50%;
539
+ transform: translate(-50%, -50%);
540
+ pointer-events: none;
541
+ box-shadow: 0 0 20px rgba(103, 80, 164, 0.5);
542
+ display: none;
543
+ }
544
+
545
+ .pitch-indicator.active {
546
+ display: block;
547
+ animation: pulseIndicator 1s infinite;
548
+ }
549
+
550
+ @keyframes pulseIndicator {
551
+ 0%, 100% { transform: translate(-50%, -50%) scale(1); }
552
+ 50% { transform: translate(-50%, -50%) scale(1.2); }
553
+ }
554
+
555
+ .pitch-grid {
556
+ position: absolute;
557
+ top: 0;
558
+ left: 0;
559
+ right: 0;
560
+ bottom: 0;
561
+ display: grid;
562
+ grid-template-columns: repeat(12, 1fr);
563
+ grid-template-rows: repeat(8, 1fr);
564
+ }
565
+
566
+ .pitch-grid-line {
567
+ border: 1px solid rgba(0, 0, 0, 0.05);
568
+ }
569
+
570
+ /* Biosensor Panel */
571
+ .biosensor-panel {
572
+ background: var(--surface);
573
+ border-radius: 16px;
574
+ padding: 20px;
575
+ margin-top: 16px;
576
+ box-shadow: var(--elevation-1);
577
+ }
578
+
579
+ .biosensor-header {
580
+ display: flex;
581
+ align-items: center;
582
+ gap: 12px;
583
+ margin-bottom: 16px;
584
+ }
585
+
586
+ .biosensor-title {
587
+ font-size: 16px;
588
+ font-weight: 600;
589
+ }
590
+
591
+ .biosensor-controls {
592
+ display: grid;
593
+ grid-template-columns: repeat(2, 1fr);
594
+ gap: 12px;
595
+ }
596
+
597
+ .biosensor-control {
598
+ display: flex;
599
+ flex-direction: column;
600
+ gap: 8px;
601
+ }
602
+
603
+ .biosensor-label {
604
+ font-size: 12px;
605
+ color: var(--on-surface-variant);
606
+ font-weight: 500;
607
+ }
608
+
609
+ .biosensor-slider {
610
+ -webkit-appearance: none;
611
+ appearance: none;
612
+ height: 4px;
613
+ background: var(--surface-variant);
614
+ border-radius: 2px;
615
+ outline: none;
616
+ }
617
+
618
+ .biosensor-slider::-webkit-slider-thumb {
619
+ -webkit-appearance: none;
620
+ appearance: none;
621
+ width: 20px;
622
+ height: 20px;
623
+ background: var(--primary);
624
+ border-radius: 50%;
625
+ cursor: pointer;
626
+ transition: all 0.2s;
627
+ }
628
+
629
+ .biosensor-slider::-webkit-slider-thumb:hover {
630
+ transform: scale(1.2);
631
+ }
632
+
633
+ .biosensor-value {
634
+ font-size: 14px;
635
+ font-weight: 500;
636
+ color: var(--primary);
637
+ }
638
+
639
+ /* Effects Panel */
640
+ .effects-panel {
641
+ background: var(--surface);
642
+ border-radius: 16px;
643
+ padding: 20px;
644
+ margin-top: 16px;
645
+ box-shadow: var(--elevation-1);
646
+ }
647
+
648
+ .effects-grid {
649
+ display: flex;
650
+ gap: 8px;
651
+ flex-wrap: wrap;
652
+ margin-top: 12px;
653
+ }
654
+
655
+ .effect-chip {
656
+ background: var(--surface-variant);
657
+ padding: 8px 16px;
658
+ border-radius: 100px;
659
+ font-size: 14px;
660
+ cursor: pointer;
661
+ transition: all 0.2s;
662
+ border: 2px solid transparent;
663
+ }
664
+
665
+ .effect-chip:hover {
666
+ border-color: var(--primary);
667
+ }
668
+
669
+ .effect-chip.active {
670
+ background: var(--primary);
671
+ color: var(--on-primary);
672
+ }
673
+
674
+ /* Bottom Navigation */
675
+ .bottom-nav {
676
+ position: fixed;
677
+ bottom: 0;
678
+ left: 0;
679
+ right: 0;
680
+ background: var(--surface);
681
+ box-shadow: 0 -2px 8px var(--shadow);
682
+ display: flex;
683
+ justify-content: space-around;
684
+ padding: 8px 0;
685
+ z-index: 100;
686
+ }
687
+
688
+ .nav-item {
689
+ display: flex;
690
+ flex-direction: column;
691
+ align-items: center;
692
+ gap: 4px;
693
+ padding: 8px 16px;
694
+ cursor: pointer;
695
+ transition: all 0.2s;
696
+ border-radius: 12px;
697
+ }
698
+
699
+ .nav-item:hover {
700
+ background: var(--surface-variant);
701
+ }
702
+
703
+ .nav-item.active {
704
+ color: var(--primary);
705
+ }
706
+
707
+ .nav-item .material-icons {
708
+ font-size: 24px;
709
+ }
710
+
711
+ .nav-label {
712
+ font-size: 12px;
713
+ font-weight: 500;
714
+ }
715
+
716
+ /* Tutorial Overlay */
717
+ .tutorial-overlay {
718
+ position: fixed;
719
+ top: 0;
720
+ left: 0;
721
+ right: 0;
722
+ bottom: 0;
723
+ background: rgba(0, 0, 0, 0.8);
724
+ display: none;
725
+ align-items: center;
726
+ justify-content: center;
727
+ z-index: 1000;
728
+ padding: 20px;
729
+ }
730
+
731
+ .tutorial-overlay.active {
732
+ display: flex;
733
+ }
734
+
735
+ .tutorial-card {
736
+ background: var(--surface);
737
+ border-radius: 24px;
738
+ padding: 32px;
739
+ max-width: 400px;
740
+ width: 100%;
741
+ text-align: center;
742
+ animation: tutorialSlide 0.4s cubic-bezier(0.4, 0, 0.2, 1);
743
+ }
744
+
745
+ @keyframes tutorialSlide {
746
+ from { opacity: 0; transform: scale(0.9) translateY(20px); }
747
+ to { opacity: 1; transform: scale(1) translateY(0); }
748
+ }
749
+
750
+ .tutorial-icon {
751
+ font-size: 64px;
752
+ color: var(--primary);
753
+ margin-bottom: 16px;
754
+ }
755
+
756
+ .tutorial-title {
757
+ font-size: 24px;
758
+ font-weight: 600;
759
+ margin-bottom: 12px;
760
+ }
761
+
762
+ .tutorial-text {
763
+ color: var(--on-surface-variant);
764
+ line-height: 1.5;
765
+ margin-bottom: 24px;
766
+ }
767
+
768
+ .tutorial-button {
769
+ background: var(--primary);
770
+ color: var(--on-primary);
771
+ border: none;
772
+ padding: 16px 32px;
773
+ border-radius: 100px;
774
+ font-size: 16px;
775
+ font-weight: 500;
776
+ cursor: pointer;
777
+ transition: all 0.2s;
778
+ }
779
+
780
+ .tutorial-button:hover {
781
+ background: var(--primary-variant);
782
+ }
783
+
784
+ /* Responsive Design */
785
+ @media (max-width: 480px) {
786
+ .header-title {
787
+ font-size: 18px;
788
+ }
789
+
790
+ .main-content {
791
+ padding: 12px;
792
+ }
793
+
794
+ .detection-result {
795
+ padding: 16px;
796
+ }
797
+
798
+ .biosensor-controls {
799
+ grid-template-columns: 1fr;
800
+ }
801
+
802
+ .effects-grid {
803
+ gap: 6px;
804
+ }
805
+
806
+ .effect-chip {
807
+ padding: 6px 12px;
808
+ font-size: 12px;
809
+ }
810
+ }
811
+
812
+ /* Loading States */
813
+ .loading-skeleton {
814
+ background: linear-gradient(90deg, var(--surface-variant) 25%, var(--surface) 50%, var(--surface-variant) 75%);
815
+ background-size: 200% 100%;
816
+ animation: loading 1.5s infinite;
817
+ border-radius: 8px;
818
+ }
819
+
820
+ @keyframes loading {
821
+ 0% { background-position: 200% 0; }
822
+ 100% { background-position: -200% 0; }
823
+ }
824
+
825
+ /* Touch Feedback */
826
+ .touch-ripple {
827
+ position: absolute;
828
+ border-radius: 50%;
829
+ background: rgba(103, 80, 164, 0.3);
830
+ transform: scale(0);
831
+ animation: ripple 0.6s ease-out;
832
+ pointer-events: none;
833
+ }
834
+
835
+ @keyframes ripple {
836
+ to {
837
+ transform: scale(4);
838
+ opacity: 0;
839
+ }
840
+ }
841
+
842
+ /* Built with Badge */
843
+ .built-with {
844
+ position: fixed;
845
+ bottom: 80px;
846
+ right: 16px;
847
+ background: var(--primary);
848
+ color: var(--on-primary);
849
+ padding: 8px 12px;
850
+ border-radius: 100px;
851
+ font-size: 12px;
852
+ text-decoration: none;
853
+ box-shadow: var(--elevation-2);
854
+ z-index: 99;
855
+ transition: all 0.2s;
856
+ }
857
+
858
+ .built-with:hover {
859
+ background: var(--primary-variant);
860
+ transform: scale(1.05);
861
+ }
862
+ </style>
863
+ </head>
864
+ <body>
865
+ <div class="app-container">
866
+ <!-- Header -->
867
+ <header class="header">
868
+ <div class="header-title">
869
+ <span class="material-icons">music_note</span>
870
+ InstrumentFromPhoto
871
+ </div>
872
+ <div class="header-actions">
873
+ <button class="icon-button" onclick="toggleTutorial()">
874
+ <span class="material-icons">help_outline</span>
875
+ </button>
876
+ <button class="icon-button" onclick="toggleSettings()">
877
+ <span class="material-icons">settings</span>
878
+ </button>
879
+ </div>
880
+ </header>
881
+
882
+ <!-- Main Content -->
883
+ <main class="main-content">
884
+ <!-- Camera Section -->
885
+ <section class="camera-section active" id="camera-section">
886
+ <div class="camera-container">
887
+ <div id="camera-view">
888
+ <div class="camera-placeholder">
889
+ <span class="material-icons">camera_alt</span>
890
+ <h3>Point camera at an instrument</h3>
891
+ <p>AI will identify and create a playable version</p>
892
+ </div>
893
+ </div>
894
+ <div class="camera-controls">
895
+ <button class="capture-button" onclick="captureInstrument()">
896
+ <span class="material-icons">photo_camera</span>
897
+ Capture Instrument
898
+ </button>
899
+ <button class="capture-button" onclick="demoInstrument()">
900
+ <span class="material-icons">auto_awesome</span>
901
+ Demo Mode
902
+ </button>
903
+ </div>
904
+ </div>
905
+ </section>
906
+
907
+ <!-- AI Processing -->
908
+ <section class="ai-processing" id="ai-processing">
909
+ <span class="material-icons processing-icon">psychology</span>
910
+ <h3>Analyzing Instrument</h3>
911
+ <p>AI is identifying and configuring your virtual instrument...</p>
912
+ </section>
913
+
914
+ <!-- Instrument Selection -->
915
+ <section class="instrument-selection" id="instrument-selection">
916
+ <div class="detection-result">
917
+ <div class="detection-header">
918
+ <div class="detection-icon">
919
+ <span class="material-icons" id="instrument-icon">guitar</span>
920
+ </div>
921
+ <div class="detection-info">
922
+ <h3 id="instrument-name">Electric Guitar</h3>
923
+ <span class="confidence-badge" id="confidence">91% confidence</span>
924
+ </div>
925
+ </div>
926
+ <p id="instrument-description">6-string fretted instrument with magnetic pickups</p>
927
+ <div class="instrument-variants" id="variants">
928
+ <span class="variant-chip" onclick="loadVariant('electric')">Electric</span>
929
+ <span class="variant-chip" onclick="loadVariant('acoustic')">Acoustic</span>
930
+ <span class="variant-chip" onclick="loadVariant('bass')">Bass</span>
931
+ </div>
932
+ </div>
933
+
934
+ <!-- Instrument Playground -->
935
+ <div class="instrument-playground">
936
+ <div class="playground-header">
937
+ <h3 class="playground-title">Virtual Instrument</h3>
938
+ <div class="playground-controls">
939
+ <button class="control-button" onclick="toggleEffects()">
940
+ <span class="material-icons">tune</span>
941
+ </button>
942
+ <button class="control-button" onclick="toggleBiosensors()">
943
+ <span class="material-icons">favorite</span>
944
+ </button>
945
+ <button class="control-button" onclick="recordPerformance()">
946
+ <span class="material-icons">fiber_manual_record</span>
947
+ </button>
948
+ </div>
949
+ </div>
950
+ <div id="instrument-renderer"></div>
951
+ </div>
952
+
953
+ <!-- Effects Panel -->
954
+ <div class="effects-panel" id="effects-panel" style="display: none;">
955
+ <div class="effects-header">
956
+ <h4>Audio Effects</h4>
957
+ </div>
958
+ <div class="effects-grid">
959
+ <span class="effect-chip" onclick="toggleEffect('distortion')">Distortion</span>
960
+ <span class="effect-chip" onclick="toggleEffect('delay')">Delay</span>
961
+ <span class="effect-chip" onclick="toggleEffect('reverb')">Reverb</span>
962
+ <span class="effect-chip" onclick="toggleEffect('chorus')">Chorus</span>
963
+ <span class="effect-chip" onclick="toggleEffect('phaser')">Phaser</span>
964
+ <span class="effect-chip" onclick="toggleEffect('flanger')">Flanger</span>
965
+ </div>
966
+ </div>
967
+
968
+ <!-- Biosensor Panel -->
969
+ <div class="biosensor-panel" id="biosensor-panel" style="display: none;">
970
+ <div class="biosensor-header">
971
+ <span class="material-icons">sensors</span>
972
+ <h4 class="biosensor-title">Biosensor Controls</h4>
973
+ </div>
974
+ <div class="biosensor-controls">
975
+ <div class="biosensor-control">
976
+ <label class="biosensor-label">EEG Alpha (Filter)</label>
977
+ <input type="range" class="biosensor-slider" id="eeg-alpha" min="0" max="127" value="64">
978
+ <span class="biosensor-value" id="eeg-alpha-value">64</span>
979
+ </div>
980
+ <div class="biosensor-control">
981
+ <label class="biosensor-label">Heart Rate (Tempo)</label>
982
+ <input type="range" class="biosensor-slider" id="heart-rate" min="60" max="180" value="120">
983
+ <span class="biosensor-value" id="heart-rate-value">120 BPM</span>
984
+ </div>
985
+ <div class="biosensor-control">
986
+ <label class="biosensor-label">Breath (Volume)</label>
987
+ <input type="range" class="biosensor-slider" id="breath" min="0" max="127" value="100">
988
+ <span class="biosensor-value" id="breath-value">100</span>
989
+ </div>
990
+ <div class="biosensor-control">
991
+ <label class="biosensor-label">Motion (Modulation)</label>
992
+ <input type="range" class="biosensor-slider" id="motion" min="0" max="127" value="64">
993
+ <span class="biosensor-value" id="motion-value">64</span>
994
+ </div>
995
+ </div>
996
+ </div>
997
+ </section>
998
+ </main>
999
+
1000
+ <!-- Bottom Navigation -->
1001
+ <nav class="bottom-nav">
1002
+ <div class="nav-item active" onclick="showSection('camera')">
1003
+ <span class="material-icons">camera_alt</span>
1004
+ <span class="nav-label">Capture</span>
1005
+ </div>
1006
+ <div class="nav-item" onclick="showSection('library')">
1007
+ <span class="material-icons">library_music</span>
1008
+ <span class="nav-label">Library</span>
1009
+ </div>
1010
+ <div class="nav-item" onclick="showSection('create')">
1011
+ <span class="material-icons">piano</span>
1012
+ <span class="nav-label">Create</span>
1013
+ </div>
1014
+ <div class="nav-item" onclick="showSection('profile')">
1015
+ <span class="material-icons">person</span>
1016
+ <span class="nav-label">Profile</span>
1017
+ </div>
1018
+ </nav>
1019
+
1020
+ <!-- Tutorial Overlay -->
1021
+ <div class="tutorial-overlay" id="tutorial-overlay">
1022
+ <div class="tutorial-card">
1023
+ <span class="material-icons tutorial-icon">music_note</span>
1024
+ <h2 class="tutorial-title">Welcome to InstrumentFromPhoto</h2>
1025
+ <p class="tutorial-text">Point your camera at any musical instrument and watch as AI creates a playable virtual version instantly!</p>
1026
+ <button class="tutorial-button" onclick="closeTutorial()">Get Started</button>
1027
+ </div>
1028
+ </div>
1029
+
1030
+ <!-- Built with Badge -->
1031
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="built-with">
1032
+ Built with anycoder
1033
+ </a>
1034
+ </div>
1035
+
1036
+ <script>
1037
+ // Audio Context and Sound Engine
1038
+ let audioContext;
1039
+ let masterGainNode;
1040
+ let currentInstrument = null;
1041
+ let activeNotes = new Map();
1042
+ let biosensorValues = {
1043
+ eegAlpha: 64,
1044
+ heartRate: 120,
1045
+ breath: 100,
1046
+ motion: 64
1047
+ };
1048
+
1049
+ // Initialize Audio Context
1050
+ function initAudio() {
1051
+ if (!audioContext) {
1052
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
1053
+ masterGainNode = audioContext.createGain();
1054
+ masterGainNode.connect(audioContext.destination);
1055
+ masterGainNode.gain.value = 0.7;
1056
+ }
1057
+ }
1058
+
1059
+ // Sound Generation Functions
1060
+ function playNote(frequency, type = 'sine', duration = 0.5) {
1061
+ initAudio();
1062
+
1063
+ const oscillator = audioContext.createOscillator();
1064
+ const gainNode = audioContext.createGain();
1065
+
1066
+ oscillator.type = type;
1067
+ oscillator.frequency.value = frequency;
1068
+
1069
+ // Apply biosensor modulation
1070
+ const breathModulation = biosensorValues.breath / 127;
1071
+ gainNode.gain.value = breathModulation * 0.3;
1072
+
1073
+ // ADSR envelope
1074
+ const now = audioContext.currentTime;
1075
+ gainNode.gain.setValueAtTime(0, now);
1076
+ gainNode.gain.linearRampToValueAtTime(breathModulation * 0.3, now + 0.01);
1077
+ gainNode.gain.exponentialRampToValueAtTime(0.001, now + duration);
1078
+
1079
+ oscillator.connect(gainNode);
1080
+ gainNode.connect(masterGainNode);
1081
+
1082
+ oscillator.start(now);
1083
+ oscillator.stop(now + duration);
1084
+
1085
+ return { oscillator, gainNode };
1086
+ }
1087
+
1088
+ function playDrum(type = 'kick') {
1089
+ initAudio();
1090
+
1091
+ const now = audioContext.currentTime;
1092
+
1093
+ if (type === 'kick') {
1094
+ const oscillator = audioContext.createOscillator();
1095
+ const gainNode = audioContext.createGain();
1096
+
1097
+ oscillator.frequency.setValueAtTime(150, now);
1098
+ oscillator.frequency.exponentialRampToValueAtTime(0.01, now + 0.5);
1099
+
1100
+ gainNode.gain.setValueAtTime(1, now);
1101
+ gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.5);
1102
+
1103
+ oscillator.connect(gainNode);
1104
+ gainNode.connect(masterGainNode);
1105
+
1106
+ oscillator.start(now);
1107
+ oscillator.stop(now + 0.5);
1108
+ } else if (type === 'snare') {
1109
+ const noiseBuffer = audioContext.createBuffer(1, audioContext.sampleRate * 0.2, audioContext.sampleRate);
1110
+ const output = noiseBuffer.getChannelData(0);
1111
+
1112
+ for (let i = 0; i < noiseBuffer.length; i++) {
1113
+ output[i] = Math.random() * 2 - 1;
1114
+ }
1115
+
1116
+ const noiseSource = audioContext.createBufferSource();
1117
+ noiseSource.buffer = noiseBuffer;
1118
+
1119
+ const noiseFilter = audioContext.createBiquadFilter();
1120
+ noiseFilter.type = 'highpass';
1121
+ noiseFilter.frequency.value = 1000;
1122
+
1123
+ const noiseGain = audioContext.createGain();
1124
+ noiseGain.gain.setValueAtTime(1, now);
1125
+ noiseGain.gain.exponentialRampToValueAtTime(0.01, now + 0.2);
1126
+
1127
+ noiseSource.connect(noiseFilter);
1128
+ noiseFilter.connect(noiseGain);
1129
+ noiseGain.connect(masterGainNode);
1130
+
1131
+ noiseSource.start(now);
1132
+ } else if (type === 'hihat') {
1133
+ const noiseBuffer = audioContext.createBuffer(1, audioContext.sampleRate * 0.05, audioContext.sampleRate);
1134
+ const output = noiseBuffer.getChannelData(0);
1135
+
1136
+ for (let i = 0; i < noiseBuffer.length; i++) {
1137
+ output[i] = Math.random() * 2 - 1;
1138
+ }
1139
+
1140
+ const noiseSource = audioContext.createBufferSource();
1141
+ noiseSource.buffer = noiseBuffer;
1142
+
1143
+ const noiseFilter = audioContext.createBiquadFilter();
1144
+ noiseFilter.type = 'highpass';
1145
+ noiseFilter.frequency.value = 5000;
1146
+
1147
+ const noiseGain = audioContext.createGain();
1148
+ noiseGain.gain.setValueAtTime(0.3, now);