Professional audio enhancement with 10-band EQ, 3D surround sound, bass boost, and spatial audio controls
Size
26.5 KB
Version
1.1.2
Created
Nov 12, 2025
Updated
about 1 month ago
1// ==UserScript==
2// @name G1EQ
3// @description Professional audio enhancement with 10-band EQ, 3D surround sound, bass boost, and spatial audio controls
4// @version 1.1.2
5// @match https://*.chatgpt.com/*
6// @icon https://cdn.oaistatic.com/assets/favicon-l4nq08hd.svg
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('ChatGPT 3D Audio Enhancer Pro - Initializing...');
12
13 // Audio processing state
14 let audioContext = null;
15 let audioSource = null;
16 let audioElements = new Map();
17 let isProcessingActive = false;
18
19 // Audio nodes
20 let nodes = {
21 splitter: null,
22 merger: null,
23 eqBands: [],
24 bassBoost: null,
25 bassTuner: null,
26 spatialLeft: null,
27 spatialRight: null,
28 surroundDelay: null,
29 surroundGain: null,
30 masterGain: null
31 };
32
33 // EQ frequencies (10 bands as requested)
34 const EQ_FREQUENCIES = [31, 62, 96, 128, 142, 196, 250, 500, 1000, 2000];
35
36 // Default settings
37 let settings = {
38 eqGains: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
39 bassBoost: 0,
40 bassTuner: 100,
41 surroundIntensity: 0,
42 surroundWidth: 50,
43 spatialBalance: 0,
44 spatialDepth: 50,
45 enabled: false
46 };
47
48 // Load saved settings
49 async function loadSettings() {
50 try {
51 const saved = await GM.getValue('audioEnhancerSettings');
52 if (saved) {
53 settings = JSON.parse(saved);
54 console.log('Loaded saved settings:', settings);
55 }
56 } catch (error) {
57 console.error('Error loading settings:', error);
58 }
59 }
60
61 // Save settings
62 async function saveSettings() {
63 try {
64 await GM.setValue('audioEnhancerSettings', JSON.stringify(settings));
65 console.log('Settings saved');
66 } catch (error) {
67 console.error('Error saving settings:', error);
68 }
69 }
70
71 // Initialize audio context and nodes
72 function initAudioContext() {
73 if (audioContext) return audioContext;
74
75 audioContext = new (window.AudioContext || window.webkitAudioContext)();
76 console.log('Audio context initialized');
77
78 // Create channel splitter and merger for stereo processing
79 nodes.splitter = audioContext.createChannelSplitter(2);
80 nodes.merger = audioContext.createChannelMerger(2);
81
82 // Create 10-band equalizer
83 EQ_FREQUENCIES.forEach((freq, index) => {
84 const filter = audioContext.createBiquadFilter();
85 filter.type = 'peaking';
86 filter.frequency.value = freq;
87 filter.Q.value = 1.0;
88 filter.gain.value = settings.eqGains[index];
89 nodes.eqBands.push(filter);
90 });
91
92 // Chain EQ bands
93 for (let i = 0; i < nodes.eqBands.length - 1; i++) {
94 nodes.eqBands[i].connect(nodes.eqBands[i + 1]);
95 }
96
97 // Bass boost filter (low shelf)
98 nodes.bassBoost = audioContext.createBiquadFilter();
99 nodes.bassBoost.type = 'lowshelf';
100 nodes.bassBoost.frequency.value = 200;
101 nodes.bassBoost.gain.value = settings.bassBoost;
102
103 // Bass tuner filter (adjustable frequency)
104 nodes.bassTuner = audioContext.createBiquadFilter();
105 nodes.bassTuner.type = 'peaking';
106 nodes.bassTuner.frequency.value = settings.bassTuner;
107 nodes.bassTuner.Q.value = 2.0;
108 nodes.bassTuner.gain.value = 0;
109
110 // 3D Surround processing nodes
111 nodes.surroundDelay = audioContext.createDelay(0.05);
112 nodes.surroundDelay.delayTime.value = 0.02;
113
114 nodes.surroundGain = audioContext.createGain();
115 nodes.surroundGain.gain.value = settings.surroundIntensity / 100;
116
117 // Spatial panning for left and right channels
118 nodes.spatialLeft = audioContext.createStereoPanner();
119 nodes.spatialLeft.pan.value = -0.5;
120
121 nodes.spatialRight = audioContext.createStereoPanner();
122 nodes.spatialRight.pan.value = 0.5;
123
124 // Master gain
125 nodes.masterGain = audioContext.createGain();
126 nodes.masterGain.gain.value = 1.0;
127
128 return audioContext;
129 }
130
131 // Connect audio element to processing chain
132 function connectAudioElement(audioElement) {
133 if (!audioContext || audioElements.has(audioElement)) return;
134
135 try {
136 const source = audioContext.createMediaElementSource(audioElement);
137
138 // Main signal path: source -> EQ chain -> bass boost -> bass tuner
139 source.connect(nodes.eqBands[0]);
140 nodes.eqBands[nodes.eqBands.length - 1].connect(nodes.bassBoost);
141 nodes.bassBoost.connect(nodes.bassTuner);
142
143 // Split into stereo channels for 3D processing
144 nodes.bassTuner.connect(nodes.splitter);
145
146 // Left channel: splitter -> spatial left -> merger
147 nodes.splitter.connect(nodes.spatialLeft, 0);
148 nodes.spatialLeft.connect(nodes.merger, 0, 0);
149
150 // Right channel: splitter -> spatial right -> merger
151 nodes.splitter.connect(nodes.spatialRight, 1);
152 nodes.spatialRight.connect(nodes.merger, 0, 1);
153
154 // Surround effect: splitter -> delay -> gain -> merger (cross-feed)
155 nodes.splitter.connect(nodes.surroundDelay, 0);
156 nodes.surroundDelay.connect(nodes.surroundGain);
157 nodes.surroundGain.connect(nodes.merger, 0, 1);
158
159 nodes.splitter.connect(nodes.surroundDelay, 1);
160 nodes.surroundDelay.connect(nodes.surroundGain);
161 nodes.surroundGain.connect(nodes.merger, 0, 0);
162
163 // Final output: merger -> master gain -> destination
164 nodes.merger.connect(nodes.masterGain);
165 nodes.masterGain.connect(audioContext.destination);
166
167 audioElements.set(audioElement, source);
168 console.log('Audio element connected to processing chain');
169 } catch (error) {
170 console.error('Error connecting audio element:', error);
171 }
172 }
173
174 // Update EQ band
175 function updateEQBand(bandIndex, gain) {
176 if (nodes.eqBands[bandIndex]) {
177 nodes.eqBands[bandIndex].gain.value = gain;
178 settings.eqGains[bandIndex] = gain;
179 saveSettings();
180 }
181 }
182
183 // Update bass boost
184 function updateBassBoost(gain) {
185 if (nodes.bassBoost) {
186 nodes.bassBoost.gain.value = gain;
187 settings.bassBoost = gain;
188 saveSettings();
189 }
190 }
191
192 // Update bass tuner frequency
193 function updateBassTuner(frequency) {
194 if (nodes.bassTuner) {
195 nodes.bassTuner.frequency.value = frequency;
196 settings.bassTuner = frequency;
197 saveSettings();
198 }
199 }
200
201 // Update 3D surround intensity
202 function updateSurroundIntensity(intensity) {
203 if (nodes.surroundGain) {
204 nodes.surroundGain.gain.value = intensity / 100;
205 settings.surroundIntensity = intensity;
206 saveSettings();
207 }
208 }
209
210 // Update surround width
211 function updateSurroundWidth(width) {
212 if (nodes.spatialLeft && nodes.spatialRight) {
213 const pan = width / 100;
214 nodes.spatialLeft.pan.value = -pan;
215 nodes.spatialRight.pan.value = pan;
216 settings.surroundWidth = width;
217 saveSettings();
218 }
219 }
220
221 // Update spatial balance
222 function updateSpatialBalance(balance) {
223 if (nodes.spatialLeft && nodes.spatialRight) {
224 const offset = balance / 100;
225 const baseWidth = settings.surroundWidth / 100;
226 nodes.spatialLeft.pan.value = -baseWidth + offset;
227 nodes.spatialRight.pan.value = baseWidth + offset;
228 settings.spatialBalance = balance;
229 saveSettings();
230 }
231 }
232
233 // Update spatial depth
234 function updateSpatialDepth(depth) {
235 if (nodes.surroundDelay) {
236 nodes.surroundDelay.delayTime.value = (depth / 100) * 0.05;
237 settings.spatialDepth = depth;
238 saveSettings();
239 }
240 }
241
242 // Monitor for audio elements
243 function monitorAudioElements() {
244 const observer = new MutationObserver(debounce(() => {
245 if (!settings.enabled) return;
246
247 const audioElements = document.querySelectorAll('audio, video');
248 audioElements.forEach(element => {
249 if (!audioElements.has(element) && element.src) {
250 console.log('New audio element detected:', element);
251 connectAudioElement(element);
252 }
253 });
254 }, 500));
255
256 observer.observe(document.body, {
257 childList: true,
258 subtree: true
259 });
260
261 console.log('Audio element monitor started');
262 }
263
264 // Debounce function
265 function debounce(func, wait) {
266 let timeout;
267 return function executedFunction(...args) {
268 const later = () => {
269 clearTimeout(timeout);
270 func(...args);
271 };
272 clearTimeout(timeout);
273 timeout = setTimeout(later, wait);
274 };
275 }
276
277 // Toggle audio processing
278 function toggleAudioProcessing(enabled) {
279 settings.enabled = enabled;
280 saveSettings();
281
282 if (enabled) {
283 initAudioContext();
284 const audioElems = document.querySelectorAll('audio, video');
285 audioElems.forEach(elem => {
286 if (elem.src) connectAudioElement(elem);
287 });
288 console.log('Audio processing enabled');
289 } else {
290 console.log('Audio processing disabled');
291 }
292 }
293
294 // Create UI
295 function createUI() {
296 // Main container
297 const container = document.createElement('div');
298 container.id = 'audio-enhancer-panel';
299 container.style.cssText = `
300 position: fixed;
301 top: 20px;
302 right: 20px;
303 width: 420px;
304 max-height: 90vh;
305 background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
306 border-radius: 16px;
307 box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
308 z-index: 999999;
309 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
310 color: #ffffff;
311 overflow: hidden;
312 display: none;
313 `;
314
315 // Header
316 const header = document.createElement('div');
317 header.style.cssText = `
318 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
319 padding: 16px 20px;
320 display: flex;
321 justify-content: space-between;
322 align-items: center;
323 cursor: move;
324 `;
325 header.innerHTML = `
326 <div style="display: flex; align-items: center; gap: 10px;">
327 <span style="font-size: 24px;">🎵</span>
328 <span style="font-weight: 600; font-size: 16px;">3D Audio Enhancer Pro</span>
329 </div>
330 <button id="close-audio-panel" style="background: rgba(255,255,255,0.2); border: none; color: white; width: 28px; height: 28px; border-radius: 50%; cursor: pointer; font-size: 18px; display: flex; align-items: center; justify-content: center;">×</button>
331 `;
332
333 // Content container with scroll
334 const content = document.createElement('div');
335 content.style.cssText = `
336 padding: 20px;
337 max-height: calc(90vh - 60px);
338 overflow-y: auto;
339 `;
340
341 // Power toggle
342 const powerSection = document.createElement('div');
343 powerSection.style.cssText = `
344 background: rgba(255, 255, 255, 0.05);
345 padding: 16px;
346 border-radius: 12px;
347 margin-bottom: 20px;
348 display: flex;
349 justify-content: space-between;
350 align-items: center;
351 `;
352 powerSection.innerHTML = `
353 <span style="font-weight: 600; font-size: 15px;">🔊 Audio Enhancement</span>
354 <label style="position: relative; display: inline-block; width: 56px; height: 28px;">
355 <input type="checkbox" id="power-toggle" ${settings.enabled ? 'checked' : ''} style="opacity: 0; width: 0; height: 0;">
356 <span style="position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 28px;"></span>
357 <span style="position: absolute; content: ''; height: 20px; width: 20px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%;"></span>
358 </label>
359 `;
360
361 // 10-Band Equalizer Section
362 const eqSection = document.createElement('div');
363 eqSection.style.cssText = `
364 background: rgba(255, 255, 255, 0.05);
365 padding: 16px;
366 border-radius: 12px;
367 margin-bottom: 20px;
368 `;
369 eqSection.innerHTML = `
370 <div style="font-weight: 600; margin-bottom: 16px; font-size: 15px; display: flex; align-items: center; gap: 8px;">
371 <span>🎚️</span>
372 <span>10-Band Equalizer</span>
373 </div>
374 <div id="eq-bands" style="display: flex; gap: 8px; justify-content: space-between;">
375 ${EQ_FREQUENCIES.map((freq, i) => `
376 <div style="flex: 1; display: flex; flex-direction: column; align-items: center; gap: 8px;">
377 <input type="range" id="eq-${i}" min="-12" max="12" step="0.5" value="${settings.eqGains[i]}" orient="vertical" style="writing-mode: bt-lr; -webkit-appearance: slider-vertical; width: 24px; height: 120px; cursor: pointer;">
378 <span style="font-size: 10px; color: #aaa;">${freq}Hz</span>
379 <span id="eq-value-${i}" style="font-size: 11px; font-weight: 600; color: #667eea;">${settings.eqGains[i]}dB</span>
380 </div>
381 `).join('')}
382 </div>
383 <button id="eq-reset" style="width: 100%; margin-top: 12px; padding: 8px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 8px; cursor: pointer; font-size: 13px;">Reset EQ</button>
384 `;
385
386 // Bass Enhancement Section
387 const bassSection = document.createElement('div');
388 bassSection.style.cssText = `
389 background: rgba(255, 255, 255, 0.05);
390 padding: 16px;
391 border-radius: 12px;
392 margin-bottom: 20px;
393 `;
394 bassSection.innerHTML = `
395 <div style="font-weight: 600; margin-bottom: 16px; font-size: 15px; display: flex; align-items: center; gap: 8px;">
396 <span>🔊</span>
397 <span>Bass Enhancement</span>
398 </div>
399 <div style="margin-bottom: 16px;">
400 <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
401 <span style="font-size: 13px; color: #ccc;">Bass Boost</span>
402 <span id="bass-boost-value" style="font-size: 13px; font-weight: 600; color: #667eea;">${settings.bassBoost}dB</span>
403 </div>
404 <input type="range" id="bass-boost" min="0" max="20" step="0.5" value="${settings.bassBoost}" style="width: 100%; cursor: pointer;">
405 </div>
406 <div>
407 <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
408 <span style="font-size: 13px; color: #ccc;">Bass Tuner Frequency</span>
409 <span id="bass-tuner-value" style="font-size: 13px; font-weight: 600; color: #667eea;">${settings.bassTuner}Hz</span>
410 </div>
411 <input type="range" id="bass-tuner" min="40" max="200" step="5" value="${settings.bassTuner}" style="width: 100%; cursor: pointer;">
412 </div>
413 `;
414
415 // 3D Surround Audio Mixer Panel
416 const surroundSection = document.createElement('div');
417 surroundSection.style.cssText = `
418 background: rgba(255, 255, 255, 0.05);
419 padding: 16px;
420 border-radius: 12px;
421 margin-bottom: 20px;
422 `;
423 surroundSection.innerHTML = `
424 <div style="font-weight: 600; margin-bottom: 16px; font-size: 15px; display: flex; align-items: center; gap: 8px;">
425 <span>🎧</span>
426 <span>3D Surround Audio Mixer</span>
427 </div>
428 <div style="margin-bottom: 16px;">
429 <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
430 <span style="font-size: 13px; color: #ccc;">Surround Intensity</span>
431 <span id="surround-intensity-value" style="font-size: 13px; font-weight: 600; color: #667eea;">${settings.surroundIntensity}%</span>
432 </div>
433 <input type="range" id="surround-intensity" min="0" max="100" step="1" value="${settings.surroundIntensity}" style="width: 100%; cursor: pointer;">
434 </div>
435 <div>
436 <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
437 <span style="font-size: 13px; color: #ccc;">Surround Width</span>
438 <span id="surround-width-value" style="font-size: 13px; font-weight: 600; color: #667eea;">${settings.surroundWidth}%</span>
439 </div>
440 <input type="range" id="surround-width" min="0" max="100" step="1" value="${settings.surroundWidth}" style="width: 100%; cursor: pointer;">
441 </div>
442 `;
443
444 // 3D Spatial Sound Control Dashboard
445 const spatialSection = document.createElement('div');
446 spatialSection.style.cssText = `
447 background: rgba(255, 255, 255, 0.05);
448 padding: 16px;
449 border-radius: 12px;
450 `;
451 spatialSection.innerHTML = `
452 <div style="font-weight: 600; margin-bottom: 16px; font-size: 15px; display: flex; align-items: center; gap: 8px;">
453 <span>🌐</span>
454 <span>3D Spatial Sound Control</span>
455 </div>
456 <div style="margin-bottom: 16px;">
457 <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
458 <span style="font-size: 13px; color: #ccc;">Spatial Balance (L/R)</span>
459 <span id="spatial-balance-value" style="font-size: 13px; font-weight: 600; color: #667eea;">${settings.spatialBalance > 0 ? 'R+' : settings.spatialBalance < 0 ? 'L+' : 'Center'}${Math.abs(settings.spatialBalance)}</span>
460 </div>
461 <input type="range" id="spatial-balance" min="-50" max="50" step="1" value="${settings.spatialBalance}" style="width: 100%; cursor: pointer;">
462 </div>
463 <div>
464 <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
465 <span style="font-size: 13px; color: #ccc;">Spatial Depth</span>
466 <span id="spatial-depth-value" style="font-size: 13px; font-weight: 600; color: #667eea;">${settings.spatialDepth}%</span>
467 </div>
468 <input type="range" id="spatial-depth" min="0" max="100" step="1" value="${settings.spatialDepth}" style="width: 100%; cursor: pointer;">
469 </div>
470 `;
471
472 // Assemble UI
473 content.appendChild(powerSection);
474 content.appendChild(eqSection);
475 content.appendChild(bassSection);
476 content.appendChild(surroundSection);
477 content.appendChild(spatialSection);
478 container.appendChild(header);
479 container.appendChild(content);
480 document.body.appendChild(container);
481
482 // Floating toggle button
483 const toggleBtn = document.createElement('button');
484 toggleBtn.id = 'audio-enhancer-toggle';
485 toggleBtn.innerHTML = '🎵';
486 toggleBtn.style.cssText = `
487 position: fixed;
488 bottom: 20px;
489 right: 20px;
490 width: 56px;
491 height: 56px;
492 border-radius: 50%;
493 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
494 border: none;
495 color: white;
496 font-size: 24px;
497 cursor: pointer;
498 box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
499 z-index: 999998;
500 transition: transform 0.2s;
501 `;
502 toggleBtn.onmouseenter = () => toggleBtn.style.transform = 'scale(1.1)';
503 toggleBtn.onmouseleave = () => toggleBtn.style.transform = 'scale(1)';
504 document.body.appendChild(toggleBtn);
505
506 // Event listeners
507 toggleBtn.addEventListener('click', () => {
508 container.style.display = container.style.display === 'none' ? 'block' : 'none';
509 });
510
511 document.getElementById('close-audio-panel').addEventListener('click', () => {
512 container.style.display = 'none';
513 });
514
515 // Power toggle with custom styling
516 const powerToggle = document.getElementById('power-toggle');
517 const powerSlider = powerToggle.nextElementSibling;
518 const powerKnob = powerSlider.nextElementSibling;
519
520 powerToggle.addEventListener('change', (e) => {
521 const enabled = e.target.checked;
522 if (enabled) {
523 powerSlider.style.backgroundColor = '#667eea';
524 powerKnob.style.transform = 'translateX(28px)';
525 } else {
526 powerSlider.style.backgroundColor = '#ccc';
527 powerKnob.style.transform = 'translateX(0)';
528 }
529 toggleAudioProcessing(enabled);
530 });
531
532 // Initialize power toggle appearance
533 if (settings.enabled) {
534 powerSlider.style.backgroundColor = '#667eea';
535 powerKnob.style.transform = 'translateX(28px)';
536 }
537
538 // EQ band controls
539 EQ_FREQUENCIES.forEach((freq, i) => {
540 const slider = document.getElementById(`eq-${i}`);
541 const valueDisplay = document.getElementById(`eq-value-${i}`);
542 slider.addEventListener('input', (e) => {
543 const value = parseFloat(e.target.value);
544 valueDisplay.textContent = `${value}dB`;
545 updateEQBand(i, value);
546 });
547 });
548
549 // EQ reset button
550 document.getElementById('eq-reset').addEventListener('click', () => {
551 EQ_FREQUENCIES.forEach((freq, i) => {
552 document.getElementById(`eq-${i}`).value = 0;
553 document.getElementById(`eq-value-${i}`).textContent = '0dB';
554 updateEQBand(i, 0);
555 });
556 });
557
558 // Bass boost control
559 const bassBoostSlider = document.getElementById('bass-boost');
560 const bassBoostValue = document.getElementById('bass-boost-value');
561 bassBoostSlider.addEventListener('input', (e) => {
562 const value = parseFloat(e.target.value);
563 bassBoostValue.textContent = `${value}dB`;
564 updateBassBoost(value);
565 });
566
567 // Bass tuner control
568 const bassTunerSlider = document.getElementById('bass-tuner');
569 const bassTunerValue = document.getElementById('bass-tuner-value');
570 bassTunerSlider.addEventListener('input', (e) => {
571 const value = parseInt(e.target.value);
572 bassTunerValue.textContent = `${value}Hz`;
573 updateBassTuner(value);
574 });
575
576 // Surround intensity control
577 const surroundIntensitySlider = document.getElementById('surround-intensity');
578 const surroundIntensityValue = document.getElementById('surround-intensity-value');
579 surroundIntensitySlider.addEventListener('input', (e) => {
580 const value = parseInt(e.target.value);
581 surroundIntensityValue.textContent = `${value}%`;
582 updateSurroundIntensity(value);
583 });
584
585 // Surround width control
586 const surroundWidthSlider = document.getElementById('surround-width');
587 const surroundWidthValue = document.getElementById('surround-width-value');
588 surroundWidthSlider.addEventListener('input', (e) => {
589 const value = parseInt(e.target.value);
590 surroundWidthValue.textContent = `${value}%`;
591 updateSurroundWidth(value);
592 });
593
594 // Spatial balance control
595 const spatialBalanceSlider = document.getElementById('spatial-balance');
596 const spatialBalanceValue = document.getElementById('spatial-balance-value');
597 spatialBalanceSlider.addEventListener('input', (e) => {
598 const value = parseInt(e.target.value);
599 const label = value > 0 ? `R+${value}` : value < 0 ? `L+${Math.abs(value)}` : 'Center';
600 spatialBalanceValue.textContent = label;
601 updateSpatialBalance(value);
602 });
603
604 // Spatial depth control
605 const spatialDepthSlider = document.getElementById('spatial-depth');
606 const spatialDepthValue = document.getElementById('spatial-depth-value');
607 spatialDepthSlider.addEventListener('input', (e) => {
608 const value = parseInt(e.target.value);
609 spatialDepthValue.textContent = `${value}%`;
610 updateSpatialDepth(value);
611 });
612
613 // Make header draggable
614 makeDraggable(container, header);
615
616 console.log('UI created successfully');
617 }
618
619 // Make element draggable
620 function makeDraggable(element, handle) {
621 let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
622
623 handle.onmousedown = dragMouseDown;
624
625 function dragMouseDown(e) {
626 e.preventDefault();
627 pos3 = e.clientX;
628 pos4 = e.clientY;
629 document.onmouseup = closeDragElement;
630 document.onmousemove = elementDrag;
631 }
632
633 function elementDrag(e) {
634 e.preventDefault();
635 pos1 = pos3 - e.clientX;
636 pos2 = pos4 - e.clientY;
637 pos3 = e.clientX;
638 pos4 = e.clientY;
639 element.style.top = (element.offsetTop - pos2) + 'px';
640 element.style.left = (element.offsetLeft - pos1) + 'px';
641 element.style.right = 'auto';
642 }
643
644 function closeDragElement() {
645 document.onmouseup = null;
646 document.onmousemove = null;
647 }
648 }
649
650 // Initialize extension
651 async function init() {
652 console.log('Initializing ChatGPT 3D Audio Enhancer Pro...');
653
654 await loadSettings();
655 createUI();
656 monitorAudioElements();
657
658 if (settings.enabled) {
659 initAudioContext();
660 toggleAudioProcessing(true);
661 }
662
663 console.log('ChatGPT 3D Audio Enhancer Pro initialized successfully!');
664 }
665
666 // Wait for page to load
667 if (document.readyState === 'loading') {
668 document.addEventListener('DOMContentLoaded', init);
669 } else {
670 init();
671 }
672})();