File size: 9,169 Bytes
2770657
 
 
 
ff37766
 
2770657
 
 
 
ff37766
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2770657
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ff37766
2770657
 
 
 
 
ff37766
 
 
 
 
 
 
 
 
 
2770657
ff37766
 
 
2770657
ff37766
 
2770657
 
 
 
ff37766
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2770657
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ff37766
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

// Import WaveSurfer for waveform visualization
import WaveSurfer from 'https://unpkg.com/wavesurfer.js@7/dist/wavesurfer.esm.js';

// Main application script
document.addEventListener('DOMContentLoaded', () => {
    // Initialize waveform visualizers
    let originalWaveform, processedWaveform;
    let originalAudioBlob = null;
// Initialize audio context for recording
    let audioContext;
    let mediaRecorder;
    let audioChunks = [];
    
    // DOM elements
    const recordBtn = document.getElementById('recordBtn');
    const audioUpload = document.getElementById('audioUpload');
    const resultsContainer = document.getElementById('resultsContainer');
    
    // Record button functionality
    recordBtn.addEventListener('click', async () => {
        try {
            if (mediaRecorder && mediaRecorder.state === 'recording') {
                // Stop recording
                mediaRecorder.stop();
                recordBtn.innerHTML = '<i data-feather="mic" class="w-4 h-4 mr-2"></i> Record Audio';
                recordBtn.classList.remove('bg-red-600');
                recordBtn.classList.add('bg-purple-600', 'hover:bg-purple-700');
                feather.replace();
                return;
            }
            
            // Start recording
            const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
            audioContext = new (window.AudioContext || window.webkitAudioContext)();
            mediaRecorder = new MediaRecorder(stream);
            
            mediaRecorder.ondataavailable = (event) => {
                audioChunks.push(event.data);
            };
            
            mediaRecorder.onstop = async () => {
                const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
                audioChunks = [];
                
                // Simulate processing
                simulateProcessing(audioBlob);
            };
            
            mediaRecorder.start();
            recordBtn.innerHTML = '<i data-feather="square" class="w-4 h-4 mr-2"></i> Stop Recording';
            recordBtn.classList.remove('bg-purple-600', 'hover:bg-purple-700');
            recordBtn.classList.add('bg-red-600');
            feather.replace();
            
        } catch (error) {
            console.error('Error accessing microphone:', error);
            alert('Error accessing microphone. Please ensure you have granted permission.');
        }
    });
    // Track current filename
    let currentFilename = 'processed_audio';
    
    // File upload functionality
    audioUpload.addEventListener('change', (event) => {
        const file = event.target.files[0];
        if (file) {
            currentFilename = file.name.replace(/\.[^/.]+$/, "") || 'processed_audio';
            const audioBlob = new Blob([file], { type: file.type });
            simulateProcessing(audioBlob);
        }
    });
    // Initialize WaveSurfer instances
    function initWaveforms() {
        originalWaveform = WaveSurfer.create({
            container: '#originalWaveform',
            waveColor: '#9f7aea',
            progressColor: '#d6bcfa',
            height: 80,
            barWidth: 2,
            barRadius: 3,
            cursorWidth: 1,
            cursorColor: '#fff',
            interact: false
        });

        processedWaveform = WaveSurfer.create({
            container: '#processedWaveform',
            waveColor: '#4c9faf',
            progressColor: '#88d1e1',
            height: 80,
            barWidth: 2,
            barRadius: 3,
            cursorWidth: 1,
            cursorColor: '#fff',
            interact: false
        });
    }

    // Simulate processing with comparison
    function simulateProcessing(audioBlob) {
        // Store original audio for comparison
        originalAudioBlob = audioBlob;
        
        // Show compare button
        document.getElementById('compareBtn').classList.remove('hidden');
resultsContainer.innerHTML = `
            <div class="text-center">
                <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-purple-500 mx-auto mb-4"></div>
                <p class="font-medium">Processing your audio with AI...</p>
            </div>
        `;
        
        setTimeout(() => {
            const audioUrl = URL.createObjectURL(audioBlob);
            resultsContainer.innerHTML = `
                <audio controls class="w-full mb-4" id="processedAudio">
                    <source src="${audioUrl}" type="audio/wav">
                    Your browser does not support the audio element.
                </audio>
                <p class="text-sm text-gray-300">Processing complete!</p>
            `;
            
            // Load the processed audio for waveform
            const processedAudio = document.getElementById('processedAudio');
            processedWaveform.load(processedAudio);
// Enable download and share buttons
            const buttons = document.querySelectorAll('#resultsContainer + div button');
            buttons.forEach(btn => {
                btn.disabled = false;
                if (btn.querySelector('i[data-feather="download"]')) {
                    btn.onclick = () => downloadProcessedAudio(audioUrl, currentFilename);
                }
            });
}, 3000);
    }
    // Process button functionality
    const processBtn = document.getElementById('processBtn');
    const processingSelect = document.querySelector('select');
    
    processBtn.addEventListener('click', () => {
        if (audioChunks.length > 0 || audioUpload.files.length > 0) {
            const processingType = processingSelect.value;
            const audioBlob = audioChunks.length > 0 
                ? new Blob(audioChunks, { type: 'audio/wav' }) 
                : new Blob([audioUpload.files[0]], { type: audioUpload.files[0].type });
            
            simulateProcessing(audioBlob, processingType);
        } else {
            alert('Please record or upload audio first');
        }
    });

    // Initialize tooltips
document.querySelectorAll('[data-tooltip]').forEach(element => {
        element.addEventListener('mouseenter', () => {
            const tooltip = document.createElement('div');
            tooltip.className = 'absolute z-10 bg-black text-white text-xs px-2 py-1 rounded mt-1';
            tooltip.textContent = element.dataset.tooltip;
            element.appendChild(tooltip);
            
            element.addEventListener('mouseleave', () => {
                tooltip.remove();
            }, { once: true });
        });
    });
});
    // Compare audio functionality
    document.getElementById('compareBtn').addEventListener('click', () => {
        const comparisonSection = document.getElementById('comparisonSection');
        comparisonSection.classList.toggle('hidden');
        
        if (!comparisonSection.classList.contains('hidden')) {
            // Create original audio element
            const originalUrl = URL.createObjectURL(originalAudioBlob);
            const originalAudio = document.createElement('audio');
            originalAudio.controls = true;
            originalAudio.innerHTML = `<source src="${originalUrl}" type="audio/wav">`;
            
            // Replace the placeholder
            const originalContainer = comparisonSection.querySelector('#originalWaveform').parentNode;
            originalContainer.querySelector('audio').replaceWith(originalAudio);
            
            // Load waveforms
            originalWaveform.load(originalAudio);
            processedWaveform.load(document.getElementById('processedAudio'));
        }
    });

    // Initialize waveforms after DOM loads
    initWaveforms();

// SpeechBrain integration placeholder
async function processWithSpeechBrain(audioBlob) {
    // This would be replaced with actual SpeechBrain API calls
    console.log('Processing with SpeechBrain...');
    return audioBlob; // Return processed audio
}
// Download processed audio with modified filename
function downloadProcessedAudio(audioUrl, originalName) {
    const link = document.createElement('a');
    link.href = audioUrl;
    link.download = `${originalName}_enhanced.wav`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

// SciPy integration placeholder with noise reduction
async function processWithSciPy(audioBlob, processingType) {
    console.log(`Processing with SciPy - ${processingType}...`);
    
    // Simulate different processing based on selection
    switch(processingType) {
        case 'Speech Enhancement (Noise Reduction)':
            console.log('Applying spectral gating and Wiener filtering...');
            break;
        case 'Speech Enhancement (Vocal Isolation)':
            console.log('Applying harmonic-percussive source separation...');
            break;
        case 'Speech Enhancement (Background Masking)':
            console.log('Applying spectral masking and ambient reduction...');
            break;
        default:
            console.log('Standard processing...');
    }
    
    return audioBlob; // Return processed audio
}