Please bookmark this page to avoid losing your image tool!

Audio To Photo Ringtone Creator

(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, 
    audioUrl = "https://actions.google.com/sounds/v1/alarms/digital_watch_alarm_long.ogg",
    ringtoneVolume = 0.8
) {
    // Create the main container
    const container = document.createElement('div');
    container.style.position = 'relative';
    container.style.display = 'inline-block';
    container.style.maxWidth = '100%';
    container.style.fontFamily = 'system-ui, -apple-system, sans-serif';
    container.style.overflow = 'hidden';
    container.style.borderRadius = '8px';
    container.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)';
    
    // Create and setup the canvas
    const canvas = document.createElement('canvas');
    const width = originalImg.width;
    const height = originalImg.height;
    canvas.width = width;
    canvas.height = height;
    canvas.style.maxWidth = '100%';
    canvas.style.height = 'auto';
    canvas.style.display = 'block';
    
    // Initial draw of the image
    const ctx = canvas.getContext('2d');
    ctx.drawImage(originalImg, 0, 0, width, height);
    
    // Add a slight dark tint initially
    ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
    ctx.fillRect(0, 0, width, height);
    
    container.appendChild(canvas);
    
    // Create the audio element
    const audio = document.createElement('audio');
    audio.crossOrigin = 'anonymous'; // Important for Web Audio API if grabbing external audio
    audio.src = audioUrl;
    audio.loop = true;
    audio.volume = Math.max(0, Math.min(1, Number(ringtoneVolume)));
    
    // Create interactive UI Overlay
    const uiOverlay = document.createElement('div');
    uiOverlay.style.position = 'absolute';
    uiOverlay.style.top = '0';
    uiOverlay.style.left = '0';
    uiOverlay.style.width = '100%';
    uiOverlay.style.height = '100%';
    uiOverlay.style.display = 'flex';
    uiOverlay.style.alignItems = 'center';
    uiOverlay.style.justifyContent = 'center';
    uiOverlay.style.cursor = 'pointer';
    uiOverlay.style.transition = 'background-color 0.3s';
    
    // Play/Pause Button
    const playBtn = document.createElement('div');
    playBtn.innerHTML = '▶'; // Play icon
    playBtn.style.fontSize = '64px';
    playBtn.style.color = 'white';
    playBtn.style.textShadow = '0 2px 10px rgba(0,0,0,0.6)';
    playBtn.style.transition = 'opacity 0.3s';
    
    uiOverlay.appendChild(playBtn);
    container.appendChild(uiOverlay);
    
    // Audio Visualizer Variables
    let audioCtx, analyser, source;
    let isInitialized = false;
    let isPlaying = false;
    let animationId;
    
    function initAudio() {
        try {
            audioCtx = new (window.AudioContext || window.webkitAudioContext)();
            analyser = audioCtx.createAnalyser();
            source = audioCtx.createMediaElementSource(audio);
            source.connect(analyser);
            analyser.connect(audioCtx.destination);
            analyser.fftSize = 128; // Gives 64 frequency bins
            isInitialized = true;
        } catch (e) {
            console.warn("Web Audio API could not be initialized:", e);
        }
    }
    
    function drawVisualizer() {
        if (!isPlaying) {
            // Draw static state when paused
            ctx.clearRect(0, 0, width, height);
            ctx.drawImage(originalImg, 0, 0, width, height);
            ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
            ctx.fillRect(0, 0, width, height);
            
            if (animationId) {
                cancelAnimationFrame(animationId);
                animationId = null;
            }
            return;
        }
        
        ctx.clearRect(0, 0, width, height);
        ctx.drawImage(originalImg, 0, 0, width, height);
        
        // Darken background to make visualizer pop out
        ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
        ctx.fillRect(0, 0, width, height);
        
        if (isInitialized) {
            const bufferLength = analyser.frequencyBinCount;
            const dataArray = new Uint8Array(bufferLength);
            analyser.getByteFrequencyData(dataArray);
            
            const centerX = width / 2;
            const centerY = height / 2;
            const radius = Math.min(width, height) / 4;
            
            // Draw inner circle
            ctx.lineWidth = 4;
            ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
            ctx.beginPath();
            ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
            ctx.stroke();
            
            // Draw frequency bars
            const angleStep = (2 * Math.PI) / bufferLength;
            for (let i = 0; i < bufferLength; i++) {
                // Normalize frequency value
                const v = dataArray[i] / 255.0; 
                // Max height for bars is about 1/3 of the shortest dimension
                const barHeight = v * (Math.min(width, height) / 3); 
                const angle = i * angleStep - Math.PI / 2; // Offset by -90deg to start at top
                
                const startX = centerX + Math.cos(angle) * (radius + 5);
                const startY = centerY + Math.sin(angle) * (radius + 5);
                
                const endX = centerX + Math.cos(angle) * (radius + 5 + barHeight);
                const endY = centerY + Math.sin(angle) * (radius + 5 + barHeight);
                
                ctx.strokeStyle = `hsla(${(i / bufferLength) * 360}, 100%, 65%, 0.9)`;
                ctx.lineWidth = Math.max(2, (radius * 2 * Math.PI) / bufferLength * 0.7);
                ctx.lineCap = 'round';
                
                ctx.beginPath();
                ctx.moveTo(startX, startY);
                ctx.lineTo(endX, endY);
                ctx.stroke();
            }
        }
        
        animationId = requestAnimationFrame(drawVisualizer);
    }
    
    // UI Event listeners
    uiOverlay.addEventListener('mouseenter', () => {
        playBtn.style.opacity = '1';
    });
    
    uiOverlay.addEventListener('mouseleave', () => {
        if (isPlaying) {
            playBtn.style.opacity = '0';
        }
    });
    
    uiOverlay.addEventListener('click', async () => {
        // Init audio context on first user interaction
        if (!isInitialized) {
            initAudio();
        }
        
        // Resume context per browser autoplay policies
        if (audioCtx && audioCtx.state === 'suspended') {
            await audioCtx.resume();
        }
        
        if (audio.paused) {
            try {
                await audio.play();
                isPlaying = true;
                playBtn.innerHTML = '⏸'; // Pause icon
                playBtn.style.opacity = '0'; // Hide button on play, shows on hover
                if (!animationId) {
                    drawVisualizer();
                }
            } catch (err) {
                console.error("Audio playback failed:", err);
                alert("Could not play audio. Check URL and cross-origin permissions.");
            }
        } else {
            audio.pause();
            isPlaying = false;
            playBtn.innerHTML = '▶'; // Play icon
            playBtn.style.opacity = '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

The Audio To Photo Ringtone Creator allows users to combine an image with an audio track to create an interactive visual experience. The tool overlays an audio visualizer onto a chosen photo, featuring dynamic, color-coded frequency bars that react to the sound in real-time. This is ideal for creating engaging social media content, personalized digital greeting cards, or interactive multimedia presentations where visual and auditory elements work together.

Leave a Reply

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