zeroed-some/cue-web / 7be5951

Browse files

iniital attempts at live feedback

Authored by espadonne
SHA
7be5951d533514c8ed48ce99b66c4010b9b251db
Parents
3c3843d
Tree
956ad48

3 changed files

StatusFile+-
M index.html 1 0
M js/app.js 31 0
M js/audio-engine.js 42 0
index.htmlmodified
@@ -15,6 +15,7 @@
1515
         <section class="controls">
1616
             <div class="control-group">
1717
                 <button id="startCamera" class="btn btn-primary">Start Camera</button>
18
+                <button id="microphoneToggle" class="btn btn-warning" disabled>Start Microphone</button>
1819
                 <select id="audioSelect" class="select">
1920
                     <option value="">Select Audio File...</option>
2021
                     <option value="__demo__">Generated Demo</option>
js/app.jsmodified
@@ -144,6 +144,9 @@ class GestureDSPApp {
144144
         // Camera control
145145
         document.getElementById('startCamera').addEventListener('click', () => this.startCamera());
146146
         
147
+        // Microphone control
148
+        document.getElementById('microphoneToggle').addEventListener('click', () => this.toggleMicrophone());
149
+        
147150
         // Audio selection
148151
         document.getElementById('audioSelect').addEventListener('change', async (e) => {
149152
             const value = e.target.value;
@@ -324,12 +327,40 @@ class GestureDSPApp {
324327
             await this.gestureDetector.start();
325328
             this.updateStatus('Camera active - wear colored gloves!');
326329
             document.getElementById('startCamera').disabled = true;
330
+            document.getElementById('microphoneToggle').disabled = false;
327331
         } catch (err) {
328332
             console.error('Error starting camera:', err);
329333
             this.updateStatus('Camera access denied');
330334
         }
331335
     }
332336
     
337
+    async toggleMicrophone() {
338
+        const micBtn = document.getElementById('microphoneToggle');
339
+        
340
+        try {
341
+            if (this.audioEngine.isMicrophoneActive) {
342
+                this.audioEngine.stopMicrophone();
343
+                micBtn.textContent = 'Start Microphone';
344
+                micBtn.className = 'btn btn-warning';
345
+                this.updateStatus('Microphone stopped');
346
+            } else {
347
+                await this.audioEngine.startMicrophone();
348
+                micBtn.textContent = 'Stop Microphone';
349
+                micBtn.className = 'btn btn-danger';
350
+                this.updateStatus('Live microphone active! Use gestures to control effects.');
351
+            }
352
+        } catch (err) {
353
+            console.error('Microphone error:', err);
354
+            if (err.name === 'NotAllowedError') {
355
+                this.updateStatus('Microphone permission denied. Please allow microphone access.');
356
+            } else if (err.name === 'NotFoundError') {
357
+                this.updateStatus('No microphone found. Please connect a microphone.');
358
+            } else {
359
+                this.updateStatus('Microphone error: ' + err.message);
360
+            }
361
+        }
362
+    }
363
+    
333364
     togglePlayback() {
334365
         if (this.audioEngine.isPlaying) {
335366
             this.audioEngine.stop();
js/audio-engine.jsmodified
@@ -8,6 +8,11 @@ export class AudioEngine {
88
         this.isPlaying = false;
99
         this.audioBuffer = null;
1010
         
11
+        // Microphone support
12
+        this.microphoneStream = null;
13
+        this.microphoneSource = null;
14
+        this.isMicrophoneActive = false;
15
+        
1116
         this.currentEffectIndex = 0;
1217
         this.currentParam = 0.5;
1318
         this.rawParam = 0.5;
@@ -436,6 +441,43 @@ export class AudioEngine {
436441
         }
437442
     }
438443
     
444
+    async startMicrophone() {
445
+        try {
446
+            await this.init();
447
+            
448
+            this.microphoneStream = await navigator.mediaDevices.getUserMedia({ 
449
+                audio: {
450
+                    echoCancellation: false,
451
+                    noiseSuppression: false,
452
+                    autoGainControl: false
453
+                } 
454
+            });
455
+            
456
+            this.microphoneSource = this.audioContext.createMediaStreamSource(this.microphoneStream);
457
+            this.microphoneSource.connect(this.inputGain);
458
+            
459
+            this.isMicrophoneActive = true;
460
+            return true;
461
+        } catch (err) {
462
+            console.error('Error starting microphone:', err);
463
+            throw err;
464
+        }
465
+    }
466
+    
467
+    stopMicrophone() {
468
+        if (this.microphoneSource) {
469
+            this.microphoneSource.disconnect();
470
+            this.microphoneSource = null;
471
+        }
472
+        
473
+        if (this.microphoneStream) {
474
+            this.microphoneStream.getTracks().forEach(track => track.stop());
475
+            this.microphoneStream = null;
476
+        }
477
+        
478
+        this.isMicrophoneActive = false;
479
+    }
480
+    
439481
     play() {
440482
         if (!this.audioBuffer) return;
441483