When I still had my digital piano, I used it as a MIDI keyboard, plugged into my laptop which was running Pianoteq, a software instrument that physically models (among other things) pianos. Physical modeling means simulating the mechanics and acoustics of an instrument, as opposed to just playing pre-recorded samples. Besides saving a lot of disk space, this can make for a much more flexible and expressive digital instrument.

Getting curious about how it works, I recently reverse-engineered the Pianoteq binary (using Claude Code and GhidraMCP) to see how the magic is done, and especially how it’s done at more than 30× real-time speed even with the highest quality settings.

This sent me down a deep rabbit hole about the broad subject of digital piano synthesis. Writing this blog series is my way to crawl back out of that hole, sharpen my understanding further along the way, hone my explanation and writing skills, and then finally be done with this. I have other rabbit holes to jump into!

So, in this series of 5 blog posts, we will build a simple, physically motivated piano from scratch and implement it in Rust.

Here are the goals (and non-goals) of this project:

  • An understandable presentation
    • Listening examples allow you to hear the things I am writing about.
    • Interactive diagrams help understand the important concepts in a more intuitive way.
    • Explanations always use a grand piano.
    • I will define relevant music-theory and physics terms as they come up.
  • A realistic but relatively simple model
    • It should sound recognizably like a real piano, but a well-trained ear can probably still tell it is a model.
    • Details that add a lot of complexity for only a tiny audible difference are not the focus.
  • A simple implementation
    • No GUI, just a command-line interface for rendering MIDI files to WAV.
    • No serious speed optimizations. If it runs in real time on a modern-ish CPU, that is enough. Turns out that is a pretty low bar nowadays.
    • When explaining, I will focus on the modeling, not on implementation details. The code should be readable and well-structured, but it is not a goal to make it a Rust masterpiece or to use every clever abstraction I can think of.

In the end, we will transpile our Rust code to WebAssembly and make it run in-browser too, so we can get our hands on it without compiling anything.

That is way down the line, though. First, this blogpost gets us started by understanding the instrument and the main synthesis approaches there are.

How a piano works

If you play the piano already, feel free to skip or skim this section :)

Where does the sound come from?

Here’s a look inside a grand piano, and how its beautiful sound actually comes to be.

When you press a key,

  1. the damper lifts, allowing a string to vibrate freely. Just in time for the next step:
  2. the hammer strikes the string and then falls back down to let the string actually vibrate. The string vibrating alone would be just a soft sound, though.
  3. one end of the string is supported on a bridge, which is attached to the piano’s soundboard, a piece of wood that vibrates and thus radiates sound into the air.
  4. As long as you hold the key down (or keep the sustain pedal pressed, see explanation below), the damper stays lifted and the string can keep vibrating. Vibrating strings gradually lose energy. Eventually, when you have released both the key and the pedal, the damper falls back and stops that string from vibrating.

And that’s basically it! We will get into some details in a bit, but a piano is just a hammer hitting a string, which transmits its vibration and force to a soundboard which then in turn actually produces most of the sound we hear.

The diagram above gleefully omits all the complexity of what happens between you pressing the key and the hammer hitting the string, the so-called action of the piano. Its ingenious design enables, among other things, the playing of fast repeated notes. While the details here are not too important for us, for the curious, they are explained well in this stellar video.

The importance of the soundboard

If you took a piano string by itself, suspended in air, and somehow hit it, it would be much quieter and much less “piano-like” than a real piano note.

In a piano, the string stores vibrational energy, and transfers it over the bridge to the soundboard, which is what really helps turn that vibration into audible sound. So the exciter (hammer) and the radiator (soundboard and body of the piano) are different parts! This is actually common in acoustic instruments: guitars and violins are obvious other examples. A counter-example would be a cymbal, triangle, or xylophone. But back to the piano!

The design of the bridge makes sure that the energy does not leave the string too easily, else the note would fade too fast. On the other hand, if the bridge were too stiff, the string would not be able to transfer enough energy to the soundboard, and our piano would be too quiet.

You may think that a single string suspended in air not being loud enough in the real world doesn’t really matter for our digital synthesis, since we can just turn up the volume in software. But the soundboard is not a one-way street; in reality, it also transfers energy between strings, as we will see in a later section of this blogpost. For now, let’s take a look at our feet.

The pedals and how they affect the sound

A grand piano has two or three pedals, and here is what they do:

  • Right pedal / Damper pedal / Sustain pedal

    • Lifts all dampers, allowing all strings to vibrate freely until the pedal is released, and thus sustains the notes.
    • This also creates a much richer, more resonant sound, as all the strings can now interact with each other via the soundboard.
  • Left pedal / Una Corda

    • Shifts the whole keyboard action a bit, so that the hammers only strike some of the strings per key.
    • The strings are also hit by a softer part of the hammer felt (see the section on hammers at the very end)
    • In an upright piano, it just moves the hammers closer to the strings, which also makes for a softer attack.
    • Either way, this makes the sound softer and more “intimate”.

The third (center) pedal is not too important for us. Open the spoiler if you’re curious, but you’re fine reading on.

Center pedal / Sostenuto / 'Selective sustain' pedal
  • This one is not found on all pianos, i.e. upright pianos often do not have it (or their center pedal does something else entirely, like only sustaining bass notes).
  • It only sustains the notes that are currently being held down when the pedal is pressed.
  • Notes played after that are not sustained by it.
  • This allows for selective sustain, which can be used for more complex voicings, because the notes played after the pedal goes down are still short and staccato.



The details of piano sound!

.. you might want to put on some headphones for this!

Up to now, we have looked at the piano mostly as a machine: key, damper, hammer, string, bridge, soundboard. That is already enough to understand where the sound comes from. Now for a different question:

What are the audible clues that tell our ear “this is a piano”?

Let’s first get our hands on some tools to visualize audio

Our tools: waveform, spectrum, and the spectrogram

We’ve already seen some audio visualizations, but let’s understand better what they show, taking a single C3 piano note as an example.

First, a waveform shows how the air pressure changes over time. Note though that due to psychoacoustic nuances, this doesn’t map perfectly to perceived loudness (which for example also depends on the frequency), but it’s a useful proxy for what is plotted.

Waveform: air pressure over time

Analysis loads when this example scrolls near view.

Second, a spectrum shows which frequencies are present at one particular moment:

Spectrum: The frequency balance at a particular point in time, here 0.1s after the attack

Analysis loads when this example scrolls near view.

Finally, a spectrogram nicely combines both ideas: time goes left to right, frequency goes bottom to top, and brightness or color shows how much energy (~loudness) is present at each frequency. This one uses a logarithmic frequency axis from 120 Hz to 8 kHz, so the useful piano partials get more visual space.

Spectrogram: The frequency balance over time

Analysis loads when this example scrolls near view.

For pianos, spectrograms are especially useful, as we’ll see soon when we use our shiny new tools!

It’s actually up to three strings per note

I explained things until now as if every note has just one string. In reality, for many of the notes, a grand piano uses not one string but two or three strings right next to each other (more strings for the upper keys, fewer for bass notes). For keys with multiple strings, even when they are tuned extremely close, they do not vibrate in exactly the same way, because hammer contact and support conditions differ ever so slightly between them. And skilled piano tuners actually adjust the tensions of the strings carefully to deliberately push for a certain tone color (also called the timbre). But how does this affect the sound?

First, this creates beating: a slow pulsation heard during the decay, caused when two almost-equal frequencies alternately reinforce and partially cancel each other out. Let’s listen to an example: In the left audio below, all three strings are tuned to the exact same tension/frequency. In the right example, the outer two are tuned slightly above and slightly below it. If you listen closely, or look really hard at the plots, you can hear or see this pulsation:

Three strings, no detune
all at 130.81 Hz

Analysis loads when this example scrolls near view.

Three strings, slight detune
one at 130.81 Hz, and two slightly detuned strings

Analysis loads when this example scrolls near view.

You might have noticed that the left example also features some beating, although less pronounced. I used Pianoteq to generate these audio clips and have only turned off the string tuning differences, but the different hammer contact and string support conditions are still simulated, and thus the strings still don’t vibrate in the exact same frequency pattern.

There is a second effect, also visible from the waveforms above: multiple strings create a two-stage decay. Decay just means how a note fades after the attack, which in turn means the very beginning of the sound. Two factors play into this:

  • Remember that in a real piano, the strings are also coupled through the bridge and soundboard. When the hammer strikes, the strings start in phase, pushing the bridge hard and draining energy quickly: the loudness initially drops fast. But because of those slight tuning differences, they quickly drift out of phase. They start fighting each other at the bridge, thus moving it less, which results in a much slower and smoother energy drain for the tail end of the note, making it also ring longer.
  • Another main reason for the two-stage decay is called string polarization, where a short while after being hit (and first vibrating up-and-down, i.e. vertically, to the bridge), the vibrating string’s motion rotates slightly into a horizontal plane (hello physics), and since the bridge is much stiffer there, it absorbs less energy, so the vibration energy is lost more slowly for this reason, too, not just the differently tuned strings fighting each other at the bridge. String polarization is why the left example still features relatively prominent decay at the start, even though the strings are tuned the same.

So even before we talk about strings of different keys resonating with each other, each single key is already richer than a one-string-per-key model would suggest.

A piano note is more than just one frequency

When you strike a piano key, you do not get just one clean frequency.

The main pitch is mostly set by the string: its length, tension, and mass. Shorter, tighter, lighter strings vibrate faster, which gives higher notes. Longer, looser, heavier strings vibrate slower, which gives lower notes.

But a string fixed at both ends cannot vibrate in just any shape. The shapes that keep reinforcing themselves are the ones that fit neatly between the ends of the string: one big wave, two half-length waves, three third-length waves, and so on. These are called the string’s modes. You can think of a mode as one of the string’s natural ways of vibrating.

fundamentalone big shape
first overtonetwo shapes, 2× as fast
second overtonethree shapes, 3× as fast
all togetherevery mode at once
Every mode adds together into the wiggling shape on the right.

The lowest mode is called the fundamental. It is the frequency our ear usually hears as the pitch of the note.

The higher components are called overtones. The fundamental plus the overtones taken together are called partials.

In an ideal mathematical string, the partials continue forever. In a real piano, the very high partials quickly become weak, and eventually they are too quiet, and/or too high for our ears. For synthesis, we only need the partials that make an audible difference.

Musically, doubling a frequency gives the same note name one octave higher. So if a C3 string vibrates at about 131 Hz, a component at 2× that frequency is another C one octave above it. The 3× component is near a G. The 4× component is another C. The 5× component is near an E.

Partials that sit at exact integer multiples of the fundamental (2×, 3×, 4×, and so on) are called harmonics.

But piano partials are not exactly harmonic.


Inharmonicity: Stiff strings stretch the partials

An ideal mathematical string has partials at exact integer multiples of the fundamental, as we have seen above.

However, a real piano string is stiff. Because of that stiffness, the upper partials are slightly stretched upward. The intuition is this: stiffness acts as a second restoring force alongside tension. Higher overtones have shorter wavelengths, which forces the string to bend more sharply. More bending means more stiffness resistance, which raises the restoring force and therefore pulls the string back faster, so they oscillate at slightly higher frequencies than the ideal-string formula would predict.

Overtone ladder for a low C, in ideal harmonic mode.C2C3C4C5× 1C2fundamental× 2C3octave× 3G3octave + fifth× 4C4two octaves× 5E4two octaves + major third× 6G4two octaves + fifth× 7≈ B♭4harmonic seventh× 8C5three octaves
In the ideal case, the partials line up at exact integer multiples of the fundamental, landing on familiar musical intervals.

As you can see, these partials are still close to the harmonic series, but not perfectly on it. This inharmonicity can be calculated with an easy formula where fnf_n is the frequency of the nn-th partial, f0f_0 is the ideal fundamental pitch reference, and BB is the inharmonicity coefficient of the string:

fn=nf01+Bn2f_n = n f_0 \sqrt{1 + B n^2}

For a grand piano key somewhere in the middle of the register, that coefficient might be something like 0.00050.0005. It is related to the string’s stiffness, length, tension, density, and diameter. It will usually be lower for the longer strings (lower keys), and higher for the short strings (higher keys). That also means uprights generally have more of it, since their strings are overall shorter than those in a grand. But in any case, it’s a small number.

If you then plug in the other numbers, you can see that the frequencies of the first few partials are very very close to being harmonic, but of course not quite. Since the stretching gets more extreme as you go up the partials (n2n^2 in the formula), by the time you reach the 15th partial, those frequencies can be sharp by almost an entire semitone compared to a pure harmonic series! This is especially noticeable in low notes, because they have many audible high-numbered partials (which stretch up most). That is part of what gives them their characteristic metallic “bite”. Side note: the per-partial stretching is actually largest in the treble notes, not in the bass, since they have highest value BB.

Let’s hear for ourselves what missing inharmonicity sounds like:

Single sine
Only the C3 fundamental

Analysis loads when this example scrolls near view.

Harmonic stack
Exact integer partials

Analysis loads when this example scrolls near view.

Inharmonic partial stack
Upper partials stretched upward

Analysis loads when this example scrolls near view.

The sine wave sounds pure but not piano-like at all. The harmonic stack is richer, but still too clean. The inharmonic version has a slightly more metallic, piano-like fingerprint.

It is still not a piano note, though. We are missing how the sound changes over time.


Why a piano note changes color as it fades

If you listen carefully to a single note (wearing your headphones yet?), you can hear a change in tone color as it decays. Tone color just means the balance (relative loudness) of the partials. Let’s have a closer look at the spectrogram I showed above:

Spectrogram: C3 piano note

Analysis loads when this example scrolls near view.

A few things are visible:

  • The beginning is bright: the upper partials are strong.
  • It is also rich: many partials are audible at once.
  • The upper partials fade first.

So higher overtones lose their energy faster than lower ones, and thus the spectral balance changes continuously while the note decays. This shifting color is one of the easiest ways for a fake piano to reveal itself. Many weak piano synths get the start of the note somewhat right, but then the sound just sits there and the balance of partials does not evolve in a realistic manner. The end of the note should sound warmer, smoother, and simpler.

Thankfully for us, Pianoteq is so versatile that it allows me to specify the decay-of-partials settings easily, so here is the same MIDI played again, but this time I made all partials decay equally fast:

Static spectrum
All partials fade together / upper partials do not decay faster

Analysis loads when this example scrolls near view.

To hear the difference clearly, seek to the end of the spectrogram by clicking.

I’m sure you agree the first example sounds more piano-like. For our synthesis, this means one loudness curve (also called an envelope) for the whole note is not enough. We will need several envelopes, so that different partials can fade at different speeds.


Sympathetic resonance: when one note wakes up others

When you strike a piano note, the vibrations of the string, including its higher partials, travel through the bridge and soundboard into the rest of the instrument, including other strings. If some of those other strings are free to vibrate — e.g. because their dampers are lifted — they can absorb some of that energy and start ringing too. That is called sympathetic resonance, and it’s another reason a cheap digital keyboard might sound off if it treats the notes as isolated events, instead of modeling how they live inside one shared resonant body.

Ghost chord demonstration 👻

Suppose we carefully press the keys of a C-major chord such that the hammers do not strike, but the dampers do lift off. Those strings are now free to vibrate.

Now we play a loud low C. That low C contains strong overtones, including frequencies close to C, E, and G above it, exactly the strings we have lifted the dampers for. Those undamped strings now pick up that energy and start vibrating. As a result, you hear a faint “ghost” C-major chord ring out, even though no hammer ever struck it.

Listen to the example below, where I first play the chord normally, so you know what to listen for, then the chord keys are lifted (so we get silence) and pressed back down carefully such that only the dampers lift, but no string is hit. Finally, the low trigger note is struck shortly (but hard, for better effect), making the undamped chord strings receive energy and start to ring out, too:

Ghost chord in C major
A low trigger note excites an undamped C-major chord above it

Analysis loads when this example scrolls near view.

This ties together several ideas from earlier: one note contains many partials, the piano is a coupled mechanical system, and the dampers decide which strings are allowed to join in on the vibration fun.

A convincing piano synthesis model will need at least some form of this shared-body behavior.


Hammer time!

Finally, let’s look at the hammer.

A piano hammer is covered in felt. Felt is soft, but not equally soft in every situation. What matters is how hard and fast the hammer hits the string.

At low playing levels, meaning you press the key gently and the hammer moves more slowly, the felt stays relatively soft. It touches the string for a little longer. A longer contact gently pushes the string and tends to produce a rounder, darker sound.

At high playing levels, meaning you press the key harder and the hammer hits faster, the felt compresses more. Compressed felt resists more strongly, so the hammer-string contact becomes effectively stiffer. The contact time becomes shorter. A shorter, sharper hit puts more energy into higher partials, making the note brighter (of course), but also feel more percussive.

To showcase this, let’s hear some audio examples where I have hit the same notes at three dynamic levels: piano, mezzo, and forte. I then normalized the output audio volumes so we can ignore the difference in volume and listen only for the difference in tone color:

Playing piano

Analysis loads when this example scrolls near view.

Playing mezzo

Analysis loads when this example scrolls near view.

Playing forte

Analysis loads when this example scrolls near view.

That is why a loud piano note is not just a quiet piano note with the volume turned up. For the synthesis, this means MIDI velocity should not control only the volume, but it must also change the tone color.

A last fun fact I will leave you with: the position where the hammer strikes the string matters a lot, since striking it at a specific spot suppresses that specific harmonic (and its multiples). And because some upper harmonics, especially the 7th, can sound harsh or dissonant, the hammer of a real piano is made to strike the string at roughly 1/7th of its total length, further shaping the piano’s characteristic tone.


Series roadmap from here

We now learned all the major things that make a piano sound like a piano. Here is what will happen next:

Part 2 — Synthesis approaches and digital waveguides

We will:

  • compare the main synthesis methods there are
  • learn about digital waveguides and why they are such a natural fit for strings
  • nail down which parts of the real piano we will model explicitly, and where we will simplify things
  • get a code repo off the ground

Part 3 — One believable note

We will build the first real note model:

  • a hammer-like excitation
  • stiff-string behavior
  • changing spectral balance over time
  • a first waveguide string

Part 4 — One believable piano key

We will move from one string to a more piano-like key:

  • multiple strings
  • slight detuning
  • richer decay behavior
  • a body resonator

Part 5 — One believable instrument

We will add whole-instrument effects:

  • dampers
  • sustain pedal
  • sympathetic resonance
  • a bit of final acoustic-space polish, such as reverb

See you there!




Further reading

For this post, the most useful sources I used were:

  • Neville H. Fletcher and Thomas D. Rossing, The Physics of Musical Instruments
    Especially the piano sections on strings, hammers, soundboard, coupling, tuning, and timbre.

  • Perry Cook, Real Sound Synthesis for Interactive Applications
    A very readable bridge from acoustics to synthesis.

  • Julius O. Smith, Physical Audio Signal Processing
    Especially the chapters on piano synthesis, digital waveguide models, force-pulse synthesis, and coupled piano strings.
    https://ccrma.stanford.edu/~jos/pasp/

  • Julius O. Smith, “Virtual Acoustic Musical Instruments: Review and Update”
    A compact overview of physical modeling and virtual acoustic instruments.

  • Anders Askenfelt, editor, Five Lectures on the Acoustics of the Piano
    Especially the lectures on piano touch, hammer-string interaction, and coupled strings.
    https://www.speech.kth.se/music/5_lectures/

  • Yamaha, “The Sound-Producing Mechanism” and “What is a Piano’s Action?”
    Useful approachable diagrams and explanations of the grand piano mechanism.