How Spotify crossfades between songs without a gap
How Spotify pre-buffers the next track's first few seconds, applies gain normalization, computes the overlap window, and blends audio PCM frames for gapless playback.
The Problem Statement
Interviewer: "You are listening to a Spotify playlist. The song ends and the next one begins playing immediately, overlapping slightly, fading out the old one and fading in the new one. How does that actually work? What has to happen before the current song ends, and how does Spotify blend two tracks together?"
This question tests whether you understand client-side audio pipeline engineering. It is not a distributed systems question. The interesting work happens entirely on the device you are holding.
Most candidates say "Spotify pre-loads the next song" and stop there. The strong answer explains what "pre-loading" actually means (at what point, how much, from what buffer), describes the PCM-level crossfade computation, and covers why gain normalization is a prerequisite for seamless transitions.
Clarifying the Scenario
You: "A few quick questions. When you say crossfade, are we talking about the user-configurable crossfade (1-12 seconds), or the automatic gapless playback for album tracks? They work differently."
Interviewer: "Start with gapless playback, then explain crossfade."
You: "Got it. And mobile vs desktop? The audio APIs are quite different."
Interviewer: "Start with desktop, then talk about mobile constraints."
You: "Perfect. I will structure this in four parts. First, the audio pipeline from download to speaker. Second, the pre-buffering state machine that sets up the next track before the current one ends. Third, how the actual PCM crossfade blending works. Fourth, the gapless vs crossfade distinction and when each applies."
My Approach
I break this into four parts:
- The audio pipeline: How encoded audio travels from CDN to the speaker, and what data format is in the pipeline at each stage.
- Pre-buffering trigger: When does Spotify decide to start loading the next track, and how much does it load before the current song ends.
- The crossfade computation: What happens at the PCM level to blend two tracks together, including gain normalization.
- Gapless vs crossfade: The important distinction between album tracks (no audible overlap desired) and playlist transitions (user-configured overlap).
The key insight I lead with: crossfade happens at the raw PCM level, after decoding. You cannot crossfade compressed audio (Ogg Vorbis, AAC, MP3). You have to decode both tracks to PCM, then apply amplitude envelopes to each, then sum the two PCM buffers together.
The Architecture
Let me show the full pipeline from CDN download to speaker output. This diagram captures where each format lives in the pipeline.
Let me walk through this pipeline stage by stage.
Stage 1: Compressed download. Spotify stores audio as Ogg Vorbis (their primary format) or AAC. These files are hosted on Spotify's CDN. The client downloads them as chunked HTTP responses, writing compressed frames into a ring buffer. Spotify downloads in chunks (typically 128KB to 1MB at a time) rather than the entire file upfront, which is why you see a small lag when first playing a new track on a slow connection.
Stage 2: Decode to PCM. The Ogg Vorbis or AAC decoder processes compressed frames and produces raw Pulse Code Modulation (PCM) samples. PCM is uncompressed audio: each sample is a 16-bit or 32-bit floating-point value representing amplitude at an instant. At 44.1kHz stereo, one second of PCM is 44,100 samples x 2 channels x 2 bytes = 176KB. A 3-minute song as PCM is about 31MB. Spotify only decodes slightly ahead of playback (typically 1-2 seconds of PCM buffer), not the entire track.
Stage 3: Gain normalization. Before the PCM audio from Track B enters the crossfade engine, it must be volume-adjusted to match Track A's perceived loudness. Without this, the transition from a quiet acoustic track to a loud electronic track would be jarring regardless of how smooth the fade envelope is. I will cover this in the normalization deep dive.
Stage 4: Crossfade engine. During the overlap window, the engine reads from both decoded PCM buffers simultaneously. It applies a fade-out amplitude envelope to Track A (samples multiply by a decreasing coefficient) and a fade-in envelope to Track B (samples multiply by an increasing coefficient). The two resulting PCM buffers are summed sample by sample to produce the blended output.
Stage 5: Audio output. The blended PCM is written to the OS audio API (WASAPI on Windows, CoreAudio on macOS). The OS audio subsystem has its own small hardware buffer (10-50ms) that feeds the speaker hardware. This hardware buffer is what you hear.
Ogg Vorbis vs AAC on Spotify
Spotify primarily uses Ogg Vorbis for most clients because it is open and royalty-free. iOS clients use AAC due to Apple's hardware decoder pipeline. Both formats decode to the same PCM representation, so the crossfade engine is format-agnostic.
The Audio Pipeline and PCM Buffer Management
The pipeline has multiple buffers at different stages, each serving a different purpose. Understanding the buffer structure is essential to understanding how crossfade is possible without gaps.
The buffering state machine. The Spotify client maintains state about each track's download and decode position. The critical transition is from PLAYING to PRE_FETCH, which is triggered when the remaining playback time on Track A drops below a threshold.
When does pre-fetch trigger? The trigger threshold depends on the crossfade duration plus a safety margin. If the user has configured a 10-second crossfade, Spotify starts fetching Track B approximately 12-15 seconds before Track A ends. The client calculates remaining time from the track duration metadata and the current playback position.
How much does Spotify pre-fetch? For the crossfade case, Spotify needs the first N+2 seconds of Track B (where N is the crossfade duration) decoded into a PCM buffer before the overlap window begins. Downloading compressed audio is fast (a 10-second Ogg segment at 128kbps is only 160KB). The bigger concern is decode time: decoding Ogg Vorbis is CPU-intensive (relatively), so Spotify starts decoding early and parks a few seconds of Track B's PCM in a buffer, waiting for the crossfade window.
What if the download is slow? If Spotify cannot download and decode enough of Track B before the crossfade window begins, it falls back to a gap (a brief pause between tracks). This is why you sometimes hear a gap on a slow cellular connection even when crossfade theoretically should work.
Crossfade Math: Overlapping PCM Frames
The actual crossfade operation works at the sample level. This is where the math happens. I want to make this concrete because most descriptions hand-wave over it.
Linear crossfade. The simplest approach: Track A's amplitude multiplied by a coefficient that goes from 1.0 to 0.0 over the crossfade duration. Track B's amplitude multiplied by a coefficient that goes from 0.0 to 1.0. Sum the two results sample by sample. The problem: at the midpoint, both coefficients are 0.5. The summed energy at the midpoint is 0.5A + 0.5B. Even if A and B are at full amplitude, the sum is at half energy. This sounds like a slight dip or "V-shaped" volume drop in the middle of the crossfade. Listeners perceive this as an audible dip.
Equal-power crossfade. Use sinusoidal (cosine/sine) coefficients instead of linear. Mathematically: $\alpha(t) = \cos\left(\frac{t}{D} \cdot \frac{\pi}{2}\right)$ and $\beta(t) = \sin\left(\frac{t}{D} \cdot \frac{\pi}{2}\right)$. The important property: $\alpha^2 + \beta^2 = 1$ at all times. This means the total power of the mixed signal remains constant throughout the crossfade. There is no perceived volume dip. This is the correct approach for perceptually seamless crossfade, and it is what Spotify uses.
Sample-level computation. For each audio frame during the crossfade window, the engine iterates over every PCM sample:
for each frame in crossfade_window:
t = elapsed_samples / sample_rate
alpha = cos(t / crossfade_duration * PI/2)
beta = sin(t / crossfade_duration * PI/2)
for each sample in frame:
output[i] = (track_a_pcm[i] * alpha) + (track_b_pcm[i] * beta)
At 44.1kHz stereo, this is 88,200 multiply-add operations per second during the crossfade window. On modern hardware, this is negligible. On a 2014 iPhone, this was a measurable CPU cost.
Gain normalization before crossfade. Before applying the amplitude envelope, both tracks' PCM buffers are adjusted by a pre-computed gain offset. Without normalization, a loud EDM track crossfading into a quiet folk recording would produce an unbalanced blend where one track overwhelms the other mid-crossfade.
Linear fades sound bad, equal-power fades sound right
The difference between linear and equal-power crossfade is not academic. If you implement a linear crossfade, listeners will hear a subtle "dip" in the middle of every transition. Equal-power is the standard for all professional audio crossfade from DJ software to DAW (digital audio workstation) faders and is what Spotify uses.
Gapless Playback for Albums vs Crossfade for Playlists
These are two distinct features that solve different problems. I have seen candidates conflate them, which is a mistake.
Gapless playback. For album tracks designed to flow continuously (think Pink Floyd's Dark Side of the Moon or a live album), Spotify uses gapless playback rather than crossfade. The goal is zero audible gap between tracks without any overlap or volume change. This is harder than it sounds because audio encoders (Vorbis, AAC, MP3) add encoder delay at the beginning and padding at the end of each compressed file.
Encoder pre-gap and post-gap. When an Ogg Vorbis encoder compresses audio, it adds silence at the beginning (pre-gap, typically 576 samples at 44.1kHz) due to encoder latency. The Ogg container format stores the total sample count in the stream header, allowing a smart decoder to know exactly how many samples to trim. For gapless playback, the Spotify decoder reads the pre-gap metadata and discards those initial padding samples. It also trims the trailing post-gap samples from Track A. The result: the PCM buffers for Track A and Track B stitch together at the exact sample boundary where the original mastering engineer intended the tracks to connect.
Crossfade. For playlist transitions (shuffled songs, curated playlists), Spotify applies the user-configured crossfade. The two tracks did not come from a continuous recording, so a brief overlap is acceptable or even desirable. Crossfade smooths the perceptual jump between songs with different keys, tempos, and sonic characteristics. The user configures the overlap window from 1 to 12 seconds in Settings.
The rule I use: gapless is for tracks that share a continuous recording. Crossfade is for tracks that are independent. If both gapless metadata exists AND crossfade is enabled, gapless takes priority for album tracks.
Mention the encoder pre-gap when discussing gapless
Describing encoder pre-gap trimming is what separates a strong candidate from one who says "gapless just plays tracks back to back." The reason there is any gap problem at all is the encoder latency artifact. Knowing that Vorbis and AAC both add silent samples and that the solution is metadata-guided trimming shows you understand audio encoding at a practical level.
The Tricky Parts
-
Seek operations during crossfade. If the user presses skip or seeks to a different position while a crossfade is in progress, the crossfade engine must immediately discard both PCM decode buffers, cancel the in-flight HTTP request for Track B, and start fresh from the new position. The state machine transitions must be clean and fast to avoid audible glitches on seek. Spotify handles this by treating seek as a hard reset of the pipeline.
-
Variable song length from the server. Audio files sometimes have incorrect duration metadata (rounding errors in the Ogg stream or CDN inconsistencies). If the client triggers the pre-fetch based on a stale duration estimate and the actual track is longer, the crossfade begins too early. Spotify tracks actual playback sample count rather than relying solely on duration metadata, recalculating remaining time continuously.
-
Background audio on iOS. iOS's CoreAudio requires the app to hold an AVAudioSession background entitlement to continue playing audio when backgrounded. The crossfade engine runs in this audio callback thread, which has strict timing requirements (must return in under the buffer period, typically 10ms). If the crossfade compute takes longer than 10ms (unlikely on modern hardware, possible on older devices during a track transition where both decoders are initializing), the audio output buffer underruns and you hear a click or pop.
-
Network handoff during pre-fetch. On mobile, switching from Wi-Fi to cellular mid-download interrupts the compressed audio chunk download. The HTTP client must seamlessly resume the range request from the last received byte. If the handoff causes a delay that pushes the chunk delivery past the pre-fetch deadline, Spotify falls back to a gap rather than attempting a partial crossfade.
-
Replay Gain metadata vs album normalization. Spotify applies loudness normalization at two levels: track-level normalization (each track sounds roughly the same loudness) and album-level normalization (tracks within an album maintain their relative volume relationships). The default for most users is track normalization. Users who prefer quiet late-night listening can engage the "Quiet" loudness level. During crossfade, the gain offset must be pre-applied to both tracks' PCM buffers before the amplitude envelopes are calculated.
What Most People Get Wrong
| Mistake | What they say | Why it is wrong | What to say instead |
|---|---|---|---|
| Wrong domain | "This is a server-side streaming feature" | Crossfade is entirely client-side. The server just provides compressed audio chunks | "The crossfade engine runs on your device. The server sends compressed audio; the client decodes to PCM and blends in the audio callback thread" |
| Wrong buffer level | "Spotify pre-loads the compressed Ogg file" | Pre-loading compressed is insufficient; you need decoded PCM in memory at the time of crossfade | "Spotify decodes a few seconds of Track B into a PCM buffer ahead of time, so the crossfade engine has raw samples to blend immediately" |
| Ignoring gain normalization | "Just fade the volume of each track" | Without gain normalization, a loud track fading into a quiet track sounds unbalanced mid-crossfade | "ReplayGain or Spotify's loudness normalization pre-adjusts track gain to a target LUFS before the crossfade amplitude envelope is applied" |
| Linear fade | "Multiply one track by a decreasing coefficient" | Linear fades produce a perceptible volume dip at the midpoint (half amplitude = -6dB loss) | "Equal-power cosine/sine crossfade: coefficients satisfy cos squared + sin squared = 1, ensuring constant perceived loudness" |
| Conflating gapless with crossfade | "Gapless and crossfade are the same feature" | Gapless = sample-accurate stitch with encoder pre-gap trimming, no overlap. Crossfade = user-configured overlap window with amplitude blending | "Different modes for different use cases: gapless for albums, crossfade for playlists" |
How I Would Communicate This in an Interview
Here is how I would actually say this, about 90 seconds:
"Spotify crossfade is entirely client-side. The server just serves compressed audio chunks. All the interesting work happens on your device.
Here is the timeline: when you are, say, 15 seconds from the end of Track A (with a 10-second crossfade configured), Spotify fires an HTTP range request for the first few seconds of Track B. It downloads the compressed Ogg Vorbis chunks, decodes them into a PCM buffer, and applies a gain normalization offset so both tracks are at the same perceived loudness.
When the crossfade window opens, the audio engine reads from two PCM decode buffers simultaneously. It applies equal-power amplitude envelopes: Track A's samples are multiplied by cos(t/D times pi/2) and Track B's samples by sin(t/D times pi/2). These two PCM streams are summed sample by sample. The property of equal-power crossfade is that cos squared plus sin squared equals 1, so the total signal power stays constant throughout the blend, which means the listener hears no volume dip.
For album tracks where you want gapless playback instead of crossfade, Spotify reads encoder pre-gap metadata from the Ogg stream header and trims those exact leading samples from Track B. This achieves sample-accurate stitching with no audible gap and no overlap, even when the encoder has added silence padding to each file."
The equal-power formula is the standout answer
If you can say "cosine and sine coefficients where alpha squared plus beta squared equals one" in your answer, you have immediately differentiated yourself from every candidate who said "fade the volume." That one mathematical property is the entire reason equal-power crossfade sounds seamless while linear crossfade does not.
Interview Cheat Sheet
- Crossfade is client-side: The server serves compressed audio. All blending happens in the Spotify app's audio processing pipeline on your device.
- PCM is the only blendable format: You cannot crossfade Ogg Vorbis or AAC directly. Both tracks must be decoded to raw PCM before any amplitude math.
- Pre-fetch trigger: Spotify starts downloading the next track when remaining playback time drops below crossfade_duration + safety_margin (approximately N+5 seconds).
- Equal-power crossfade: Use cosine/sine coefficients where alpha squared plus beta squared equals 1 at all times, ensuring constant perceived loudness with no midpoint dip.
- Linear crossfade is wrong: Linear coefficients sum to 1.0 at midpoint by amplitude (0.5 + 0.5) but only 0.5 by power, causing a perceived -6dB dip.
- ReplayGain normalization: Both tracks' PCM gain must be adjusted to the same target LUFS before the crossfade envelope is applied, or volume jumps ruin the transition.
- Gapless vs crossfade: Gapless trims encoder pre-gap samples using Ogg metadata for sample-accurate stitching. Crossfade applies a user-configured overlap with amplitude blending.
- Encoder pre-gap: Ogg Vorbis encoders add ~576 leading silence samples due to MDCT encoder latency. Gapless playback trims these using stream header metadata.
- iOS constraint: The crossfade compute runs in the CoreAudio callback thread, which has a hard deadline of approximately 10ms. Both decoders must be initialized before the crossfade window, not during it.
- Seek handling: Any user seek or skip during crossfade immediately cancels the blending, discards both PCM buffers, and restarts the pipeline from the new position.
Test Your Understanding
Quick Recap
- Crossfade is entirely client-side: the server sends compressed audio chunks; all decoding, normalization, and blending happen in the Spotify app's audio pipeline.
- Both tracks must be decoded to raw PCM before blending, because you cannot apply amplitude math to compressed Ogg Vorbis or AAC frames.
- Pre-fetch triggers approximately crossfade_duration plus 5 seconds before Track A ends, downloading and decoding enough of Track B to fill the PCM overlap buffer.
- Equal-power crossfade uses cosine/sine coefficients satisfying alpha squared plus beta squared equals 1, maintaining constant perceived loudness with no midpoint dip.
- ReplayGain loudness normalization adjusts each track's PCM gain to a common target LUFS before the crossfade envelope is applied, ensuring balanced blending.
- Gapless playback for albums requires reading encoder pre-gap sample counts from Ogg stream headers and trimming exactly those samples from the track boundary.
- On iOS, both PCM decode buffers must be fully initialized before the CoreAudio callback fires, as the real-time audio thread cannot block to wait for decode.
- Automix extends crossfade with BPM-based tempo matching and beat alignment, using server-pre-analyzed tempo metadata and client-side phase vocoder time-stretching.
Related Concepts
- How Spotify Plays Music Instantly: The same chunked HTTP download and CDN infrastructure that enables fast playback start also enables the pre-fetch that crossfade depends on.
- How Spotify Recommendations Work: The recommendation engine determines what Track B is. Crossfade depends on accurate next-track prediction happening before the current track ends.
- How Data Compression Works: Understanding why Ogg Vorbis adds encoder pre-gap and why you cannot crossfade compressed audio frames requires understanding how lossy audio codecs encode and decode data.
title: "How Spotify crossfades between songs without a gap" description: "How Spotify pre-buffers the next track's first few seconds, applies gain normalization, computes the overlap window, and blends audio PCM frames for gapless playback." tags:
- "situational"
- "spotify"
- "audio"
- "streaming" difficulty: "medium" category: "situational/architecture" order: 115 publishedAt: "2026-04-12" relatedArticles: []
The Problem Statement
Interviewer: "You are listening to a playlist on Spotify. One song ends and the next one starts, but there is no gap and the audio smoothly fades between them. How does Spotify actually do that? Walk me through what happens at the audio level."
This question tests three things: your understanding of audio buffering and decoding pipelines, how two separate audio streams get blended at the PCM sample level, and whether you know the difference between naive crossfading and perceptually correct crossfading. Interviewers use this to see if you can reason about real-time media processing where latency budgets are measured in milliseconds, not seconds.
Clarifying the Scenario
You: "Before I start, I want to scope this properly."
You: "When you say 'crossfade,' are we talking about the user-configurable crossfade setting (where the slider goes from 0 to 12 seconds), or are we also covering gapless playback for albums that are designed to flow together, like a live concert recording?"
Interviewer: "Cover both. Start with the crossfade feature, then explain how gapless differs."
You: "Got it. Should I focus on the client-side audio processing, or do you want me to cover how the server prepares the audio streams too?"
Interviewer: "Mostly client-side, but mention what the server needs to provide."
You: "OK. I will structure this in four parts: how Spotify pre-buffers the next track, how it normalizes volume between two tracks, how the crossfade overlap window works at the PCM level, and how gapless playback differs from crossfade."
My Approach
I break this into five layers:
- Track pre-buffering: The client must start downloading and decoding the next track before the current one ends
- Gain normalization: Two consecutive tracks might have very different loudness levels, so the system applies ReplayGain/LUFS normalization before blending
- Overlap window computation: The crossfade duration determines how many PCM frames from both tracks get mixed simultaneously
- PCM frame blending: The actual math of combining two audio waveforms using crossfade curves (linear vs equal-power)
- Gapless playback: A special case where tracks on the same album skip crossfade entirely and eliminate all inter-track silence
The key insight most candidates miss: crossfading is not just "play two songs at the same time and adjust volume." The volume curves matter enormously. A naive linear fade creates a perceptible dip in loudness at the midpoint. Equal-power crossfading fixes this by using sine/cosine curves that maintain constant perceived energy. I have seen candidates lose points by describing only the simple approach.
The Architecture
Here is the walkthrough of the crossfade pipeline:
Step 1: Prefetch triggers. When the current track reaches approximately 10 seconds before its end (adjusted by the user's crossfade duration setting), the Prefetch Manager requests the next track's first chunks from the CDN. It also fetches the ReplayGain metadata for the next track.
Step 2: Dual decoding. The client spins up a second decoder instance. Decoder A continues decoding the current track. Decoder B starts decoding the next track from its first byte. Both produce raw PCM audio frames (typically 44,100 samples per second at 16-bit depth, or 48kHz for premium on some devices).
Step 3: Gain normalization. Before any mixing happens, both PCM streams pass through the Gain Normalizer. Each track has a ReplayGain value (measured in LUFS, Loudness Units Full Scale) embedded in its metadata. The normalizer adjusts each stream so they have roughly equal perceived loudness. Without this step, a quiet jazz track fading into a loud rock track would create a jarring volume jump.
Step 4: The mixer blends. During the overlap window (say the user set crossfade to 6 seconds), the Audio Mixer receives PCM frames from both streams. For each sample, it applies a crossfade curve: the outgoing track's volume decreases from 1.0 to 0.0, and the incoming track's volume increases from 0.0 to 1.0. The curve shape determines whether the fade sounds natural or has a loudness dip.
Step 5: Output buffer and playback. The blended PCM frames go into a ~200ms output buffer that feeds the device's DAC (Digital-to-Analog Converter) or audio API. This buffer absorbs jitter from the decoding pipeline and prevents glitches.
For your interview: describe this as "two decoders feeding a mixer through a normalizer" and you have communicated the core architecture in one sentence.
Why the Crossfade Curve Shape Matters
This is the single most important detail in audio crossfading, and the one most candidates skip. The shape of the fade curve determines whether the transition sounds smooth or has an audible "dip" in the middle.
The math is straightforward but the perceptual impact is dramatic. At the midpoint of a crossfade, both tracks play simultaneously. The question is: at what gain?
Why 0.707?
The value 1/v2 οΏ½ 0.707 is the gain where two uncorrelated audio signals sum to the same power as one signal at full gain. This is a fundamental constant in audio engineering. If an interviewer asks "why not just use 0.5?", this is the answer.
I have seen candidates describe crossfading as "just lowering one volume and raising the other." That is technically correct for linear fading, but it misses the key engineering decision. Always mention equal-power crossfading. It signals that you understand audio beyond the surface level.
Gapless Playback vs Crossfade
Crossfade and gapless playback solve different problems and use different techniques. Most candidates conflate them. Gapless playback is for albums where the artist intended zero silence between tracks (live albums, concept albums, DJ mixes). Crossfade is a user preference for playlists.
The encoder padding problem. Every lossy audio codec (MP3, Vorbis, AAC) adds padding samples at the beginning and end of the encoded stream. MP3 adds 1,152 samples of silence at the start (one full MPEG frame). AAC adds 2,048 samples. If you decode two tracks and concatenate the PCM output without trimming this padding, you get a ~26ms gap for MP3 or ~46ms for AAC at 44.1kHz. That is clearly audible.
Spotify solves this by storing the exact padding length in the track metadata. The decoder trims exactly that many samples from the start of Track B and the end of Track A before concatenation. This produces a sample-accurate join.
Live tracks are different
Live albums and DJ mixes often have crowd noise or applause that continues across track boundaries. The audio does not start at zero amplitude. If crossfade is accidentally applied to these tracks, you get a weird double-applause effect. Spotify uses album metadata to detect consecutive tracks on the same album and forces gapless mode, overriding the user's crossfade setting.
How Spotify detects gapless intent. The decision is not just "same album." It also checks whether the tracks are consecutive in the album's track listing, whether the audio at the boundary is non-silent (above a threshold like -40dB), and whether the album is tagged as a live recording or continuous mix. If all conditions are met, gapless wins over crossfade. This prevents the system from crossfading "Sgt. Pepper's Lonely Hearts Club Band" into "With a Little Help from My Friends" and ruining one of the most famous album transitions in music.
Related Articles
How Spotify uses predictive prefetching, Vorbis/AAC codec switching, local cache management, and crossfade buffering for instant playback.
Spotify's recommendation engine combines collaborative filtering (matrix factorization on listening history), NLP on playlist metadata, and audio analysis. Learn how Discover Weekly and Daily Mixes are generated at scale.
Understand the algorithms behind gzip, zstd, and LZ4 that compress files and network payloads, the entropy theory, dictionary-based compression, and why system designers must understand when to compress, when not to, and what the tradeoffs are.