Hummingtomidi

What MIDI Cannot Capture — Expression, Velocity, and Timing Feel After MP3 Conversion

Converting MP3 to MIDI gives you note pitches and timing — but the format itself drops the nuance that makes a performance feel alive. Here are the hard limits of what MIDI captures, traceable to the conversion code, and what you need to add back by hand.

Short answer: MIDI is a note-event format, not an audio recording. When you convert MP3 to MIDI, the output contains pitch, start time, and duration for each note — and a fixed velocity value that is the same for every note. What MIDI does not capture from your original audio: dynamic variation (how hard or soft each note was played), expressive pitch movement (bends, slides, vibrato), articulation (staccato vs legato), timbre, and the micro-timing that gives a performance its human feel. These are not bugs in the converter — they are structural limits of both the detection method and the MIDI format itself.

This page breaks down each loss, shows exactly where it happens in the conversion pipeline, and explains what you need to do in your DAW to restore expression that MIDI cannot store.

Velocity: every note gets the same hit

In a real performance, a pianist strikes some keys harder than others. A singer pushes a phrase louder, then pulls back. A guitarist digs into a note and lets it decay. This dynamic variation is part of the audio waveform — louder moments have higher amplitude.

The converter on this site does not preserve that variation. In the source code, the buildMidi function assigns the same note-on velocity to every single note:

evs.push({t:Math.round(n.startSec*tps), kind:'on', note:n.midi, vel:90});

The value 90 is hardcoded. Whether the original note was a loud accented downbeat or a soft ghost note, the MIDI file says velocity 90. Note-off events carry velocity 0 — 0x80, e.note & 0x7f, 0 — which is the standard "note released" signal and carries no release-velocity information either.

This means every note in the converted MIDI file has identical loudness when played back through any instrument. The dynamic arc of the original performance — the rises and falls, the accents, the gentle phrases — is gone. To restore it, you need to open the MIDI in your DAW's piano roll and manually draw or edit velocity values per note.

Why velocity is hardcoded

The autocorrelation detector (autoCorrelate) returns a frequency value — one number representing pitch. It does not return an amplitude envelope that could be mapped to per-note velocity. The RMS calculation it performs (threshold of 0.008) is used only to reject silence, not to measure dynamic level. Even if the detector tracked amplitude, mapping audio amplitude to MIDI velocity is not a one-to-one conversion — amplitude in a recording depends on microphone distance, gain staging, instrument volume, and mastering compression, none of which correspond directly to MIDI's 0–127 velocity scale.

Timing: quantized to a fixed grid

MIDI stores timing as integer "ticks" relative to a clock defined by PPQ (pulses per quarter note) and BPM (beats per minute). The converter writes SMF format 0 with PPQ=480 and BPM=120. This means the clock ticks 480 * 120 / 60 = 960 times per second.

Every note's start time and end time are quantized to this grid:

evs.push({t:Math.round(n.startSec*tps), kind:'on', ...})

evs.push({t:Math.round((n.startSec+n.durSec)*tps), kind:'off', ...})

The Math.round call means each event is snapped to the nearest tick. If a note actually started at a time that falls between two ticks, it gets pushed to whichever tick is closer. The original audio's micro-timing — the human push and pull against the beat, the slight rushing of a melody, the laid-back feel of a groove — is flattened onto a uniform grid.

Furthermore, the detection itself introduces timing quantization. The detectNotes function steps through audio in hops of 0.023 * sampleRate samples with a window of 0.046 * sampleRate samples. This means pitch is sampled at discrete intervals, not continuously. A note that starts between two hops will be detected at the next hop position, not at its true onset. The note's reported start time is the hop boundary, not the exact moment the sound began.

Pitch bend and slides: flattened to the nearest semitone

The detector maps each frequency to a MIDI note number using Math.round(69 + 12 * Math.log2(f / 440)). The Math.round call snaps the frequency to the nearest integer MIDI note — the nearest semitone on a piano keyboard.

This means any pitch movement within a semitone is lost:

MIDI does support pitch bend as a continuous controller (Pitch Wheel), but the converter does not write pitch bend events. The output contains only note-on and note-off messages. Any pitch movement that happened inside a note is absent from the file.

Additionally, consecutive detection frames with the same pitch (within ±1 semitone) are merged into a single note object: if(Math.abs(midi-active.midi)<=1){ active.endSample = s+HOP; }. This merge rule means that if a note drifts slightly in pitch without crossing into the next semitone, the drift is invisible in the output. One long note appears, regardless of how much the pitch wavered inside it.

Articulation: staccato and legato are not preserved

MIDI can represent articulation through gaps between notes (staccato = short note with a gap before the next; legato = notes touch or overlap). But the converter's output depends entirely on what the detector found, and the detection pipeline introduces its own artifacts:

Timbre and tone: MIDI has no concept of sound

MIDI is a performance protocol, not an audio format. A MIDI note says "play note C4" — it does not say "play it with a warm cello tone" or "play it with a distorted electric guitar." The instrument sound depends entirely on the synthesizer or sampler that plays back the MIDI file.

When you convert a saxophone solo to MIDI, the output contains the pitch sequence. If you play it back through a piano synth, it sounds like a piano playing those pitches. The timbre of the saxophone — the breathiness, the growl, the reed quality — is not in the MIDI data and cannot be. MIDI stores note events. It does not store audio characteristics.

This is true of all MP3 to MIDI converters, not just this one. The MIDI format itself does not have a field for "this note was played on a Stratocaster with the neck pickup." You assign the instrument after conversion, in your DAW or notation software.

What the MIDI file does contain

After listing everything that is lost, here is what the converted MIDI file does contain — the things you can rely on:

Data Present in MIDI output Source in converter code
Pitch (MIDI note number) Yes — nearest semitone via Math.round(69 + 12*Math.log2(f/440)) autoCorrelate → detectNotes
Note start time Yes — quantized to PPQ=480, BPM=120 grid buildMidi
Note duration Yes — quantized, with minimum 0.05s filter detectNotes + buildMidi
Tempo Single tempo: BPM=120 (Math.round(60000000/120) microseconds per quarter note) buildMidi
Note velocity Fixed: 90 for every note-on, 0 for every note-off buildMidi
Dynamic variation No —
Pitch bend / vibrato No —
Articulation data No (gaps depend on detection, not on original articulation) —
Timbre / instrument sound No (MIDI format limitation) —
Original audio No (MIDI is note events, not audio) —

How to add expression back in your DAW

Since the MIDI file gives you pitch and timing but nothing else, here is what you need to do manually to make the output sound musical:

1. Edit velocity per note

Open the piano roll in your DAW (Ableton, FL Studio, Logic, Cubase, Studio One, Reaper, Bitwig — all support this). Select each note and adjust the velocity value. Listen to your original MP3 alongside the MIDI playback and match the dynamic contour. Accented notes get higher velocity; ghost notes get lower velocity. This is the single biggest improvement you can make — going from uniform velocity 90 to a varied velocity curve transforms the feel of the MIDI.

2. Add pitch bend where needed

If the original performance had slides, bends, or vibrato, draw pitch bend automation in your DAW's piano roll. MIDI Pitch Wheel events let you bend notes up or down continuously. This is how you restore a vocal slide or a guitar bend that the converter flattened to discrete semitone steps.

3. Adjust timing for human feel

The converter quantizes all timing to a grid at BPM=120. If your original audio was at a different tempo, or if the performance pushed and pulled against the beat, you need to adjust note positions manually. Some DAWs have "humanize" features that add slight random timing variation. You can also drag individual notes slightly off the grid to restore groove.

If the original audio was not at 120 BPM, the MIDI file will still play back at 120 BPM — the tempo is hardcoded in the SMF header as Math.round(60000000/120). Change the project tempo in your DAW to match the original recording's tempo before working with the MIDI.

4. Choose the right instrument

The MIDI file does not specify an instrument. Assign one that matches the character of your original recording. If you converted a vocal melody, try a lead synth, a piano, or a wind instrument patch. The right instrument choice can make a simple pitch sequence sound expressive even before you edit velocity and timing. You can also use MIDI to WAV on this site to render the MIDI back to audio with whatever instrument you assign.

5. Trim and clean up

Run through the detected-note list and remove obvious false detections. The autocorrelation method can lock onto harmonics or produce spurious notes in noisy passages. Compare the note list against your original audio — if a note appears where you do not hear one, delete it. If a note is missing where you do hear one, add it manually. The converter's note list is a starting point, not a final result.

Why these limits are not bugs

The missing expression data is not a flaw in the code that could be patched. It is a consequence of two things:

  1. The detection method. Autocorrelation finds one fundamental frequency per analysis window. It returns a single number — the detected pitch. There is no amplitude envelope, no spectral envelope, no harmonic content, and no phase information in the output. The detector answers one question per window: "what is the dominant pitch?" It does not answer "how loud is it," "what is the timbre," or "is the pitch bending."
  2. The MIDI format. Standard MIDI Files store note-on events (pitch, velocity, time) and note-off events (pitch, time). Even if the detector extracted rich expression data from the audio, a basic SMF format 0 file with note-on/note-off events would not carry it. MIDI does support additional controllers — pitch bend, sustain pedal, expression, breath control — but writing those requires analyzing the audio for the corresponding information, which the autocorrelation pipeline does not do.

Tools that promise richer expression data from audio-to-MIDI conversion use different technology — neural networks that analyze spectro-temporal features, amplitude tracking, or models trained to map audio characteristics to MIDI controller data. These are fundamentally different systems from autocorrelation, and they require significant compute. The free, browser-based converter on this site uses autocorrelation because it runs on your device's CPU in real time, without a server, without a login, and without cost.

What to do with the MIDI you get

The converted MIDI file is a skeleton — pitch and timing, nothing else. That skeleton is still useful:

For more on what the converter does and does not detect, read about MP3 to MIDI accuracy and why MIDI cannot hear chords.

Try the MP3 to MIDI converter →