Please bookmark this page to avoid losing your image tool!

Audio And Video Carrier Vocal Manipulation 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, carrierType = 'sawtooth', carrierFrequency = 110, numBands = 64, duration = 5, gain = 0.5) {

    /**
     * Helper function to convert an AudioBuffer to a WAV audio format Blob.
     * @param {AudioBuffer} abuffer The audio buffer to convert.
     * @returns {Blob} A blob containing the WAV audio data.
     */
    const bufferToWave = (abuffer) => {
        const numChannels = abuffer.numberOfChannels;
        const sampleRate = abuffer.sampleRate;
        const format = 1; // PCM
        const bitDepth = 16;

        const numSamples = abuffer.length;
        const dataSize = numSamples * numChannels * (bitDepth / 8);
        const fileSize = 44 + dataSize;

        const buffer = new ArrayBuffer(fileSize);
        const view = new DataView(buffer);

        let offset = 0;

        const writeString = (str) => {
            for (let i = 0; i < str.length; i++) {
                view.setUint8(offset + i, str.charCodeAt(i));
            }
            offset += str.length;
        };

        const writeUint32 = (val) => {
            view.setUint32(offset, val, true);
            offset += 4;
        };

        const writeUint16 = (val) => {
            view.setUint16(offset, val, true);
            offset += 2;
        };

        // RIFF header
        writeString('RIFF');
        writeUint32(fileSize - 8);
        writeString('WAVE');

        // fmt chunk
        writeString('fmt ');
        writeUint32(16); // chunk size
        writeUint16(format);
        writeUint16(numChannels);
        writeUint32(sampleRate);
        writeUint32(sampleRate * numChannels * (bitDepth / 8)); // byte rate
        writeUint16(numChannels * (bitDepth / 8)); // block align
        writeUint16(bitDepth);

        // data chunk
        writeString('data');
        writeUint32(dataSize);

        // Write PCM data
        const channels = [];
        for (let i = 0; i < numChannels; i++) {
            channels.push(abuffer.getChannelData(i));
        }

        for (let i = 0; i < numSamples; i++) {
            for (let c = 0; c < numChannels; c++) {
                let sample = channels[c][i];
                sample = Math.max(-1, Math.min(1, sample)); // clamp
                const intSample = sample < 0 ? sample * 0x8000 : sample * 0x7FFF;
                view.setInt16(offset, intSample, true);
                offset += 2;
            }
        }

        return new Blob([view], {
            type: 'audio/wav'
        });
    };

    try {
        if (!originalImg || !originalImg.width || !originalImg.height) {
            throw new Error("Invalid or unloaded image object provided.");
        }

        const AudioContext = window.AudioContext || window.webkitAudioContext;
        if (!AudioContext) {
            const p = document.createElement('p');
            p.textContent = 'Web Audio API is not supported in this browser.';
            return p;
        }

        // Use a canvas to read pixel data from the image
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d', { willReadFrequently: true });
        canvas.width = originalImg.width;
        canvas.height = originalImg.height;
        ctx.drawImage(originalImg, 0, 0);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const pixelData = imageData.data;

        // Set up an OfflineAudioContext to render the audio in the background
        const numChannels = 1; // Mono
        const sampleRate = 44100;
        const offlineCtx = new OfflineAudioContext(numChannels, sampleRate * duration, sampleRate);

        // Create the carrier sound source (an oscillator)
        const carrier = offlineCtx.createOscillator();
        carrier.type = carrierType;
        carrier.frequency.setValueAtTime(carrierFrequency, 0);

        // Create master gain to control the final volume
        const masterGain = offlineCtx.createGain();
        masterGain.gain.setValueAtTime(gain, 0);
        masterGain.connect(offlineCtx.destination);

        // Create a bank of band-pass filters and gain nodes
        const bandGains = [];
        const minFreq = 80;
        const maxFreq = 16000;
        const logMin = Math.log(minFreq);
        const logMax = Math.log(maxFreq);
        const logRange = logMax - logMin;

        for (let i = 0; i < numBands; i++) {
            // Distribute band frequencies logarithmically for a more natural sound
            const freq = Math.exp(logMin + logRange * (i / (numBands - 1)));

            const filter = offlineCtx.createBiquadFilter();
            filter.type = 'bandpass';
            filter.frequency.value = freq;
            filter.Q.value = numBands / 4; // Higher Q for more bands = better separation

            const gainNode = offlineCtx.createGain();
            gainNode.gain.value = 0; // Start with silence

            carrier.connect(filter);
            filter.connect(gainNode);
            gainNode.connect(masterGain);

            bandGains.push(gainNode);
        }

        // Schedule gain automation based on image pixel data
        const timeStep = 0.02; // Update gain every 20ms for smooth transitions
        for (let t = 0; t <= duration; t += timeStep) {
            const x = Math.min(canvas.width - 1, Math.floor((t / duration) * canvas.width));

            for (let i = 0; i < numBands; i++) {
                // Map band index to a vertical slice of the image.
                // Low frequency (i=0) maps to the bottom, high frequency to the top.
                const y_slice_index = numBands - 1 - i;
                const yStart = Math.floor((y_slice_index / numBands) * canvas.height);
                const yEnd = Math.floor(((y_slice_index + 1) / numBands) * canvas.height);
                
                let totalBrightness = 0, pixelCount = 0;

                // Average the brightness of pixels in the band's designated slice
                for (let y = yStart; y < yEnd; y++) {
                    const pixelIndex = (y * canvas.width + x) * 4;
                    const r = pixelData[pixelIndex];
                    const g = pixelData[pixelIndex + 1];
                    const b = pixelData[pixelIndex + 2];
                    // Using the luminance formula for perceived brightness
                    const brightness = (0.299 * r + 0.587 * g + 0.114 * b) / 255.0;
                    totalBrightness += brightness;
                    pixelCount++;
                }

                const avgBrightness = (pixelCount > 0) ? (totalBrightness / pixelCount) : 0;
                // Square the brightness to make quiet parts quieter and enhance dynamics
                const bandGainValue = avgBrightness * avgBrightness; 

                // Schedule a smooth transition to the new gain value
                bandGains[i].gain.linearRampToValueAtTime(bandGainValue, offlineCtx.currentTime + t);
            }
        }

        carrier.start(0);
        carrier.stop(duration);

        // Render the audio and convert it to a playable format
        const renderedBuffer = await offlineCtx.startRendering();
        const wavBlob = bufferToWave(renderedBuffer);
        const audioUrl = URL.createObjectURL(wavBlob);

        // Create and return an <audio> element
        const audio = document.createElement('audio');
        audio.controls = true;
        audio.src = audioUrl;

        return audio;

    } catch (e) {
        console.error("Audio processing failed:", e);
        const p = document.createElement('p');
        p.textContent = `An error occurred: ${e.message}`;
        p.style.color = 'red';
        p.style.fontFamily = 'monospace';
        return p;
    }
}

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 and Video Carrier Vocal Manipulation Tool is designed to transform visual images into audio representations using various carrier waveforms and frequencies. Users can upload an image, and the tool will process the visual data to create a corresponding audio track, modulating different frequency bands based on the brightness of specific portions of the image. This tool is ideal for artists and sound designers looking to experiment with unique audio creations, as well as for educators who wish to demonstrate the relationship between visual and auditory stimuli. It can also be used in multimedia projects to add an innovative layer of sound that corresponds to visual elements.

Leave a Reply

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