technique

Stingers and transitions

Short musical cues for winning, losing, and changing scenes, and how to move between loops without a jarring cut.

Before this

This page assumes you are comfortable with:

Why you need this

Loops carry a scene; stingers mark the moment it changes. The win and lose cues are the most-heard music in a card game, and they arrive at a moment the game picks, not the music. This page is stage 4 of the pipeline: making short cues that fit the loop they interrupt, and moving between pieces of music without a cut that sounds like a mistake.

The idea

A stinger is a short musical cue, usually one to a few bars, that plays on an event: a win, a loss, a level-up. A transition is how the game gets from one piece of music to the next: lobby loop to match loop, match loop to stinger, stinger back to the lobby.

Match the stinger to the loop. A stinger that follows a loop should share its key (the home note and scale the music is built on, such as A minor) and its tempo (in BPM). A stinger in a different key sounds like a second radio station. One at a different tempo makes the beat lurch at the handoff. Write the loop's key and tempo into the stinger's prompt, and listen for both in the result.

Two ways to get a stinger.

Method How Good for Watch for
Generate it short Ask the model for a short clip, naming the key, tempo, mood, and "short ending" or a final chord Clean endings written as endings Models often pad short requests with silence or a fade; trim it
Cut it from a longer take Generate a longer piece in the same key and tempo, keep the strongest 1 to 2 bars plus the ending A cue that sounds like the loop's world The cut start needs a short fade-in or a downbeat; the end needs its full tail

Either way, keep the tail. A stinger's last chord rings, and cutting the ring short is the most obvious edit a player can hear.

Three ways to transition.

  1. Fade. The old music fades out over a set time, then the new music starts. Simple, and fine for leaving a menu.
  2. Crossfade. The old music fades out while the new one fades in, overlapping. Works when the two pieces share a key and do not have clashing beats, or when the crossfade is long enough that the clash is quiet.
  3. Wait for the bar line. The game waits until the old loop reaches its next bar line, then starts the new music exactly there. The change lands on the beat, which sounds deliberate. The cost is a short delay.

The wait is one line of arithmetic. If the loop started playing at time t0t_0, the current time is tt, and one bar is LL seconds long, then the time already spent in the current bar is (t−t0) mod L(t - t_0) \bmod L, where "mod" means the remainder after dividing. The wait to the next bar line is

w=L−((t−t0) mod L)w = L - \big((t - t_0) \bmod L\big)

With small numbers: L=2L = 2 s, the loop has played for 5.3 s. 5.3 mod 2=1.35.3 \bmod 2 = 1.3, so w=2−1.3=0.7w = 2 - 1.3 = 0.7 s.

The game logic in plain words. When the match ends: compute the wait to the next bar line of the match loop. Fade the loop out over the last stretch of that wait. Start the stinger exactly at the bar line. When the stinger's tail has finished, start the lobby loop, from its intro if it has one. If the player leaves the screen during the stinger, fade it out quickly rather than cutting it.

Worked example

The prompts, seeds, and clips here are illustrations, not records of real runs. The Lumen Clash in-match loop is in A minor, 4/4, 150 BPM, and 24 bars long. One beat is 60/150=0.460/150 = 0.4 s and one bar is 4×0.4=1.64 \times 0.4 = 1.6 s (76,800 samples at 48 kHz, meaning 48,000 samples per second), so the loop is 24×1.6=38.424 \times 1.6 = 38.4 s.

The stingers.

Cue Seed Prompt idea (illustration) Musical length Tail kept File length
Win 812 "short victorious fanfare, A minor resolving to A major, 150 BPM, strings and bells, final chord" 2 bars = 3.2 s 1.5 s 4.7 s
Lose 813 "short defeated cue, A minor, 150 BPM, low strings falling, soft final chord" 1 bar = 1.6 s 1.5 s 3.1 s

Both share the loop's tempo, so a bar of stinger is the same 1.6 s as a bar of loop. The win cue ends on A major, the bright version of the loop's home chord, which reads as a lift without changing the home note. The lose cue stays in A minor and falls.

The wait to the bar line. The match ends 45.3 s after the in-match loop started, so the loop has already wrapped around once.

Step Value
Position in the loop 45.3 mod 38.4=6.945.3 \bmod 38.4 = 6.9 s
Which bar bar 5 of 24 (bar 5 runs from 6.4 s to 8.0 s)
Position in the bar 6.9 mod 1.6=0.56.9 \bmod 1.6 = 0.5 s
Wait to next bar line 1.6−0.5=1.11.6 - 0.5 = 1.1 s

So the game fades the loop out over the next 1.1 s and starts the win stinger exactly 1.1 s after the match ends. If that feels slow for a win, wait for the next beat instead: one beat is 0.4 s, 6.9 mod 0.4=0.16.9 \bmod 0.4 = 0.1, so the wait is 300 ms. Waiting for a beat is quicker; waiting for a bar sounds more finished. In Web Audio, schedule the stinger by time rather than by checking each frame: stinger.start(ctx.currentTime + 1.1) lands on the sample.

Lobby to match. The lobby loop is at 120 BPM (2 s bars) and the match loop at 150 BPM (1.6 s bars). Two loops at one tempo could use the same bar-line wait. These cannot, so use a fade or a crossfade over about one bar of the outgoing loop, because a bar line of one tempo is not a bar line of the other.

In a game's audio pipeline

Stingers are cut after Seamless music loops settles the loops' tempo and key, and they go through Loudness for games with the loops, judged by ear against the loop they follow. The wait-to-bar logic lives in the game's code, so write the tempo and bar length into the audio manifest next to the file names when you reach Exporting game audio. The seeds and prompts go in each stinger's provenance record (see Licensing and provenance).

Common mistakes

  • Wrong key. Symptom: the stinger sounds sour against the last notes of the loop, as if two songs were playing.
  • Wrong tempo. Symptom: the beat stumbles at the handoff, even when the stinger starts on a bar line.
  • Tail cut off. Symptom: the last chord stops dead, followed by silence or the next loop.
  • Silence at the start. Symptom: the win feels late. A generated short clip often begins with a few hundred milliseconds of nothing; trim to the first attack.
  • Hard cut to the stinger. Symptom: a click and a jolt when the loop stops mid-note. Fade the loop, even if only for 50 ms.
  • Stinger restarted on repeated events. Symptom: rapid wins or button presses retrigger the stinger, stuttering. Let a playing stinger finish, or ignore new triggers until it does.

Cost

Stingers are cheap to generate: a few seconds of audio per take, so a batch of a dozen candidates costs little model time. The time goes to listening for key and tempo against the loop, which means playing loop and stinger together in an editor or in the game. Files are small: the two stingers above total 7.8 s of stereo audio. The bar-line wait costs the player up to one bar of delay (1.6 s at 150 BPM), or up to one beat if you wait for beats; the computation itself is a single remainder.

Going further

  • Horizontal re-sequencing: building longer music from short segments chosen at bar lines, the general form of "wait for the bar".
  • Vertical layering: one loop with stems (drums, bass, melody) faded in and out as the game's tension rises.
  • Variations and audio-to-audio, for making a stinger from the loop itself so it shares its sound.
  • The Web Audio scheduling model: AudioContext.currentTime and starting sources at a future time.

Back to Local text-to-audio for games