An interactive course · Sony S-SMP + S-DSP

How the Super Nintendo made sound.

We start from the very beginning — what a digital sound even is — assuming you know nothing about audio. Once the vocabulary is solid, we open up Nintendo's little audio computer: the SPC700 CPU, its 64 KB of private RAM, and the S-DSP that decodes samples and mixes eight voices into 32 kHz stereo. Sixteen modules, each with a live synthesiser so you can hear every idea. No game audio ships with this page; every sound is generated in your browser.

Begin Part I
Part I

Digital sound from zero

This first part is pure fundamentals — nothing about any specific chip yet. It's the toolkit that every piece of digital audio gear is built from, whether that's a phone, a CD player, or the little Sony chip we'll meet in Part II. We build the vocabulary one word at a time — wave, sample, harmonic, compression, envelope, pitch, echo — and you can play and see each idea with a synthesised tone. If a term is ever used before it's explained, that's a bug. Everything in Parts II and III is just these ideas wired into silicon.

Modules 01–07Difficulty Absolute beginnerLabs 7 interactive
Module 01 · Part I

Sound as waves

GoalUnderstand what sound physically is, and the three numbers that describe any simple tone: frequency, amplitude and phase.

Let's start with what sound physically is. When something vibrates — a guitar string, your vocal cords, a speaker cone — it pushes and pulls on the surrounding air, making tiny, fast changes in air pressure. Those changes ripple outward as a wave and reach your eardrum, which vibrates in step. That's all sound is: a wobble in air pressure over time.

To put that wobble in a computer we do something wonderfully simple. Many thousands of times per second we measure the pressure and write the number down. Each measurement is called a sample. String the samples together in order and you have the whole sound as a plain list of numbers; feed that list back to a speaker at the same speed and the sound reappears.

Analogy · A flipbook

A movie isn't really moving — it's a stack of still photos shown fast enough that your eye fills in the motion. Digital sound works the same way: each sample is a still “photo” of the wave's height at one instant. Play the photos back quickly and smooth sound returns. Take too few per second and, like a choppy movie, it comes out wrong — that's Module 02.

Three numbers describe any simple wave. Its frequency is how many times it repeats each second, measured in hertz (Hz) — 440 Hz means 440 cycles a second, and higher frequency means higher pitch. Its amplitude is how far the wave swings from rest — how loud it is. And its phase is where in the cycle it happens to start. Hold on to frequency and amplitude; they run through the whole course.

Continuous pressure wave measured at each tick ↓ → a list of numbers amplitude = height · frequency = cycles per second
Sound as numbers. A smooth pressure wave is measured at regular ticks; each measurement — a sample — becomes one number. The wave's height is its amplitude; how fast it repeats is its frequency.

The basic shapes

A synthesiser like the one on this page builds everything from a few shapes. A sine is the purest tone — one frequency, no extra colour, like a tuning fork. Square and saw(tooth) are jagged and buzzy — those classic chiptune “bleeps” — because they're secretly a sine plus a pile of higher tones (Module 03). Triangle sits in between, mellow but a little richer than a sine. Noise is every frequency at once with no pitch — your “shh”: wind, static, a snare. Play with the scope: switch shapes, sweep the frequency, and watch the trace while you listen.

Signal lab — waveforms on a scopeWeb Audio · live

The trace is an oscilloscope: it draws amplitude (up/down) against time (left/right), so you're literally seeing the stream of sample values as a line.

Key takeaways
  • Sound is a pressure wave; a digital signal is that wave measured as regularly-spaced numbers (samples).
  • Frequency = pitch (Hz); amplitude = loudness; phase = where the cycle starts.
  • Sine, square, saw, triangle and noise are the building blocks a synth combines.
Module 02 · Part I

Sampling & quantisation

GoalLearn the two knobs of every digital format — sample rate and bit depth — and hear what happens when each is set too low.

Storing sound as numbers raises two questions. How often do we measure, and how precisely do we write each measurement down? The answers are the sample rate and the bit depth, and together they define any audio format — including the SNES's.

The sample rate is measured in samples per second, again in hertz. There's a hard rule about it, the Nyquist limit: to capture a frequency you must sample more than twice as fast. You've seen this rule with your eyes: in old films a fast-spinning wagon wheel can appear to crawl or even roll backwards, because the camera's frames sample the motion too slowly — the flipbook from Module 01 with too few pages. Sample sound too slowly and high frequencies do the same trick: they don't just vanish — they fold back down and reappear as false, lower tones. That folding is called aliasing, and it sounds like a metallic, warbly grunge riding on top of the sound.

The S-DSP mixes all its voices internally and pushes out 16-bit stereo at 32 000 Hz. By Nyquist that gives a ceiling of 16 kHz — a touch shy of the ~20 kHz limit of young ears, which is part of why the SNES sounds warm and slightly soft rather than crisp and clinical. Individual voices are usually stored at rates well below 32 kHz to save precious RAM; the chip then reads them out more slowly — a per-voice pitch register set below its neutral value of $1000 — so they still sound at their true pitch (Module 06). Raising that register above $1000 is what shifts a sound up.

Aside · What's a “bit”?

A bit is a single 0-or-1 switch. Line up n of them and you can spell 2n different patterns: 2 bits give 4, 8 bits give 256, 16 bits give 65 536. “16-bit audio” simply means each sample is written down as one of 65 536 possible values.

Bit depth is the other knob: how many distinct values a sample can take. 16-bit gives 65 536 possible levels; drop to 8-bit and you have only 256, so every sample must snap to the nearest available rung. That rounding is quantisation, and the error it introduces is heard as a gritty hiss — quantisation noise. The lab below lets you strangle both knobs on a bright tone. Drop the rate to hear aliasing; drop the bits to hear the crunch. The reference button plays it back at the SNES's own 32 kHz / 16-bit.

Sample & hold + quantisation grid smooth wave (cyan) → held between ticks and snapped to the nearest rung (magenta) dashed rungs = the only levels this bit depth can write down Aliasing — the fold-back Nyquist = 16 kHz (fs ÷ 2) 0 32 kHz true tone · 24 kHz alias · 8 kHz reflects off fs ÷ 2
The two failure modes. Left: sample-and-hold turns a smooth wave into a staircase, and quantisation snaps each step to the nearest available rung — the snap error is quantisation noise. Right: a 24 kHz tone sampled at 32 kHz is above the 16 kHz Nyquist limit, so it folds back and plays as a false 8 kHz tone — aliasing.
Sampling lab — starve the two knobsWeb Audio · live
Key takeaways
  • Sample rate = how often; the Nyquist limit is half the sample rate — above it, sound aliases.
  • Bit depth = how precisely; too few bits adds quantisation noise (a gritty hiss).
  • The S-DSP outputs 16-bit stereo at 32 000 Hz — a 16 kHz ceiling, hence its warm tone.
Module 03 · Part I

Waves add up

GoalSee that every timbre is a sum of pure sine waves — the harmonics — and build tones by stacking them yourself.

In Module 01 we said a square or saw wave is “secretly a sine plus a stack of higher tones.” That wasn't a metaphor. It's one of the most important facts in audio, and we owe it to the mathematician Fourier: any sound, however complicated, is just a sum of simple sine waves at different frequencies and volumes. Add the right sines and you can build any waveform; pull a sound apart and you always find sines underneath.

The lowest sine is the fundamental — the pitch you actually hear. The sines stacked above it, at 2×, 3×, 4×… the fundamental's frequency, are the harmonics. Their pattern of loudnesses is what makes a flute sound different from a trumpet at the same pitch. A pure sine has no harmonics at all; a saw has every harmonic, each a bit quieter than the last; a square has only the odd ones.

Analogy · A recipe

The finished tone is a baked cake — you taste it all at once. The list of harmonics is the recipe: two parts fundamental, one part second harmonic, a pinch of the fifth. Change the amounts and you've baked a different instrument. The mixer below is that recipe card, live.

Saw — every harmonic, 1/n loud = this waveform Square — odd harmonics only = this waveform bar height = how loud that harmonic is · the “recipe card” on the left bakes the waveform on the right
Recipe → waveform. A sawtooth contains every harmonic, the n-th at 1/n the loudness; a square keeps only the odd ones. Same fundamental, different recipe, different shape — and a different sound.

Slide the first eight harmonics up and down and listen to the timbre change, or hit a preset to snap to a sine, a saw, a square or a reedy organ. This is additive synthesis — building sound by piling sines up. (The SNES doesn't synthesise this way; it plays recorded samples. But understanding harmonics is what lets you read why one sample sounds bright and another dull.)

Additive lab — stack the harmonicsWeb Audio · live
100%
0%
0%
0%
0%
0%
0%
0%
Key takeaways
  • Any tone = a sum of sine waves: a fundamental plus harmonics at whole-number multiples.
  • The pattern of harmonic loudnesses is the timbre — why a flute ≠ a trumpet.
  • Saw = all harmonics; square = odd harmonics only; sine = fundamental alone.
Module 04 · Part I

Squeezing samples: ADPCM & BRR

GoalUnderstand ADPCM compression, then learn the SNES's exact BRR format — 9-byte blocks, four filters — by encoding and decoding a sound yourself.

The SNES has only 64 KB of audio RAM (Part II), so every sample must be tiny. Raw 16-bit audio is far too fat, so the chip stores everything in a compressed form. The trick is ADPCM — Adaptive Differential PCM. Instead of storing each sample's full value, ADPCM predicts the next sample from the previous ones and stores only the small correction, in just a few bits. Sound changes smoothly, so the corrections stay small, and a handful of bits is plenty.

The SNES's specific flavour is called BRR — Bit Rate Reduction — and it's beautifully rigid. Samples are packed into 9-byte blocks, each holding exactly 16 samples. The first byte is the header; the remaining eight bytes hold sixteen 4-bit signed nibbles, one per sample — each a tiny signed value spanning just −8…+7.

Aside · Reading hexadecimal

From here on you'll see numbers like $C5. The $ marks hexadecimal — base 16, with digits 0–9 and then A–F standing for 10–15. Each hex digit is exactly four bits (one nibble), which is why hardware people love it: a byte is always two hex digits, $00$FF = 0–255. So $C5 = 12 × 16 + 5 = 197.

One BRR block — 9 bytes, 16 samples byte 0 · header shift 4b flt 2b L E bytes 1–8 · sixteen 4-bit nibbles (one per sample) s0s1s2s3 s4s5s6s7 s8s9s10s11 s12s13s14s15 header bits: shift/range (4) · filter select (2) · LOOP (1) · END (1) decode: sampleₙ = (nibble ≪ shift ≫ 1) + filter(prev₁, prev₂) ≈ 16-bit PCM 32 bytes → 9 BRR bytes ≈ 3.5 : 1
The BRR block. A header byte carries a 4-bit shift (how far to scale the nibbles), a 2-bit filter select, and the LOOP and END flags; eight data bytes hold the sixteen 4-bit samples.

Decoding is where the “adaptive” and “predictive” parts live. Each 4-bit nibble is first scaled up by the header's shift (0–12). Then one of four filters reconstructs the real sample by adding a prediction from the previous one or two decoded outputs:

  • Filter 0 — no prediction; the nibble stands alone. Used at the start of a sample so nothing leaks in from before.
  • Filter 1 — adds about 0.94× the previous sample. A gentle slope-follower.
  • Filters 2 and 3 — use the previous two samples for a stronger prediction, ideal for smooth, tonal material.

Let's decode one sample by hand, with real numbers. Say the header set shift = 8 and filter 1, the previous decoded sample came out as 1000, and the next nibble is −3. First the scaling, (nibble << shift) >> 1: shift −3 left by 8 places to get −768, then halve it → −384. Next the prediction: filter 1 contributes about 15⁄16 of the previous sample, ⌊1000 × 15⁄16⌋ = 937. Add them: 937 − 384 = 553. That's the reconstructed 16-bit sample — sixteen of those little sums and the block is done.

Two header flags finish the picture. END marks the last block of a sample; LOOP, when set on that final block, tells the hardware to jump back to a loop point instead of going silent (Module 10). One subtlety hides there: filters 1–3 lean on samples decoded before the block, so the block at the loop point should use filter 0 (or data crafted so the history matches), otherwise the first pass and every repeat through the loop decode slightly differently and the joint clicks — we'll see the loop machinery in Module 10. The whole scheme lands around a 3.5 : 1 squeeze — 32 bytes of PCM become 9 bytes of BRR.

The lab actually runs a BRR codec. It synthesises a short plucked waveform, encodes it to real 9-byte blocks (brute-forcing the best filter and shift per block, exactly as tools like BRRtools do), then decodes and plays it back. Compare the source with the decoded version — the loss is audible but small — and inspect the block headers.

BRR codec — encode, decode, inspectWeb Audio · live
Key takeaways
  • ADPCM stores a prediction plus a small correction, not the full sample — cheap and compact.
  • BRR = 9-byte blocks of 16 samples: 1 header + 8 data bytes of 4-bit nibbles.
  • The header holds a 4-bit shift, a 2-bit filter select, and LOOP + END flags; four filters reconstruct from the previous 1–2 samples.
Module 05 · Part I

Envelopes — shaping a note over time

GoalLearn how a note's loudness changes from start to finish, and the four-stage ADSR shape used to describe it.

A real note isn't a steady blast — its loudness changes from the moment it starts to the moment it dies away. That loudness-over-time curve is the envelope, and it matters as much as the waveform. The very same tone with a slow, swelling envelope becomes a string pad; with a sharp attack and quick decay it becomes a plucked harp. Envelope is character.

The classic way to describe an envelope has four stages, abbreviated ADSR:

  • Attack — how quickly the note fades in to full volume when it starts.
  • Decay — how quickly it then falls back to a held level.
  • Sustain — the held level while the note is still on. (This is a loudness, not a time.)
  • Release — how quickly it fades to silence once the note is let go.
Analogy · Pressing a piano key

Strike a piano key hard and the sound leaps up (attack), settles back a little (decay), and hums at a steady level as long as you hold the key (sustain). Lift your finger and it fades out (release). A pipe organ has an almost instant attack and a sustain that never droops; a plucked string has a fast attack and no sustain at all. Same four stages, different settings.

Draw an envelope with the sliders below and hear it applied to a live tone. Watch how the same sawtooth becomes a pluck, a pad, or a stab depending only on the four numbers. In Part II you'll set these exact stages on the S-DSP's hardware envelope registers (Module 11).

Envelope lab — shape a note with ADSRWeb Audio · live
Key takeaways
  • An envelope is a note's loudness shaped over time; ADSR = Attack, Decay, Sustain, Release.
  • Sustain is a level (how loud while held), not a duration.
  • The same waveform with different envelopes becomes different-sounding instruments.
Module 06 · Part I

Playing at any pitch

GoalUnderstand resampling — playing one stored sample at many pitches — and why the quality of the interpolation matters.

A game can't store a separate recording for every note; there isn't the RAM. Instead it stores one sample and plays it back faster for a higher pitch or slower for a lower one. You already know this trick from tape decks: run the tape fast and a voice turns squeaky and chipmunk-like; run it slow and it drops to a growl. Changing a recording's playback speed changes its pitch. Reading a stored waveform at a new speed is called resampling, and it's the beating heart of a sample-based sound chip.

The catch: to play back faster you need sample values between the ones you stored — at fractional positions like “sample 4.63.” You have to make up those in-between values, and how you do it is called interpolation. The crudest method, nearest-neighbour, just grabs whichever stored sample is closest — cheap, but it produces a jagged, aliased buzz. Linear interpolation draws a straight line between the two neighbours — better, but corners in the signal still add grit.

The read head lands between samples 012 345 678 read position 4.63 ← this value doesn't exist — it must be invented dots = stored samples (violet) · the playhead needs a value 63% of the way from sample 4 to sample 5 — that invention is interpolation
Between the dots. Resampling asks for values at fractional positions like “sample 4.63”. Nothing is stored there, so the chip must invent one from the neighbours — nearest grabs sample 5, linear draws a line from 4 to 5, and the SNES blends four neighbours (below).

The SNES uses something nicer: a 4-point Gaussian interpolation. For each fractional position it takes the four nearest stored samples and blends them with weights read from a fixed Gaussian-shaped table baked into the chip — a 512-entry table on the real silicon, which the lab below stands in for with a smooth Gaussian approximation (the same shortcut its code comments admit to). The result is smooth, and it gently rolls off the highest frequencies — which, along with the 32 kHz output, is the other half of why the SNES sounds so soft and round. Play the same bright sweep through nearest and Gaussian and the difference is immediate.

The resample speed is set by a per-voice 14-bit register, VxPITCH. A value of $1000 means the DSP consumes exactly one stored sample per output sample — the data is read at the output rate of 32 000 samples per second. Double it to $2000 and the DSP steps through two stored samples per output sample: an octave up. VxPITCH's slot in the register table arrives in Module 09; the interpolation hardware behind it in Module 12.

Interpolation lab — nearest vs GaussianWeb Audio · live
A bright sweep “stored at 32 kHz” resampled three ways. Listen to the highs:
Key takeaways
  • Resampling = playing one stored sample faster or slower to change its pitch.
  • Faster playback needs invented in-between values — that's interpolation.
  • Nearest is buzzy; the SNES's 4-point Gaussian is smooth and rolls off the highs (its warm sound).
Module 07 · Part I

Echo, reverb & filters

GoalBuild up delay, feedback and filtering — the three ingredients behind the SNES's signature reverb, before we meet the real echo unit.

The last big idea before the hardware is space. A sound in a room reaches your ear directly, then again a moment later after bouncing off the walls, and again and again, each bounce quieter. Recreate that and a dry, flat sample suddenly sits in a cathedral. It's built from three simple parts.

The first is a delay line: a short memory that holds the sound and plays it back a set number of milliseconds later. One delay gives you a single echo. The second is feedback: route the delay's output back into its own input, scaled down, and the echo repeats — each pass quieter than the last — until it fades. Many overlapping, decaying echoes blur into reverb.

The echo machine — three parts input + delay line holds the sound N ms output × feedback (0–1) each pass a bit quieter
Delay + feedback. The input enters a delay line; its output goes to the speakers and loops back through a feedback gain into its own input, so each echo repeats a little quieter. This exact template — with an ARAM buffer as the delay line and a filter in the loop — is what Module 13's echo unit builds in silicon.

The third part is a filter. Real walls absorb high frequencies more than low ones, so each echo should come back a little duller than the last. A filter does exactly that. The most flexible kind is an FIR filter, which builds each output sample as a weighted sum of the last few input samples; the weights are called taps. Choose the taps and you choose the filter's colour. The SNES bakes exactly this into its echo hardware — an 8-tap FIR — which we'll design in Module 13.

“Weighted sum” sounds fancier than it is. Take a 3-tap FIR with taps 0.5, 0.3, 0.2, and suppose the three most recent input samples were 10, 20, 40 (newest first). The output sample is 0.5 × 10 + 0.3 × 20 + 0.2 × 40 = 5 + 6 + 8 = 19. That's the whole algorithm: multiply each recent sample by its tap, add, slide forward one sample, repeat — 32 000 times a second.

Echo playground — delay + feedbackWeb Audio · live
Short delay + high feedback = a metallic tunnel; long delay + low feedback = discrete echoes. Changes apply live.
Key takeaways
  • An echo is a delay line; feedback makes it repeat and decay.
  • Many overlapping decaying echoes blur into reverb — a sense of space.
  • An FIR filter is a weighted sum of recent samples (taps); it colours each echo. The SNES uses an 8-tap FIR.
Part II

The SNES sound hardware

Now we meet the silicon. The Super Nintendo's audio is handled by a near-independent little computer, the Sony S-SMP, wired to the S-DSP mixer. Every idea from Part I is about to become a register: BRR blocks in RAM, eight hardware voices, ADSR and GAIN envelopes, a 14-bit pitch, the 4-point Gaussian, and an echo unit with an 8-tap FIR. We'll go block by block — and every lab drives the real register names and addresses.

Modules 08–14Focus Real registersLabs 7 interactive
Module 08 · Part II

The S-SMP & the SPC700

GoalSee that SNES audio is a second computer with its own CPU, RAM and boot ROM, talking to the main system through a four-byte mailbox.

Here's the surprise that defines SNES audio: it isn't a peripheral, it's a whole second computer. Sony's S-SMP package — often just called the APU, the Audio Processing Unit — contains its own CPU, its own memory, its own boot ROM, and the sound mixer, all running on a separate crystal. The main SNES CPU can't reach into it directly at all.

Inside the S-SMP:

  • The SPC700 — an 8-bit CPU running at roughly 1.024 MHz, with a small, quirky instruction set of its own.
  • 64 KB of private audio RAM (ARAM) — the SPC700's entire world: driver code, the sample directory, all BRR samples, and the echo buffer share this one space.
  • Three timers the driver reads to keep musical time — T0 and T1 tick at 8 kHz, T2 at a finer 64 kHz.
  • A 64-byte IPL boot ROM that runs at power-on and knows how to receive an upload.
  • The S-DSP (next module), which does the actual sample decoding and mixing.
Main system 65816 S-CPU · 21.477 MHz WRAM · PPU · cartridge uploads driver + samples, then just sends note events S-SMP (APU) SPC700 ~1.024 MHz S-DSP 8 voices · 32 kHz 64 KB ARAM · driver + samples + echo 3 timers (T0/T1 · T2) 64-byte IPL ROM 4-byte mailbox $2140–$2143 = $F4–$F7 on the SPC side
Two computers, four bytes between them. The main CPU and the S-SMP each run on their own clock and share nothing but a four-register mailbox — $2140–$2143 on the CPU side, the same latches as $F4–$F7 on the SPC700 side.

Before the handshake, one thing is worth pinning down: what does “writing to $2140” physically mean? Not every address in a computer is RAM. Some addresses are wired straight to a chip instead — store a byte there and it lands in a register, a byte-sized cell of the hardware itself. This is memory-mapped I/O: the CPU talks to other chips with the same store instructions it uses for memory, just at special addresses. The four mailbox ports are latches — each simply holds the last byte one side wrote until the other side gets around to reading it. And the driver we keep mentioning is not hardware at all: it's a program, the piece of SPC700 code that reads those mailbox bytes and turns them into music. It gets a module of its own (Module 14).

All communication squeezes through those four mailbox ports. At power-on the main CPU can't just poke samples into ARAM; it has to hand them over through a handshake with the IPL boot ROM. The CPU uploads a sound driver plus all the BRR samples, tells the SPC700 where to start, and from then on the APU runs on its own — the game only sends short note events (“play sample 5 at this pitch”) whenever the music demands. Step through that boot handshake below.

Boot handshake — one mail at a timeno audio · protocol
Key takeaways
  • SNES audio is a near-independent computer: SPC700 CPU + 64 KB ARAM + timers + IPL ROM + the S-DSP.
  • Main CPU and APU share only a 4-byte mailbox — $2140–$2143 (CPU) / $F4–$F7 (SPC).
  • The CPU uploads a driver and samples via the IPL boot handshake, then the APU plays on its own.
Module 09 · Part II

The S-DSP & its 8 voices

GoalMeet the mixer: eight independent hardware voices, the 128-byte register file that controls them, and how they sum to 32 kHz stereo.

The S-DSP is the part that actually makes sound. It runs eight independent voices, and every voice is a little assembly line: it reads a BRR sample from ARAM, resamples it to the wanted pitch (the Gaussian of Module 06), shapes it with an envelope (ADSR or GAIN), and scales it by a left and a right volume. All eight results are summed and pushed out as one 16-bit stereo pair, 32 000 times a second.

One voice (×8) BRR source VxSRCN · from DIR pitch / resample VxPITCH · Gaussian envelope VxADSR / VxGAIN L / R volume VxVOL L/R Σ mix all 8 voices × MVOL L/R 16-bit 32 kHz stereo …voices 2–8 identical, each with its own registers · global KON/KOFF start & stop them
The voice assembly line. Source → pitch → envelope → volume, eight times over, summed and scaled by the master volume into 32 kHz stereo.

The S-DSP is controlled entirely through a 128-byte register file, addressed $00$7F. It's laid out cleverly: the low nibble of the address picks a field, the high nibble picks the voice, so each voice gets a tidy 16-byte row. Per voice you get:

RegisterAddress (voice x)What it does
VxVOL L / R$x0 / $x1left and right volume for the voice (signed)
VxPITCH$x2 / $x314-bit resample rate — the pitch
VxSRCN$x4which sample to play (index into the directory)
VxADSR1/2$x5 / $x6the ADSR envelope settings
VxGAIN$x7the alternative GAIN envelope mode
VxENVX / VxOUTX$x8 / $x9read-back: current envelope level and output

Those volumes being signed is not a technicality. A negative volume flips the waveform upside down — it inverts its phase (Module 01). Set a voice's left volume positive and its right volume negative and the two speakers push and pull in opposition, a trick games leaned on for wide, pseudo-surround effects.

The rest of the file is global: KON/KOFF key voices on and off (one bit each), FLG holds mute/reset, the noise clock and the echo-write-enable bit ECEN (remember it — it matters in Module 13), MVOLL/R and EVOLL/R are the master and echo volumes, PMON/NON/EON enable pitch-modulation, noise and echo per voice, DIR points at the sample directory (Module 10), ESA/EDL place the echo buffer and EFB ($0D) sets its feedback (Module 13), C0C7 are the echo FIR taps, and the read-only ENDX ($7C) reports which voices have reached their sample's END block. Toggle the eight voices below and hear them sum.

8-voice mixer — the whole S-DSPWeb Audio · live
V1tri
V2saw
V3sqr
V4sin
V5tri
V6saw
V7sqr
V8sin
ON/OFF keys each voice · tall slider = volume · wide slider = pitch (±1 octave). Changes apply live.
Key takeaways
  • The S-DSP mixes 8 voices — each source → pitch → envelope → L/R volume — into 32 kHz stereo.
  • A 128-byte register file ($00–$7F) controls it: 16 bytes per voice plus global registers.
  • KON/KOFF start and stop voices; MVOL sets the master volume.
Module 10 · Part II

BRR samples & the sample directory

GoalFollow how the DSP locates a sample in ARAM through the directory table, and how the LOOP flag makes a short sample sustain forever.

A voice's VxSRCN register just says “play sample number 5.” How does the DSP turn that number into an address in ARAM? Through a lookup table called the sample directory. The global DIR register holds the high byte of where that table lives, and each entry is four bytes: a start pointer and a loop pointer, both 16-bit. VxSRCN is simply the index into it.

From “play sample 5” to bytes in ARAM VxSRCN = 5 sample directory table @ DIR × $100 = $2000 0 · start $2100 · loop $2100 1 · start $2180 · loop $21B0 5 · start $2450 · loop $2462 entry addr = $2000 + 5 × 4 = $2014 4 bytes: start lo·hi, loop lo·hi start $2450 hdr (filter 0) + 16 samples $2459 hdr + 16 samples $2462 loop point + 16 samples $246B END + LOOP + 16 samples loop pointer on END+LOOP: jump back, keep playing 9 bytes per block, so consecutive blocks sit 9 apart: $2450 → $2459 → $2462 → $246B · the attack blocks play once; the loop region repeats forever
The lookup chain. VxSRCN = 5 indexes the directory at DIR×$100; entry 5 (at DIR×$100 + 5×4) holds two 16-bit pointers. Decoding starts at start and walks 9-byte BRR blocks until the END flag; with LOOP also set, playback bends back to the loop pointer — usually mid-sample, past the attack.

So keying a voice on does this: read VxSRCN, jump to DIR's table, pull out the start and loop addresses for that entry, and begin decoding BRR blocks from the start address. The hardware walks block after block until it hits one with the END flag set. What happens next depends on the LOOP flag in that same header:

  • END set, LOOP clear — the voice goes silent. This is a one-shot: a drum hit, a footstep.
  • END set, LOOP set — the voice jumps to the loop pointer and keeps decoding. This is how a half-second recording of a violin sustains for as long as the note is held.

That loop pointer usually lands partway into the sample — a short attack plays once, then a small steady-state section repeats forever. It's the single most important trick for fitting real instruments into 64 KB. The lab decodes a real looping BRR sample and lets you play it once or hold the loop.

Sample directory + looping playbackWeb Audio · live
“Hold the loop” plays the attack blocks once, then repeats only the region between the loop pointer and the END block — exactly the hardware behaviour — for as long as you let it ring. Press play elsewhere or scroll away to stop.
Key takeaways
  • DIR points at a table of {start, loop} pointers; VxSRCN indexes it.
  • The DSP decodes BRR blocks from the start pointer until it sees the END flag.
  • END + LOOP jumps to the loop pointer, so a tiny sample can sustain indefinitely.
Module 11 · Part II

ADSR & GAIN on hardware

GoalSet the S-DSP's real envelope registers bit by bit — the ADSR fields and the GAIN modes — and watch the ENVX level readback move.

Module 05 drew envelopes as smooth curves. On the S-DSP an envelope is a handful of bits, and there are two ways to make one. The first is hardware ADSR, packed into two registers per voice:

RegisterBitsField
VxADSR1 ($x5)bit 71 = use ADSR (0 = use GAIN instead)
bits 6–4 / 3–0decay rate (3 bits) · attack rate (4 bits)
VxADSR2 ($x6)bits 7–5sustain level (3 bits, in eighths)
bits 4–0sustain rate (5 bits) — how fast the level sags from the sustain level while the key is held

The rates aren't times in milliseconds — they're indices into a fixed rate table in the chip. A higher attack rate means a faster attack; the fastest is nearly instant, the slowest takes several seconds. A few real rows to calibrate your ear: attack rate 15 is effectively instantaneous and rate 14 takes about 6 ms, while attack rate 0 crawls up over ~4.1 s; the fastest decay (rate 7) falls in ~37 ms; sustain rate 31 fades in ~18 ms while sustain rate 1 takes a glacial ~38 s. Attack rises linearly; decay and the sustain phase fall exponentially, which is why SNES notes taper so naturally. Sustain rate 0 is special: it means “hold the sustain level forever,” used for organ-like tones.

One naming trap if you're mapping this back onto Module 05's ADSR: the sustain rate is not the release. It governs how the envelope keeps sagging from the sustain level while the key is still held. So where did the “R” go? It happens at key-off: when the driver clears the voice via KOF, the chip ignores the sustain rate entirely and applies one fixed release for every voice — a linear ramp down of 1⁄256 of full scale per output sample, so even a full-volume note reaches silence in about 8 ms. On this chip the release isn't programmable at all.

Two bytes, four stages VxADSR1 · $x5 E d d d a a a a E = 1 → use ADSR · ddd = decay rate · aaaa = attack rate VxADSR2 · $x6 s s s r r r r r sss = sustain level · rrrrr = sustain rate (while held!) the envelope those fields draw (key held) attack (linear) decay (exp) sustain level sustain rate (exp sag) key-off (KOF) fixed linear ramp −1/256 per sample ≈ 8 ms from full same for every voice · SR ignored
The bit-fields and their stages. ADSR1 packs the enable bit, decay rate and attack rate; ADSR2 packs the sustain level and the sustain rate — which shapes the slow sag while the key is held. The release is not in either byte: key-off always triggers the same fixed linear ramp (right panel).

The alternative is GAIN mode (bit 7 of ADSR1 cleared). GAIN gives the driver hands-on control: a direct mode sets the level outright, and four ramp modes slide the level: linear increase, bent-line increase (rises linearly, then eases off for the final quarter), linear decrease, and exponential decrease. Drivers use GAIN for effects ADSR can't express, like a slow fade-in or a custom multi-stage envelope. Either way, the chip exposes the current envelope level in the read-only VxENVX register (0–127) — the ENVX readout the lab tracks live.

Envelope register explorerWeb Audio · live
ENVX —
Key takeaways
  • VxADSR1/2 pack attack rate, decay rate, sustain level and sustain rate into bit-fields (rates are table indices, not times).
  • Sustain rate applies while the key is held; key-off (KOF) always uses the same fixed linear release ramp of −1/256 per sample.
  • Clearing ADSR1 bit 7 switches to VxGAIN: direct level, or four ramps — linear increase, bent-line increase, linear decrease, exponential decrease.
  • VxENVX reads back the current envelope level (0–127) at any instant.
Module 12 · Part II

Pitch, Gaussian interpolation & modulation

GoalWatch the 4-point Gaussian slide across stored samples, and meet two extras: pitch modulation and the noise generator.

Back in Module 06 we heard why interpolation matters. Here's how the S-DSP actually does it. For each output sample the chip needs a value at a fractional position between stored samples. It takes the four nearest stored samples — two behind, two ahead — and multiplies each by a weight read from a fixed 512-entry Gaussian table, indexed by the fractional part of the voice's accumulating pitch counter — the running position that grows by VxPITCH every output sample. (VxPITCH is the step size; the counter's fraction is where the read head currently sits between two stored samples.) Sum the four weighted taps and that's the output.

Drag the position below and watch the four active taps slide along the stored samples, their weights (g0…g3) shifting as the read head moves. Because the Gaussian is broad and smooth, it quietly attenuates the highest frequencies — the mathematical root of the SNES's soft treble.

Gaussian interpolation visualiserinteractive · live

Two more features ride on the pitch machinery. Pitch modulation (PMON) lets voice N's output continuously bend the pitch of voice N+1 — a cheap way to make growling, vibrato-rich, or metallic sounds without extra samples. (Voice 0 is the exception: it has no lower-numbered neighbour to listen to, so its PMON bit does nothing.) And the noise generator (NON) replaces a voice's sample with pseudo-random noise, clocked at a rate set in the FLG register — the source of wind, surf, cymbals and explosions. Both are per-voice enable bits, so a game can mix tonal voices, a modulated voice and a noise voice in the same eight.

PMON — the neighbour wiggle voice N−1 (e.g. V0) plays its own sample OUTX → PMON bit N set: N−1's output wiggles N's pitch voice N (e.g. V1) pitch = VxPITCH ± neighbour's output → vibrato, growl, FM-ish bells voice 0 is exempt no voice sits before it, so PMON bit 0 does nothing
One arrow. Setting a voice's PMON bit routes the previous voice's output (OUTX) into its pitch. Voice 0 has no previous voice, so its bit is dead — modulator pairs start at V0→V1.
Key takeaways
  • The S-DSP resamples with a 4-point Gaussian: four taps weighted by a fixed table indexed by the pitch counter's fractional part.
  • The Gaussian's smoothness rolls off highs — the technical reason for the SNES's warm tone.
  • PMON lets one voice modulate the next voice's pitch; NON swaps a voice for the noise generator.
Module 13 · Part II

The echo unit & the 8-tap FIR

GoalAssemble the signature SNES reverb from an ARAM echo buffer, feedback, and an 8-tap FIR filter you design tap by tap.

The lush reverb in so much SNES music comes from one dedicated block: the echo unit. It's the delay-feedback-filter machine of Module 07, built into the chip. The delay lives in a circular echo buffer inside ARAM: the ESA register sets its start page and EDL sets its length in 16 ms steps, from 0 to 15 — so the longest possible echo is 15 × 16 = 240 ms. (EDL = 0 is a special case: the buffer doesn't vanish but shrinks to a token 4 bytes.) The price is concrete: at 32 000 samples/s in 16-bit stereo, 240 ms of delay is 240 ms × 32 000 × 4 bytes ≈ 30 KB — nearly half of the 64 KB of ARAM, gone from the space the samples live in. Because the buffer sits in the same 64 KB as the samples, a long echo eats memory the samples could have used — a constant trade-off for SNES composers.

64 KB ARAM — one shared space driver code DIR table pointers BRR sample data echo buffer ESA start · EDL length ↑ echo steals RAM from samples — longer reverb = fewer/smaller instruments echo return → 8-tap FIR (C0…C7) → × EFB feedback → back into the buffer → × EVOL into the mix
The echo detour. Output is written into the ARAM echo buffer; on the way back it passes through the 8-tap FIR, is scaled by feedback (EFB) into the buffer again, and by echo volume (EVOL) into the final mix.

Each pass through the buffer is scaled by the feedback register EFB before being written back — that's what makes the echo repeat and decay. And crucially, on the way out the echo signal runs through an 8-tap FIR filter whose coefficients are the global registers C0C7. Those eight signed taps let the driver shape the echo's tone: a gentle low-pass for a warm hall, or odd taps for a metallic ring. Design the filter below — set the eight taps, the delay and the feedback — and hear the reverb while the tap stems and the filter's frequency response plot update live.

8-tap FIR designer + echoWeb Audio · live
C0
C1
C2
C3
C4
C5
C6
C7
Key takeaways
  • The echo buffer lives in ARAM: ESA sets its start, EDL its length — it competes with sample data.
  • EFB feeds the echo back on itself (decay); EVOL mixes it into the output.
  • An 8-tap FIR (C0–C7) colours the echo return — the SNES's signature tunable reverb.
Module 14 · Part II

Mixing it all & music drivers

GoalSee how the final mix comes together, and how a music driver on the SPC700 turns a song into a stream of register writes.

Follow one sample through to the speaker. Each of the eight voices is scaled by its VxVOL left and right, summed, and multiplied by the master volume MVOLL/R. In parallel, the echo return is scaled by EVOLL/R and added in. The result is clamped to 16 bits and clocked out as the stereo pair, 32 000 times a second. That's the whole output stage — a handful of multiplies and adds, done in hardware.

The whole output stage V0 × VOL L/R V1 × VOL L/R V2 × VOL L/R V3 × VOL L/R V4 × VOL L/R V5 × VOL L/R V6 × VOL L/R V7 × VOL L/R Σ × MVOL L/R + clamp to 16-bit 32 kHz DAC stereo out only voices with their EON bit set echo buffer (ARAM) ESA start · EDL length 8-tap FIR C0…C7 × EVOL L/R × EFB feedback
Two paths to the speaker. Dry path on top: eight voices × VxVOL → Σ → × MVOL. Echo path below: EON-selected voices are written into the ARAM echo buffer, come back through the 8-tap FIR, feed themselves back via EFB, and join the mix through EVOL. The sum is clamped to 16 bits and clocked out at 32 kHz.

But the S-DSP has no idea what a “song” is. It only knows registers. Turning sheet music into register writes is the job of a music driver — a program running on the SPC700 that the game uploaded at boot. Every musical tick it reads a sequence of note events and translates them: load VxSRCN and VxPITCH for the instrument and note, set the volumes, choose an envelope, then write a bit into KON to key the voice on. Timers keep the tempo.

Different studios wrote different drivers. Nintendo's own is often called the N-SPC / Kankichi engine (heard across first-party games); Rare, Konami, Square and others shipped their own, each with its own effects and sequence format. They all boil down to the same loop: read events → write DSP registers → wait for the timer. The lab is a tiny four-voice tracker doing exactly that — toggle steps and each active cell fires a KON write on the beat.

Tiny driver — a 16-step patternWeb Audio · live
stopped
Each lit cell = a note event → a KON write on that step. Edit while it plays.
Key takeaways
  • Final mix = Σ(voice × VxVOL) × MVOL, plus echo × EVOL, clamped to 16-bit, at 32 kHz.
  • A music driver on the SPC700 turns note events into register writes and keys voices with KON.
  • Studios wrote their own drivers (Nintendo's N-SPC and many others) over the same DSP.
Part III

Emulating the chip

To hear SNES music on a modern machine, an emulator has to recreate two synchronised computers cycle by cycle — and then package the result so you can share a song as a tiny file. These last two modules cover the timing problem at the heart of accurate SNES audio emulation, and the SPC file format that lets a fixed 66,048-byte download — barely more than the 64 KB of ARAM it wraps — play a full track.

Modules 15–16Tools bsnes · snes9xLabs 2 interactive
Module 15 · Part III

Emulating the SPC700 + DSP

GoalUnderstand why accurate SNES audio means running two clocks in lock-step, and see the SPC700 execute a driver's register writes by hand.

An emulator that wants SNES music to sound right can't fake the audio chip — it has to run it. That means two problems at once. First, there are two crystals: the main system runs at 21.477 MHz while the S-SMP runs off its own ~24.576 MHz crystal (divided down to the SPC700's ~1.024 MHz). A quick word on the unit hiding in “MHz”: a CPU cycle is a single tick of a chip's clock, the smallest step in which it can do any work, and megahertz just counts millions of those ticks per second. The two clocks here aren't in any tidy ratio, so the emulator must interleave them carefully; let them drift and the mailbox handshake from Module 08 breaks, and games hang waiting for an APU that answered a beat too early or too late.

Second is the CPU↔APU sync problem. Because games poll the mailbox in tight timing loops, an accurate emulator has to switch between emulating the main CPU and the SPC700 the instant either touches a shared port — sometimes cycle by cycle. Get it slightly wrong and you get missing music, stuck notes, or a boot that never completes.

Two clocks, one moment of truth S-CPU · 21.477 MHz emulator runs the CPU ahead… S-SMP · 24.576 MHz …then the APU catches up to the same instant CPU touches $2140 ⇒ sync point tick spacings differ (the clocks share no tidy ratio) · slices may run ahead, but a mailbox access forces both cores to the exact same instant
Interleaved execution. An emulator can't run both chips truly in parallel, so it alternates slices — CPU a while, then APU up to the same point in time. The moment either side touches a mailbox port, the other must be caught up exactly, or the handshake reads a stale byte.

On top of timing sit the fiddly details of the DSP itself: the exact 512-entry Gaussian table, the precise integer maths of the four BRR filters, and edge cases like what a shift value above 12 does or how the very first block behaves. Getting these bit-exact took years of reverse engineering. Much of it crystallised in blargg's SPC_DSP core — a compact, bit-accurate C++ implementation. snes9x uses that core directly, and bsnes' own DSP is derived from the same core and the research behind it — which is why the two agree down to the sample. The lab steps an SPC700 driver snippet as it writes a voice's volumes and keys it on — the fetch/execute cycle an emulator runs millions of times a second.

SPC700 by hand — key on a voiceno audio · step

Reading the listing: in MOV X, #$4C the # means “this literal number” — copy the value $4C itself into register X. Without #, as in MOV $F2, X, the operand is an address: X's value is stored to location $F2. Everything after ; is a comment for humans.

Key takeaways
  • SNES audio accuracy means running two crystals in lock-step (21.477 MHz vs the SMP's ~24.576 MHz → 1.024 MHz).
  • The CPU↔APU mailbox is polled in tight loops, so the emulator must sync the two cores tightly.
  • blargg's SPC_DSP core — used directly by snes9x, and the basis for bsnes' derived DSP — nails the Gaussian table and BRR-decode edge cases.
Module 16 · Part III

SPC files & try it

GoalLearn what an SPC file actually contains, how players resume a song from it, and test everything you've learned.

Here's the elegant payoff of the two-computer design. Because the whole song lives inside the APU — driver, samples and all — you can capture a track by freezing the APU's entire state. That snapshot is the SPC file format, and it's small and rigidly fixed in size: a 256-byte header carrying the SPC700's CPU registers and the ID666 metadata tags (song title, game, composer, length — the same idea as an MP3's ID3 tags), then a full 64 KB dump of ARAM, the 128 bytes of DSP registers, and a few spare bytes: 66 048 bytes, every time. No rendered audio is stored — the ARAM dump does contain the BRR-compressed samples, but the finished waveform the console would output is nowhere in the file. It's the machine itself, paused mid-song.

One .spc file — 66,048 bytes, fixed ARAM dump — 65,536 bytes driver code + DIR table + BRR samples + echo buffer, exactly as frozen header · 256 B magic + SPC700 CPU regs + ID666 tags (≈ MP3's ID3) DSP regs · 128 B the whole $00–$7F map spare/extra RAM · 128 B $00000 $00100 $10100 $10180 256 + 65,536 + 128 + 128 = 66,048 bytes · thin slices widened to stay visible (at true scale the header is 3 px) · some files append an optional extended-ID666 tail
The byte map. An SPC file is the APU's whole world in one flat snapshot: a 256-byte header (CPU registers + ID666 tags), the entire 64 KB of ARAM, the 128 DSP registers, and 128 spare bytes — a fixed 66,048 bytes, whatever the song.

An SPC player is therefore not really a player of audio; it's a mini SNES with only the sound half. It loads the 64 KB into an emulated ARAM, restores the DSP registers and SPC700 state, and simply lets the frozen driver keep running from exactly where it was captured. The music resumes because the driver picks up its own sequence data and carries on writing KONs — the same loop from Module 14, thawed. This is why a 66,048-byte file can play minutes of music: you're shipping the program and its instruments, not the performance.

Want to go further? Grab bsnes or snes9x, load a game you own, and open the audio debugger to watch the eight voices and DSP registers change in real time. Or open an .spc in a player and mute voices one by one — you'll hear the exact eight-voice split from Module 09. Everything in this course is right there on screen.

One last thing: a quick exam. Six questions, each pointing back at the module that answers it.

Final check — six questionsquiz · 0 / 6
Course complete ✦
  • You can read the signal path from a pressure wave — Module 01 — all the way to 32 kHz stereo.
  • You know the SNES stores sound as BRR, plays it on 8 Gaussian-interpolated voices, and shapes it with ADSR/GAIN and an 8-tap echo FIR.
  • You understand why one little Sony computer, frozen into a 64 KB SPC file, can replay a whole song.

An interactive teardown of Super Nintendo audio. Every sound here is generated on the fly with the Web Audio API to illustrate a concept — the BRR codec, envelopes, interpolation and echo are all real algorithms running live in your browser. This page contains no game audio and ships no binary assets. Register names and addresses follow the documented S-DSP map.

Source of truth · S-DSP register map $00–$7F · SPC700 / S-SMP · BRR 9-byte blocks · blargg SPC_DSP (bsnes / snes9x)

Now playing
Nothing playing
Web Audio · synth
no game audio