Soundcloud Audio Equalizer Bass Booster GUI UPDATE

Applies EQ (high-shelf, low-shelf, gain) for SoundCloud with a red EQ button, matte black GUI, and red knobs.

// ==UserScript==
// @name         Soundcloud Audio Equalizer Bass Booster GUI UPDATE
// @namespace    http://tampermonkey.net/
// @version      2.5
// @description  Applies EQ (high-shelf, low-shelf, gain) for SoundCloud with a red EQ button, matte black GUI, and red knobs.
// @author       MARSE
// @match        *://soundcloud.com/*
// @license      Marse9008
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const DEFAULT_GAIN = 0.1;
    const DEFAULT_TREBLE = 0.1;
    const DEFAULT_BASS = 0.1;

    const OriginalAudioContext = window.AudioContext || window.webkitAudioContext;
    if (!OriginalAudioContext) {
        return;
    }

    // Create GUI container (Matte Black background, no transparency)
    const guiContainer = document.createElement('div');
    guiContainer.style.position = 'fixed';
    guiContainer.style.left = '0';
    guiContainer.style.top = '80px';  // Adjusted to lower the GUI
    guiContainer.style.width = '250px';
    guiContainer.style.height = '300px';
    guiContainer.style.backgroundColor = '#1e1e1e'; // Matte black background
    guiContainer.style.padding = '10px';
    guiContainer.style.display = 'none'; // Initially hidden
    guiContainer.style.zIndex = '1000';
    guiContainer.style.color = 'white';
    guiContainer.style.borderRadius = '10px';
    guiContainer.style.boxShadow = '0 0 15px rgba(0, 0, 0, 0.8)';
    guiContainer.style.opacity = '1'; // No transparency

    // Create minimize button (Red)
    const minimizeButton = document.createElement('button');
    minimizeButton.textContent = 'Minimize';
    minimizeButton.style.position = 'absolute';
    minimizeButton.style.bottom = '10px';  // Moved to bottom-right
    minimizeButton.style.right = '10px';
    minimizeButton.style.backgroundColor = '#ff0000'; // Red minimize button
    minimizeButton.style.color = 'white';
    minimizeButton.style.border = 'none';
    minimizeButton.style.padding = '8px 12px';
    minimizeButton.style.cursor = 'pointer';
    minimizeButton.style.fontSize = '14px';
    minimizeButton.style.borderRadius = '5px';
    guiContainer.appendChild(minimizeButton);

    minimizeButton.addEventListener('click', () => {
        guiContainer.style.display = 'none';
    });

    // Create EQ button to toggle the GUI
    const eqButton = document.createElement('button');
    eqButton.textContent = 'EQ';
    eqButton.style.position = 'fixed';
    eqButton.style.left = '0';
    eqButton.style.top = '10px';
    eqButton.style.zIndex = '1001';
    eqButton.style.backgroundColor = '#ff0000'; // Red EQ button
    eqButton.style.color = 'white';
    eqButton.style.border = 'none';
    eqButton.style.padding = '10px 15px';
    eqButton.style.fontSize = '16px';
    eqButton.style.cursor = 'pointer';
    eqButton.style.transition = 'background-color 0.3s ease';
    eqButton.style.borderRadius = '5px';
    document.body.appendChild(eqButton);

    eqButton.addEventListener('click', () => {
        guiContainer.style.display = guiContainer.style.display === 'none' ? 'block' : 'none';
    });

    // Create sliders for Bass, Treble, and Gain with Red knobs and red labels
    const createSlider = (label, min, max, defaultValue) => {
        const sliderContainer = document.createElement('div');
        sliderContainer.style.marginBottom = '20px';

        const sliderLabel = document.createElement('label');
        sliderLabel.textContent = label;
        sliderLabel.style.display = 'block';
        sliderLabel.style.marginBottom = '5px';
        sliderLabel.style.color = '#ff0000'; // Red labels for Bass, Treble, and Gain

        const slider = document.createElement('input');
        slider.type = 'range';
        slider.min = min;
        slider.max = max;
        slider.value = defaultValue;
        slider.step = '0.1'; // Set step size to 0.1 for smooth increments
        slider.style.width = '100%';
        slider.style.backgroundColor = '#555';
        slider.style.borderRadius = '10px';
        slider.style.height = '8px';
        slider.style.webkitAppearance = 'none';
        slider.style.transition = 'background-color 0.3s ease';

        // Red knobs (slider thumb color)
        slider.style['-webkit-appearance'] = 'none';
        slider.style['appearance'] = 'none';
        slider.style.border = 'none';
        slider.style.height = '15px';
        slider.style.backgroundColor = '#ff0000'; // Red color for the knob
        slider.style.borderRadius = '50%';

        slider.addEventListener('mouseover', () => {
            slider.style.backgroundColor = '#cc0000'; // Darker red when hovering
        });
        slider.addEventListener('mouseout', () => {
            slider.style.backgroundColor = '#ff0000'; // Restore red when not hovering
        });

        sliderContainer.appendChild(sliderLabel);
        sliderContainer.appendChild(slider);

        return {
            sliderContainer,
            slider
        };
    };

    const bassControl = createSlider('Bass', 1, 20, DEFAULT_BASS);
    const trebleControl = createSlider('Treble', 1, 15, DEFAULT_TREBLE);
    const gainControl = createSlider('Gain', 1, 5, DEFAULT_GAIN);

    guiContainer.appendChild(bassControl.sliderContainer);
    guiContainer.appendChild(trebleControl.sliderContainer);
    guiContainer.appendChild(gainControl.sliderContainer);

    document.body.appendChild(guiContainer);

    // Create AudioContext with filters and gain
    window.AudioContext = class extends OriginalAudioContext {
        constructor(...args) {
            super(...args);

            const lowShelf = this.createBiquadFilter();
            lowShelf.type = 'lowshelf';
            lowShelf.frequency.value = 200;
            lowShelf.gain.value = DEFAULT_BASS;

            const highShelf = this.createBiquadFilter();
            highShelf.type = 'highshelf';
            highShelf.frequency.value = 12000;
            highShelf.gain.value = DEFAULT_TREBLE;

            const globalGain = this.createGain();
            globalGain.gain.value = DEFAULT_GAIN;

            const originalDestination = this.destination;
            lowShelf.connect(highShelf);
            highShelf.connect(globalGain);
            globalGain.connect(originalDestination);

            const originalCreateMediaElementSource = this.createMediaElementSource.bind(this);
            this.createMediaElementSource = function (mediaElement) {
                const source = originalCreateMediaElementSource(mediaElement);
                source.connect(lowShelf);
                return source;
            };

            const originalCreateBufferSource = this.createBufferSource.bind(this);
            this.createBufferSource = function () {
                const source = originalCreateBufferSource();
                source.connect(lowShelf);
                return source;
            };

            // Listen for slider changes to update EQ
            bassControl.slider.addEventListener('input', () => {
                lowShelf.gain.value = parseFloat(bassControl.slider.value);
            });
            trebleControl.slider.addEventListener('input', () => {
                highShelf.gain.value = parseFloat(trebleControl.slider.value);
            });
            gainControl.slider.addEventListener('input', () => {
                globalGain.gain.value = parseFloat(gainControl.slider.value);
            });
        }
    };
})();