{What I Love!}
Hello! I’m Scruffy, and today, I’m going to show you how to implement my favorite little detail
of the sound design in Mario Kart, that’s been around since the Nintendo 64 edition.
And it’s not anything to do with the music of
the series—I love Mario Kart’s music and the adaptive details to it, but I’m treating
all that as a separate entity from this video.
If you really want what I love most about the raw sound effects of racing with Mario
characters, it’s—
[kart races by]
Heh, it's the—
[another kart races by]
It's that, the Doppler effect.
That natural phenomenon where the sounds from a fast-moving object change in frequency as
it moves toward or away from an observer.
Observing this effect is easy!
You'll notice it especially when something loud passes you at high speeds, such as a
train or an ambulance.
The Doppler effect is integral to the feeling of going fast, and thus it’s key to racing
games, so much so that Mario Kart games often open with the sound of karts speeding by,
demonstrating the effect.
And as you’re driving on a Mario Kart track and karts are passing each other, it sounds
natural for the Doppler effect to occur, doesn’t stand out at all.
Er, well, maybe sometimes it does: in Mario Kart Wii in particular, they really went all
out with the Doppler effect: kart engines, kart horns, even the sounds of an Invincible
Star or a Mega Mushroom—they all change pitch depending on their velocity relative
to you, the listener.
And that clues us in that none of this is pre-baked into the sound effects.
There’s a system handling this in real time.
Some proprietary game engines nowadays have an optional Doppler effect built into a sound emitter.
But honestly, the basic system wouldn’t be too difficult to implement ourselves.
We can start small, with some visual aid, and think about how we might construct this sort of system.
So, the Doppler effect occurs when an object is moving while generating waves.
Because this source of the sound waves moves over time, and the
waves are moving at a constant speed of sound, the crests of those waves get bunched together
in the direction the object is moving, and they’re more spread out opposite the direction
the object is moving.
So, to someone like me, at rest over here, I’ll hear the bunched up sound waves as
higher in frequency as the car approaches, and then suddenly lower in frequency when
the car passes and I’m in the spread-out zone.
The faster the object, the more drastic the difference.
But that’s only because the kart is moving relative to me: if I were in the kart, I wouldn’t
be moving relative to the sound source, and thus I wouldn’t hear any Doppler effect.
Now there’s more to the Doppler effect than just that: there’s different mediums in
which waves can travel, there’s going fast enough to create a sonic boom, there’s the
other kinds of waves, like light waves or microwaves, that demonstrate the Doppler effect.
But for our purposes in this game, we just need to know that there’s a connection between
sound frequency and relative velocity.
So, let’s begin there.
We’ll need an audio listener, that’ll be this flagged kart here.
This is the observer hearing the sounds.
And then we’ll need a subject to make an engine sound, this other kart.
To measure the relative velocity between these two, we’d need to figure out how fast one
is approaching or moving away from the other.
So, first we’ll measure the distance between the two karts.
That’s our first variable, NewKartDistance, and it will be updated every frame, so it
can and will change.
But, we’ll add another variable, OldKartDistance, one that remembers the distance on a frame.
And then on the next frame, NewKartDistance will be updated, but before OldKartDistance
is updated, we’ll compare the two, just subtract Old from New, and that difference
becomes our rate of change, in units per frame.
We store that rate of change as a variable, VelocityRelative, and that will drive the
effect on our sound system.
We'll map out a range of values, positive and negative, that VelocityRelative can be,
and that will correspond to the speed at which our sound can play.
If VelocityRelative equals zero, that means the karts are not getting any closer or farther
from each other, so that would mean the sound plays at regular speed, 100% speed.
And notice, that doesn’t factor in how fast the karts are actually going: they could be at
rest, or both bookin’ it top speed, and the Doppler effect would not be present because
the sound source and the listener are not moving relative to each other.
Now, if VelocityRelative is negative, that means the distance between the karts is decreasing,
and that corresponds to a sound speed greater than 100%.
And conversely, if VelocityRelative is positive, that means the karts are getting farther apart,
and the sound speed would be less than 100%.
The exact mapping of sound speed will be weird here since… there is no speed of sound in
the game world. Sound “travels” instantly, there’s no delay.
So, how you map VelocityRelative to sound speed kinda depends on preference: how much
do you want to exaggerate the Doppler effect?
The system on which that’s built works, so that final step becomes a matter of taste.
And there you have it, the Doppler effect between one opponent kart and you, the audio listener.
Now multiply that by every opponent kart.
This may look complicated, but to a computer it’s not so bad, especially if we only perform
this function while the sound is in earshot of us.
Now, bonus question, and this one’s a little harder: what if there were multiple audio listeners?
And I don’t mean online multiplayer where everyone has their own screen, I mean splitscreen,
where two or more players share audio playback.
You could have every kart track every player, and perform individualized Doppler effects,
but that’s where it starts to get costly on the audio engine.
So, while I don’t know the exact code behind it, I have observed a solution Nintendo thought
up to this.
First of all, players just don’t exhibit a Doppler effect.
The developers thought: Player 2 doesn’t need to hear a unique, Dopplerized version
of Player 1 when they’re already taking up half the screen and half the audio.
Ok, but how about computer players?
Let’s make an example where, Player 1 is at rest on the side of the road, and Player
2 is driving roughly the same speed as a CPU driver.
As they pass player 1, what do you hear?
Does Player 1 hear a Doppler effect, and Player 2 doesn’t?
This is a cool answer: as far as I can tell, the CPU kart also tracks which player is closer
to it, and it applies the Doppler function relative to whoever is closest.
So, Player 2 starts out closer, you wouldn’t hear any Doppler effect since they’re traveling
at the same speed.
But as Player 1 becomes the closest, the CPU switches its focus to Player 1, and applies
an appropriate Doppler effect.
Then when it’s passed Player 1 and Player 2 is once again the focus, it goes back to
playing sound for Player 2.
Might sound a little jarring to jump between effects like that, so there are some makeshift
solutions on top of that.
In Mario Kart Wii, CPU kart audio is ducked a little under other sounds when multiple
players are near it.
In Mario Kart 8, the Doppler effect of one CPU kart has some damping on it, so it takes
some time for the sound speed to gradually get to where it should be.
The same damping is applied to the kart’s stereo position: it gradually shifts from
being right of Player 2 to left of Player 1, and then back.
And finally, in all Mario Kart games, only some sounds experience the Doppler effect.
Kart engines yes, kart horns sometimes, item sound effects fewer times, and other sounds
like stage props or character voices often just aren’t Dopplerized.
This is a cartoon world, after all, and while the Doppler effect conveys a real sense of
speed, everything else should convey a sense of cartoonish clarity.
And that’s my favorite part of the sound design in Mario Kart.
It’s stood the test of time, while still allowing every player and computer to each
make only one instance of sound effects, which I find pretty elegant.
I’d like to thank my friend jesterzon for helping with the concept of this video, and
with the final music arrangement here. And my friend Wolfgang for helping me with the script.
I'd also like to thank my patrons on Patreon, who help make my videos a more sustainable process.
If you’d like to support my work directly and get perks like your credit here, seeing
videos early, a vote on what music I arrange, and more behind-the-scenes content, you can
visit my Patreon link in this video’s description.
And with that, I’m Scruffy, and thank you very much for driving by.