Please bookmark this page to avoid losing your image tool!

Audio Effects Playback And Vocoder Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg,
    carrierUrl = 'https://cdn.freesound.org/previews/415/415789_6142146-lq.mp3',
    vocoderUrl = 'https://cdn.freesound.org/previews/328/328877_2334836-lq.mp3'
) {
    // --- State variables ---
    let audioContext = null;
    let carrierBuffer = null;
    let modulatorBuffer = null;
    let modulatorAnalyser = null;
    let bandData = []; // Array of { filter, gain } objects
    let carrierSource = null;
    let modulatorSource = null;
    let animationFrameId = null;
    let isPlaying = false;
    let isInitialized = false;

    // --- UI Setup ---
    const container = document.createElement('div');
    container.style.position = 'relative';
    container.style.display = 'inline-block';
    container.style.border = '1px solid #555';
    container.style.borderRadius = '8px';
    container.style.overflow = 'hidden';
    container.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
    container.style.color = 'white';
    container.style.minWidth = '250px';
    container.style.minHeight = '150px';
    container.style.textAlign = 'center';
    container.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';

    const bgImg = originalImg.cloneNode();
    bgImg.style.position = 'absolute';
    bgImg.style.top = '0';
    bgImg.style.left = '0';
    bgImg.style.width = '100%';
    bgImg.style.height = '100%';
    bgImg.style.objectFit = 'cover';
    bgImg.style.zIndex = '-1';
    container.appendChild(bgImg);

    const overlay = document.createElement('div');
    overlay.style.width = '100%';
    overlay.style.height = '100%';
    overlay.style.background = 'rgba(0, 0, 0, 0.65)';
    overlay.style.backdropFilter = 'blur(2px)';
    overlay.style.display = 'flex';
    overlay.style.flexDirection = 'column';
    overlay.style.justifyContent = 'center';
    overlay.style.alignItems = 'center';
    overlay.style.padding = '15px';
    overlay.style.boxSizing = 'border-box';
    container.appendChild(overlay);
    
    const title = document.createElement('h3');
    title.textContent = 'Audio Vocoder';
    title.style.margin = '0 0 15px 0';
    title.style.fontWeight = 'normal';
    title.style.textShadow = '1px 1px 2px black';
    overlay.appendChild(title);

    const playButton = document.createElement('button');
    playButton.textContent = 'Play Vocoder';
    playButton.style.padding = '10px 20px';
    playButton.style.fontSize = '16px';
    playButton.style.cursor = 'pointer';
    playButton.style.backgroundColor = '#4CAF50';
    playButton.style.color = 'white';
    playButton.style.border = 'none';
    playButton.style.borderRadius = '5px';
    playButton.style.marginBottom = '10px';
    playButton.style.transition = 'background-color 0.2s';
    overlay.appendChild(playButton);

    const statusLabel = document.createElement('p');
    statusLabel.textContent = 'Ready to initialize.';
    statusLabel.style.margin = '0';
    statusLabel.style.fontSize = '14px';
    statusLabel.style.textShadow = '1px 1px 2px black';
    statusLabel.style.minHeight = '1.2em';
    overlay.appendChild(statusLabel);

    // --- Audio Helper Functions ---
    const loadAudioBuffer = async (url, context) => {
        const response = await fetch(url, { mode: 'cors' });
        if (!response.ok) {
            throw new Error(`Failed to fetch audio (${response.status})`);
        }
        const arrayBuffer = await response.arrayBuffer();
        return await context.decodeAudioData(arrayBuffer);
    };

    const initializeAudio = async () => {
        if (isInitialized) return true;
        playButton.disabled = true;

        statusLabel.textContent = 'Initializing Audio Context...';
        audioContext = new (window.AudioContext || window.webkitAudioContext)();

        try {
            statusLabel.textContent = 'Loading audio files...';
            [carrierBuffer, modulatorBuffer] = await Promise.all([
                loadAudioBuffer(carrierUrl, audioContext),
                loadAudioBuffer(vocoderUrl, audioContext)
            ]);
        } catch (error) {
            statusLabel.textContent = `Error: ${error.message}. Check CORS.`;
            console.error("Audio loading error:", error);
            audioContext = null;
            playButton.disabled = false;
            return false;
        }

        modulatorAnalyser = audioContext.createAnalyser();
        modulatorAnalyser.fftSize = 2048;

        const numBands = 32;
        const minFreq = 100;
        const maxFreq = audioContext.sampleRate / 2 * 0.9; // Up to near Nyquist
        const logMin = Math.log(minFreq);
        const logMax = Math.log(maxFreq);
        const logRange = logMax - logMin;

        for (let i = 0; i < numBands; i++) {
            const freq = Math.exp(logMin + logRange * (i / (numBands - 1)));
            const filter = audioContext.createBiquadFilter();
            filter.type = 'bandpass';
            filter.frequency.value = freq;
            filter.Q.value = 10.0;
            const gain = audioContext.createGain();
            gain.gain.value = 0.0;
            filter.connect(gain);
            gain.connect(audioContext.destination);
            bandData.push({ filter, gain });
        }

        isInitialized = true;
        statusLabel.textContent = 'Ready to play.';
        playButton.disabled = false;
        return true;
    };

    const updateGains = () => {
        if (!isPlaying || !modulatorAnalyser) return;
        const frequencyData = new Uint8Array(modulatorAnalyser.frequencyBinCount);
        modulatorAnalyser.getByteFrequencyData(frequencyData);
        const nyquist = audioContext.sampleRate / 2;
        bandData.forEach(band => {
            const centerFreq = band.filter.frequency.value;
            const freqIndex = Math.round((centerFreq / nyquist) * frequencyData.length);
            const amplitude = frequencyData[freqIndex] || 0;
            const gainValue = Math.pow(amplitude / 255, 2) * 2.5;
            band.gain.gain.setTargetAtTime(gainValue, audioContext.currentTime, 0.01);
        });
        animationFrameId = requestAnimationFrame(updateGains);
    };

    const play = () => {
        if (!isInitialized || isPlaying) return;

        carrierSource = audioContext.createBufferSource();
        carrierSource.buffer = carrierBuffer;
        carrierSource.loop = true;

        modulatorSource = audioContext.createBufferSource();
        modulatorSource.buffer = modulatorBuffer;
        modulatorSource.loop = true;

        modulatorSource.connect(modulatorAnalyser);
        bandData.forEach(band => carrierSource.connect(band.filter));

        carrierSource.start(0);
        modulatorSource.start(0);
        isPlaying = true;

        statusLabel.textContent = 'Playing...';
        playButton.textContent = 'Stop';
        playButton.style.backgroundColor = '#f44336';
        updateGains();
    };

    const stop = () => {
        if (!isPlaying) return;

        carrierSource?.stop(0);
        modulatorSource?.stop(0);

        if (animationFrameId) {
            cancelAnimationFrame(animationFrameId);
            animationFrameId = null;
        }

        bandData.forEach(band => band.gain.gain.setTargetAtTime(0, audioContext.currentTime, 0.02));
        isPlaying = false;

        statusLabel.textContent = 'Stopped.';
        playButton.textContent = 'Play Vocoder';
        playButton.style.backgroundColor = '#4CAF50';
    };

    // --- Event Listener ---
    playButton.addEventListener('click', async () => {
        if (!isInitialized) {
            const success = await initializeAudio();
            if (!success) return;
        }

        if (audioContext.state === 'suspended') {
            await audioContext.resume();
        }

        isPlaying ? stop() : play();
    });

    return container;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Audio Effects Playback and Vocoder Tool offers a unique way to combine audio processing with interactive playback. By utilizing two audio sources, a carrier signal and a modulator signal, users can create vocoder effects that modulate one audio track with another. This tool is ideal for musicians, sound designers, and audio enthusiasts looking to experiment with sound synthesis and audio effects in real-time. With a simple interface, users can easily initialize the audio context, load audio files, and play or stop the vocoder effect with a click of a button. It’s perfect for enhancing live performances, creating unique soundscapes, or just having fun with audio manipulation.

Leave a Reply

Your email address will not be published. Required fields are marked *