Float:ImgPlay

Float:ImgPlay

Image-to-sound player — Scans pixel data and generates rule-based music via Web Audio API

GitHub Repository →

Live Demo 10 images with different UI control combinations

Inst
Ens
Algo
BPM 100
VOL 25%
Clouds
All Controls
Volcano
No Controls
Landscape
Play Only
Ocean
Settings Only
Portrait
Volume Only
City
Speed Only
Galaxy
Play + Volume
Food
Play + Speed
Abstract
Speed + Volume
Forest
Play + Settings

Upload Image Drop or select your own image to play

🖼
Drop image here or click to select
PNG, JPG, WebP, GIF
Play
Click any image to play its generated sound. Each image produces different music based on its pixel data.
Mix
Switch instruments, ensembles, and algorithms from the mixer strip above the demo grid. Changes apply to all images instantly.
Orchestra
Hit Play All to play every image simultaneously. Choose an ensemble preset to layer multiple instruments.
Per-Image Settings
Click the gear icon on images that have it. Each image can have its own instrument, algorithm, and audio settings.
Upload
Drop your own images above to hear what they sound like. Any image works — photos, art, screenshots.
Embed MIDI
Combine a PNG image with a MIDI file. The resulting image looks normal but plays your MIDI when loaded by Float:ImgPlay.
Fine-Tune
Scroll down to Settings to adjust tempo, waveform, scale, filter, envelope, and more. Click Apply to hear the difference.
Export
Export your current settings as JSON or download generated scores as MIDI files. Import presets others have shared.

Embed MIDI into Image Combine PNG + MIDI into one playable image file

🖼
Drop PNG or click
🎵
Drop .mid or click

Settings Change options and click "Apply" to reinitialize

General

0.25

Audio - Volume & Pitch

0.25
0

Audio - Tempo & Rhythm

100
0.5
28

Audio - Sampling

auto

Audio - Filter

900
3000

Audio - Envelope

0.02
0.03

Audio - Scale & Key

60 (C4)

Audio - Octave & Duration

100
12
0.26
0.46
0.34

Security

10 MB

Generated Code

Current settings as initialization code. Copy and use directly.

Preset JSON

Export/import your current settings as JSON.

API Methods

Try the API

play/stop targets the first image (Clouds). destroy removes all instances. init re-initializes.

MIDI Export

Export image-generated scores as Standard MIDI Files (.mid). Uses MidiExport module.

Code Examples

Script Tag
ESM Import
CommonJS
Background Image
Per-Element
API Usage
v2 Features
<!-- CSS (optional) --> <link rel="stylesheet" href="https://unpkg.com/float-imgplay/dist/float-imgplay.css"> <!-- Image --> <div class="float-imgplay"> <img src="/images/photo.jpg" width="320" height="320"> </div> <!-- Library --> <script src="https://unpkg.com/float-imgplay"></script> <script> new FloatImgPlay({ selector: '.float-imgplay' }).init(); </script>
import { FloatImgPlay } from 'float-imgplay'; import 'float-imgplay/css'; const player = new FloatImgPlay({ selector: '.float-imgplay', autoplay: false, audio: { masterVolume: 0.35, waveform: 'triangle', tempo: 104 } }); player.init();
const { FloatImgPlay } = require('float-imgplay'); const player = new FloatImgPlay({ selector: '.float-imgplay' }); player.init();
<!-- Works with background-image too --> <div class="float-imgplay" style="background-image:url('/images/sky.jpg'); width:320px; height:320px; background-size:cover;"> </div> <!-- Also works on img directly --> <img class="float-imgplay" src="/images/photo.jpg" width="320" height="320">
const player = new FloatImgPlay({ selector: '.float-imgplay', autoplay: false }); player.init(); // Register a specific element with different options const hero = document.querySelector('#hero-image'); player.register(hero, { autoplay: true, audio: { waveform: 'sawtooth', masterVolume: 0.5, pitchShiftSemitones: 3, tempo: 132, scaleMode: 'minor' } });
const player = new FloatImgPlay({ selector: '.float-imgplay' }); player.init(); // Play a specific element player.play(document.querySelector('#my-image')); // Stop a specific element player.stop(document.querySelector('#my-image')); // Pause (alias for stop) player.pause(document.querySelector('#my-image')); // Re-analyze after image src changes player.refresh(); // Remove a single element player.unregister(document.querySelector('#my-image')); // Clean up everything player.destroy();
import { FloatImgPlay } from 'float-imgplay'; // --- Single Instrument --- const pianoPlayer = new FloatImgPlay({ selector: '.float-imgplay', instruments: [{ preset: 'piano' }] }); pianoPlayer.init(); // --- Ensemble Preset (multi-instrument) --- const orchestraPlayer = new FloatImgPlay({ selector: '.float-imgplay', ensemble: 'orchestra' // Strings + Brass + Flute }); orchestraPlayer.init(); // --- Custom Multi-Instrument --- const customPlayer = new FloatImgPlay({ selector: '.float-imgplay', instruments: [ { preset: 'piano', volume: 0.25 }, { preset: 'bass', volume: 0.2 }, { preset: 'bell', volume: 0.1 } ] }); customPlayer.init(); // --- Available Instrument Presets (20) --- // piano, epiano, organ, synthLead, synthPad, bass, subBass, // pluck, strings, brass, flute, choir, bell, marimba, guitar, // acid, chiptune, warmPad, glass, wobble // --- Available Ensemble Presets (10) --- // orchestra, rockBand, electronic, jazzTrio, ambient, // chiptuneBand, cinematic, lofi, acidHouse, minimal // --- MIDI Export --- const inst = player.instances.get(someElement); if (inst && inst.currentScore) { FloatImgPlay.MidiExport.exportAndDownload( inst.currentScore, { bpm: 120 }, 'my-image.mid' ); } // --- Security Options --- const securePlayer = new FloatImgPlay({ selector: '.float-imgplay', ensemble: 'cinematic', security: { allowedDomains: ['cdn.example.com'], maxFileSize: 5242880 // 5MB } }); securePlayer.init();

Full Options Reference

new FloatImgPlay({ // --- General --- selector: '.float-imgplay', // CSS selector for target elements autoplay: false, // Auto-play on init autoplayWhenVisibleOnly: true, // Only autoplay when element is visible stopWhenHidden: true, // Stop when scrolled away / tab hidden / occluded showPlayOverlay: true, // Show centered play button overlay showVolumeControl: true, // Show volume slider (bottom-right) overlayIcon: '\u25B6', // Play button icon character overlayPlayText: '', // Optional text next to play icon visibilityThreshold: 0.25, // IntersectionObserver threshold (0-1) zIndexUI: 12, // z-index for UI overlay // --- Instruments (v2) --- ensemble: 'orchestra', // Ensemble preset name (overrides instruments) // OR instruments: [ // Array of instrument configs { preset: 'piano', volume: 0.25 }, { preset: 'bass' }, { waveform: 'sine', octaveShift: 1, volume: 0.1 } // custom ], // --- Audio --- audio: { masterVolume: 0.25, // Master volume (0-1) pitchShiftSemitones: 0, // Global pitch shift (-24 to 24) waveform: 'triangle', // sine | square | sawtooth | triangle tempo: 100, // BPM (40-240) noteDurationBeats: 0.5, // Note length in beats restThreshold: 28, // Brightness below this = rest (0-128) sampleColumns: 24, // Number of pixel columns to sample (4-64) sampleRows: [0.25, 0.5, 0.75], // Vertical positions to sample (0-1) filterType: 'lowpass', // lowpass | highpass | bandpass | notch | allpass filterBaseHz: 900, // Base filter frequency (Hz) filterVelocityAmount: 3000, // Velocity-driven filter sweep range (Hz) attack: 0.02, // Envelope attack time (seconds) release: 0.03, // Envelope release time (seconds) scaleMode: 'auto', // auto | major | minor | pentatonic rootMode: 'filename-first-char', // filename-first-char | fixed fixedRootMidi: 60, // MIDI note for fixed root (36-84, 60=C4) octaveContrastThreshold: 100, // R-B contrast above this = octave shift octaveShiftSemitones: 12, // Semitones to shift on contrast trigger brightDuration: 0.26, // Duration multiplier for red-dominant pixels blueDuration: 0.46, // Duration multiplier for blue-dominant pixels neutralDuration: 0.34 // Duration multiplier for neutral pixels }, // --- Security --- security: { allowedDomains: [], // Empty = allow all. List of allowed hostnames maxFileSize: 10485760, // Max file size in bytes (10MB). 0 = no limit allowedMimeTypes: [ // Allowed MIME types for images 'image/png', 'image/jpeg', 'image/webp', 'image/gif' ] } }).init();