Please bookmark this page to avoid losing your image tool!

Image To Animal Sound Effects Voice Changer

(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.
function processImage(originalImg, animalType = "auto", effectIntensity = "1.0") {
    // Determine scale and size for the display
    const MAX_WIDTH = 600;
    const scale = Math.min(1, MAX_WIDTH / originalImg.width);
    const canvasWidth = originalImg.width * scale;
    const canvasHeight = originalImg.height * scale;

    // Create main container
    const container = document.createElement("div");
    container.style.position = "relative";
    container.style.display = "inline-block";
    container.style.fontFamily = "system-ui, -apple-system, sans-serif";
    container.style.overflow = "hidden";
    container.style.borderRadius = "8px";
    container.style.boxShadow = "0 4px 6px rgba(0,0,0,0.1)";
    container.style.width = canvasWidth + "px";
    container.style.height = canvasHeight + "px";
    container.style.backgroundColor = "#000";

    // Setup Canvas
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    container.appendChild(canvas);

    // Image Analysis for Animal Type Detection
    let activeAnimal = animalType.toLowerCase();
    if (activeAnimal === "auto") {
        const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
        let r = 0, g = 0, b = 0;
        
        // Sample pixels to compute average color
        for (let i = 0; i < imgData.length; i += 16) { // Sample every 4th pixel for speed
            r += imgData[i];
            g += imgData[i + 1];
            b += imgData[i + 2];
        }
        
        const pixels = imgData.length / 16;
        r /= pixels; g /= pixels; b /= pixels;

        const avg = (r + g + b) / 3;
        const max = Math.max(r, g, b);

        if (max === g && g > r + 20 && g > b + 20) activeAnimal = "frog";
        else if (max === b && b > r + 30 && b > g + 30) activeAnimal = "bird";
        else if (avg < 80) activeAnimal = "bear";
        else if (avg > 180) activeAnimal = "cat";
        else activeAnimal = "dog";
    }

    const validAnimals = ["cat", "dog", "bear", "bird", "frog"];
    if (!validAnimals.includes(activeAnimal)) activeAnimal = "cat";

    // Badge showing current status
    const badge = document.createElement("div");
    badge.style.position = "absolute";
    badge.style.top = "10px";
    badge.style.left = "10px";
    badge.style.backgroundColor = "rgba(0,0,0,0.6)";
    badge.style.color = "white";
    badge.style.padding = "5px 10px";
    badge.style.borderRadius = "20px";
    badge.style.fontSize = "12px";
    badge.style.zIndex = "10";
    badge.innerText = `Detected Mode: ${activeAnimal.toUpperCase()}`;
    container.appendChild(badge);

    // Create UI controls
    const uiContainer = document.createElement("div");
    uiContainer.style.position = "absolute";
    uiContainer.style.bottom = "0";
    uiContainer.style.left = "0";
    uiContainer.style.width = "100%";
    uiContainer.style.backgroundColor = "rgba(0,0,0,0.75)";
    uiContainer.style.padding = "15px";
    uiContainer.style.boxSizing = "border-box";
    uiContainer.style.display = "flex";
    uiContainer.style.flexDirection = "column";
    uiContainer.style.alignItems = "center";
    uiContainer.style.gap = "10px";

    // Selector row
    const topRow = document.createElement("div");
    topRow.style.color = "#fff";
    topRow.style.fontSize = "14px";
    topRow.style.display = "flex";
    topRow.style.alignItems = "center";
    topRow.style.gap = "10px";

    const label = document.createElement("label");
    label.innerText = "Voice Effect:";
    
    const select = document.createElement("select");
    select.style.padding = "4px 8px";
    select.style.borderRadius = "4px";
    select.style.cursor = "pointer";
    select.style.backgroundColor = "#fff";
    
    validAnimals.forEach(animal => {
        const option = document.createElement("option");
        option.value = animal;
        option.innerText = animal.charAt(0).toUpperCase() + animal.slice(1);
        if (animal === activeAnimal) option.selected = true;
        select.appendChild(option);
    });
    
    select.onchange = (e) => { 
        activeAnimal = e.target.value; 
        badge.innerText = `Selected Mode: ${activeAnimal.toUpperCase()}`;
    };

    topRow.appendChild(label);
    topRow.appendChild(select);
    uiContainer.appendChild(topRow);

    // Buttons row
    const btnRow = document.createElement("div");
    btnRow.style.display = "flex";
    btnRow.style.gap = "10px";
    
    const btnStyle = "padding: 10px 20px; border: none; border-radius: 20px; font-weight: bold; cursor: pointer; transition: all 0.2s; white-space: nowrap; user-select: none; -webkit-user-select: none;";
    
    const recordBtn = document.createElement("button");
    recordBtn.innerHTML = "🎤 Hold to Record Voice";
    recordBtn.style.cssText = btnStyle + "background-color: #ff4757; color: white;";

    const playBtn = document.createElement("button");
    playBtn.innerHTML = "â–¶ Play Back Effect";
    playBtn.style.cssText = btnStyle + "background-color: #2ed573; color: white; display: none;";

    btnRow.appendChild(recordBtn);
    btnRow.appendChild(playBtn);
    uiContainer.appendChild(btnRow);
    container.appendChild(uiContainer);

    // Audio Processing Logic
    let mediaRecorder;
    let audioChunks = [];
    let audioContext;
    let recordedAudioBuffer = null;
    let isRecording = false;
    let isPlaying = false;

    const startRecording = async () => {
        if (isRecording) return;
        
        try {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
            }
            if (audioContext.state === "suspended") {
                await audioContext.resume();
            }

            const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
            mediaRecorder = new MediaRecorder(stream);
            audioChunks = [];

            mediaRecorder.ondataavailable = e => { if (e.data.size > 0) audioChunks.push(e.data); };
            mediaRecorder.onstart = () => {
                isRecording = true;
                recordBtn.innerHTML = "🔴 Recording...";
                recordBtn.style.backgroundColor = "#ff6b81";
                playBtn.style.display = "none";
            };

            mediaRecorder.onstop = async () => {
                isRecording = false;
                recordBtn.innerHTML = "🎤 Hold to Record Voice";
                recordBtn.style.backgroundColor = "#ff4757";
                
                if (audioChunks.length === 0) return;

                const audioBlob = new Blob(audioChunks, { type: mediaRecorder.mimeType });
                const arrayBuffer = await audioBlob.arrayBuffer();

                audioContext.decodeAudioData(arrayBuffer, (buffer) => {
                    recordedAudioBuffer = buffer;
                    playBtn.style.display = "block";
                    playModifiedAudio(); 
                }, (err) => {
                    console.error("Audio decoding failed. The recording might have been too short. ", err);
                });
            };

            mediaRecorder.start();
        } catch (e) {
            alert("Microphone access is required for the Voice Changer.");
        }
    };

    const stopRecording = () => {
        if (mediaRecorder && mediaRecorder.state !== "inactive") {
            mediaRecorder.stop();
            mediaRecorder.stream.getTracks().forEach(track => track.stop());
        }
    };

    // Event listeners to handle mouse and touch
    recordBtn.addEventListener("mousedown", startRecording);
    recordBtn.addEventListener("mouseup", stopRecording);
    recordBtn.addEventListener("mouseleave", stopRecording);
    recordBtn.addEventListener("touchstart", (e) => { e.preventDefault(); startRecording(); }, { passive: false });
    recordBtn.addEventListener("touchend", (e) => { e.preventDefault(); stopRecording(); }, { passive: false });

    playBtn.addEventListener("click", () => {
        if (recordedAudioBuffer) playModifiedAudio();
    });

    function playModifiedAudio() {
        if (isPlaying || !recordedAudioBuffer) return;
        isPlaying = true;

        const intensity = parseFloat(effectIntensity) || 1.0;
        const source = audioContext.createBufferSource();
        source.buffer = recordedAudioBuffer;
        
        const analyser = audioContext.createAnalyser();
        analyser.fftSize = 256;

        let targetNode = source;

        // Apply animal effect filters and speed shifts
        switch(activeAnimal) {
            case "cat": // High pitch chipmunk
                source.playbackRate.value = 1.4 + (0.2 * intensity);
                const highpass = audioContext.createBiquadFilter();
                highpass.type = "highpass";
                highpass.frequency.value = 600 * intensity;
                source.connect(highpass);
                targetNode = highpass;
                break;

            case "dog": // Lower, rougher
                source.playbackRate.value = 0.75 - (0.1 * intensity);
                const lowpass = audioContext.createBiquadFilter();
                lowpass.type = "lowpass";
                lowpass.frequency.value = 1200 / intensity;
                source.connect(lowpass);
                targetNode = lowpass;
                break;

            case "bear": // Very low / slowed down
                source.playbackRate.value = 0.5 - (0.1 * intensity);
                const bearLowpass = audioContext.createBiquadFilter();
                bearLowpass.type = "lowpass";
                bearLowpass.frequency.value = 800;
                source.connect(bearLowpass);
                targetNode = bearLowpass;
                break;

            case "bird": // Fast and twangy resonance
                source.playbackRate.value = 1.7 + (0.3 * intensity);
                const bpeq = audioContext.createBiquadFilter();
                bpeq.type = "peaking";
                bpeq.frequency.value = 3000;
                bpeq.Q.value = 5;
                bpeq.gain.value = 15;
                source.connect(bpeq);
                targetNode = bpeq;
                break;

            case "frog": // Croaky (Tremolo effect modulated on gain)
                source.playbackRate.value = 0.85;
                const tremoloGain = audioContext.createGain();
                const lfo = audioContext.createOscillator();
                lfo.type = "sine";
                lfo.frequency.value = 18 * intensity; 
                
                const lfoGain = audioContext.createGain();
                lfoGain.gain.value = 0.5;
                lfo.connect(lfoGain);
                
                tremoloGain.gain.value = 0.5;
                lfoGain.connect(tremoloGain.gain);
                
                source.connect(tremoloGain);
                lfo.start();
                
                source.onended = () => { lfo.stop(); isPlaying = false; };
                targetNode = tremoloGain;
                break;
        }

        if (activeAnimal !== "frog") {
            source.onended = () => { isPlaying = false; };
        }

        targetNode.connect(analyser);
        analyser.connect(audioContext.destination);
        
        source.start();
        drawVisualizer(analyser);
    }

    function drawVisualizer(analyser) {
        if (!isPlaying) {
            // Restore original image once playback drops
            ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
            return;
        }
        requestAnimationFrame(() => drawVisualizer(analyser));

        const bufferLength = analyser.frequencyBinCount;
        const dataArray = new Uint8Array(bufferLength);
        analyser.getByteFrequencyData(dataArray);

        // Draw image backdrop mapping audio visual overlay
        ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        const barWidth = (canvas.width / bufferLength) * 2;
        let x = 0;

        for (let i = 0; i < bufferLength; i++) {
            const barHeight = dataArray[i];
            
            // Color mapping based on chosen creature
            let hue = 0;
            switch(activeAnimal) {
                case "cat": hue = 350; break;
                case "dog": hue = 30; break;
                case "bear": hue = 0; break;
                case "bird": hue = 200; break;
                case "frog": hue = 120; break;
            }
            
            ctx.fillStyle = `hsl(${hue}, 100%, ${activeAnimal === 'bear' ? barHeight / 4 : barHeight / 2}%)`;
            ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
            x += barWidth + 1;
        }
    }

    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

This tool allows users to upload an image and transform their voice into various animal-inspired sound effects. The tool features an intelligent detection mode that analyzes the colors and tones of your uploaded image to automatically suggest a suitable animal effect, such as a cat, dog, bear, bird, or frog. Users can record their voice directly through the interface, apply different animal voice filters with adjustable intensity, and view a real-time audio visualizer that overlays dynamic, color-coded frequency bars on top of their image during playback. It is an ideal tool for creating fun social media content, making prank recordings, or adding whimsical elements to digital presentations.

Leave a Reply

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