Your p5.js sketch was working perfectly on your laptop. Then you share it with a friend, and suddenly: "Uncaught TypeError: Cannot read properties of undefined."
Sound familiar? I spent 2 hours debugging this exact error on my first interactive music project.
What you'll learn: How to make your p5.js audio work across all browsers
Time needed: 10 minutes
Difficulty: Beginner-friendly
Here's the fix that saved my project and will save yours: soundFormats() tells p5.js which audio files to try loading, preventing those mysterious audio errors.
Why I Had to Learn This
I built a generative music visualizer for a gallery installation. Everything worked perfectly on my MacBook Pro in Chrome. The day before the opening, I tested it on the gallery's Windows machine running Firefox.
Complete silence.
My setup:
- p5.js 1.7.0 with p5.sound library
- Audio files in MP3 format only
- Modern web browsers (I thought)
- Zero backup plan for audio compatibility
What broke:
- Firefox didn't like my MP3 encoding
- Safari was picky about file headers
- Edge threw cryptic loading errors
- No fallback audio formats
Time wasted: 4 hours of panic debugging at midnight
The Root Problem: Browser Audio Support
Different browsers support different audio formats. Your MP3 might work in Chrome but fail in Firefox. Your OGG file might load in Firefox but crash Safari.
My solution: Use soundFormats() to provide multiple file formats and let p5.js pick the best one.
Time this saves: Prevents hours of cross-browser debugging
Step 1: Set Up Multiple Audio Formats
Before writing any code, you need audio files in different formats for maximum compatibility.
// Place this BEFORE preload() function
function preload() {
// Tell p5.js which formats to try, in order of preference
soundFormats('mp3', 'ogg', 'wav');
// Load your audio file (without extension)
mySound = loadSound('assets/background-music');
}
What this does: p5.js tries to load 'background-music.mp3' first, then 'background-music.ogg', then 'background-music.wav' until one works.
Expected file structure:
your-project/
├── sketch.js
└── assets/
├── background-music.mp3
├── background-music.ogg
└── background-music.wav
Personal tip: "Always put soundFormats() as the first line in preload(). I learned this the hard way when my loading order caused weird timing issues."
Step 2: Convert Your Audio Files
You'll need your audio in multiple formats. Here's my streamlined workflow:
Online conversion (easiest):
- Upload your original file to CloudConvert or similar
- Convert to MP3, OGG, and WAV
- Keep file names identical (just different extensions)
FFmpeg command line (fastest for multiple files):
# Convert to all three formats at once
ffmpeg -i original-audio.wav \
-codec:a libmp3lame -b:a 192k background-music.mp3 \
-codec:a libvorbis -q:a 5 background-music.ogg \
-codec:a pcm_s16le background-music.wav
What this creates: Three versions of your audio optimized for different browsers
Personal tip: "I keep a 'convert-audio.sh' script in my project folder. Converting 5 files takes 30 seconds instead of 20 minutes of manual work."
Step 3: Test Your Browser Compatibility
Here's the complete working example I use to test audio loading:
let mySound;
let isLoaded = false;
function preload() {
// Set supported formats in order of preference
soundFormats('mp3', 'ogg', 'wav');
// Load audio file (p5.js will try each format)
mySound = loadSound(
'assets/test-audio',
// Success callback
() => {
console.log('Audio loaded successfully!');
isLoaded = true;
},
// Error callback
(error) => {
console.log('Audio loading failed:', error);
}
);
}
function setup() {
createCanvas(400, 400);
// Create play button after everything loads
if (isLoaded) {
let playBtn = createButton('Play Sound');
playBtn.mousePressed(playAudio);
}
}
function playAudio() {
if (mySound && isLoaded) {
mySound.play();
}
}
function draw() {
background(220);
// Show loading status
textAlign(CENTER);
if (isLoaded) {
text('Audio ready! Click play button.', width/2, height/2);
} else {
text('Loading audio...', width/2, height/2);
}
}
Expected behavior: Console shows "Audio loaded successfully!" and you see a play button
Personal tip: "Always include error callbacks. The default p5.js error messages don't tell you which format failed or why."
Step 4: Handle Loading Errors Gracefully
Even with multiple formats, audio might fail to load. Here's my bulletproof error handling:
let sounds = {};
let audioReady = false;
function preload() {
soundFormats('mp3', 'ogg', 'wav');
// Load multiple audio files with error handling
sounds.background = loadSound(
'assets/background-music',
() => console.log('Background music loaded'),
(err) => {
console.log('Background music failed:', err);
sounds.background = null;
}
);
sounds.click = loadSound(
'assets/click-sound',
() => console.log('Click sound loaded'),
(err) => {
console.log('Click sound failed:', err);
sounds.click = null;
}
);
}
function setup() {
createCanvas(400, 400);
// Check what actually loaded
audioReady = Object.values(sounds).some(sound => sound !== null);
if (audioReady) {
console.log('At least some audio loaded successfully');
} else {
console.log('No audio could be loaded - running in silent mode');
}
}
function mousePressed() {
// Safe audio playback
if (sounds.click && sounds.click.isLoaded()) {
sounds.click.play();
} else {
console.log('Click sound not available - visual feedback only');
// Add visual feedback instead
background(random(255), random(255), random(255));
}
}
What this prevents: Crashes when audio files are missing or corrupted
Personal tip: "I always build a 'silent mode' into my projects. Some users have audio disabled, others have corporate firewalls that block audio files."
Common Mistakes I Made (So You Don't Have To)
Mistake 1: Wrong File Extensions
// ❌ Don't include extensions
mySound = loadSound('assets/music.mp3');
// ✅ Let p5.js choose the format
soundFormats('mp3', 'ogg', 'wav');
mySound = loadSound('assets/music');
Mistake 2: soundFormats() in Wrong Place
// ❌ Too late - loadSound already happened
function preload() {
mySound = loadSound('assets/music');
soundFormats('mp3', 'ogg'); // This won't work
}
// ✅ Set formats BEFORE loading
function preload() {
soundFormats('mp3', 'ogg', 'wav');
mySound = loadSound('assets/music');
}
Mistake 3: Not Testing File Sizes
Large audio files will timeout on slow connections. My 5MB background track caused loading failures.
My fix: Keep audio files under 1MB, use compressed formats for longer tracks.
Browser-Specific Tips That Saved My Projects
Chrome: Loves MP3, handles large files well
soundFormats('mp3', 'ogg'); // MP3 first for Chrome
Firefox: Prefers OGG, sometimes rejects MP3s with weird encoding
soundFormats('ogg', 'mp3', 'wav'); // OGG first for Firefox
Safari: Picky about MP3 headers, WAV is safest fallback
soundFormats('mp3', 'wav', 'ogg'); // WAV as safety net
Mobile browsers: Require user interaction before audio plays
function touchStarted() {
// Enable audio context on first touch (mobile requirement)
if (getAudioContext().state !== 'running') {
getAudioContext().resume();
}
}
What You Just Built
Your p5.js project now loads audio reliably across all major browsers. No more mysterious silent failures or "Cannot read properties" errors.
Key Takeaways (Save These)
- Always use soundFormats() before loadSound(): Sets up fallback formats for browser compatibility
- Include error callbacks: Default p5.js errors don't give enough debugging info
- Test on multiple browsers: What works in Chrome might fail in Firefox or Safari
- Build silent mode fallbacks: Some users can't or won't load audio files
- Keep files under 1MB: Large audio causes timeout errors on slow connections
Your Next Steps
Pick one based on your experience level:
- Beginner: Try loading multiple sound effects with different formats
- Intermediate: Add audio analysis with
FFT()for visual responses - Advanced: Build a complete audio-reactive animation system
Tools I Actually Use
- Audacity: Free audio editing and format conversion
- FFmpeg: Command-line batch conversion for multiple files
- CloudConvert: Online converter when I need just one file
- p5.js Sound Reference: Official documentation with all audio functions
Personal tip: "Bookmark this soundFormats() pattern. I reference it for every new project because browser audio support keeps changing."