Audio to MIDI Converter

WAV to MIDI: how to prepare the file before you convert

The short answer: four properties of your WAV change the result, and bit depth is not one of them. Sample rate: anything above 22 050 Hz is resampled down to 22 050 Hz, so 44.1 kHz, 48 kHz and 96 kHz files all end up on the same analysis grid — but a file already at or below 22 050 Hz is left alone and gets a different one. Channels: stereo is averaged to mono, which costs a part that exists in only one channel 6.02 dB, or about 11 velocity steps. Level: velocity is computed from absolute RMS in dBFS, not from how loud the note is compared with its neighbours, so an un-normalised file comes back with compressed velocities no matter how it was played. Noise floor: the gate that decides whether a frame counts as a note is placed between the quietest tenth of the file and its loudest frame, so hum, hiss and rumble directly raise the bar for quiet passages.

What happens to the file before a single note is looked for

Everything below is from this converter's own analysis code, not a general description of audio software. When you drop a file in, four things happen in this order:

  1. Your browser decodes the file. Whatever the container held — 16-bit, 24-bit, 32-bit float — comes out as floating-point samples.
  2. All channels are summed and divided by the channel count. A stereo file becomes one mono signal that is the arithmetic mean of left and right.
  3. If the sample rate is above 22 050 Hz, the signal is resampled to exactly 22 050 Hz by linear interpolation. If it is at or below 22 050 Hz, nothing is touched.
  4. The signal is read in 2048-sample windows, Hann-weighted, stepped forward 256 samples at a time.

Step 3 is the one that surprises people, because it is conditional. It resamples down but never up.

Sample rate: the setting that decides the analysis grid

Two numbers fall straight out of the window size and the sample rate: the width of one frequency bin, and how long one frame lasts. Change the sample rate and both change.

What this converter actually uses, per input sample rate. Rates above 22 050 Hz are all resampled to 22 050 Hz; rates at or below it are used as-is.
Your WAVAnalysed atBin widthFrame lengthFrames/secNyquist
8 000 Hz8 000 Hz3.9063 Hz32.000 ms31.254 000 Hz
11 025 Hz11 025 Hz5.3833 Hz23.220 ms43.075 512.5 Hz
16 000 Hz16 000 Hz7.8125 Hz16.000 ms62.508 000 Hz
22 050 Hz22 050 Hz10.7666 Hz11.610 ms86.1311 025 Hz
32 000 Hz22 050 Hz10.7666 Hz11.610 ms86.1311 025 Hz
44 100 Hz22 050 Hz10.7666 Hz11.610 ms86.1311 025 Hz
48 000 Hz22 050 Hz10.7666 Hz11.610 ms86.1311 025 Hz
96 000 Hz22 050 Hz10.7666 Hz11.610 ms86.1311 025 Hz

The practical consequence: there is no accuracy gain from exporting a 96 kHz WAV instead of a 44.1 kHz one. Both are resampled to the same rate and read with the same 10.7666 Hz bins. There is also no gain from converting at 22 050 Hz yourself, because that is what happens anyway.

There is a difference if you go below 22 050 Hz, because then no resampling happens and you get a genuinely different grid. A 16 kHz file gives finer frequency resolution — 7.8125 Hz bins instead of 10.7666 Hz — but coarser time resolution, 16.000 ms per frame instead of 11.610 ms, and a Nyquist limit of 8 kHz. Whether that trade helps depends on the material, and we have not measured it across a corpus, so treat it as something to test on your own file rather than a recommendation.

How the downsampling is done, and where it is crude

The resampler is a linear interpolation between two neighbouring input samples. There is no anti-aliasing filter in front of it. Two details are worth knowing:

Missing anti-alias filtering means content above the new Nyquist limit of 11 025 Hz can fold back into the analysed band. In practice this rarely changes a result, because detection is band-limited: single-line mode searches 55 Hz to 1 800 Hz, and polyphonic peak detection stops at 4 000 Hz. Content would have to be loud, above 11 kHz, and fold down into those bands to matter — hi-hats and cymbals sit up there, which is one more reason to convert a clean instrumental take rather than a full mix.

Channels: the file is averaged to mono, and that has a price

The analysis sums every channel and divides by the number of channels. There is no weighting and no mid/side handling. If a part is panned hard to one side and the other channel is silent, the average is half the original amplitude: −6.02 dB.

That number matters because of how velocity is computed. This converter maps the RMS level of a note's frames to velocity as vel = round(20 + (dB + 60) × (100 / 54)), clamped to 1–127. One decibel is worth 1.852 velocity steps, so 6.02 dB is worth 11.1 velocity steps. A hard-panned part loses roughly eleven points of velocity purely through the channel average.

What to do about it: if the source is a single instrument, export mono. If it is a stereo mix and the part you want is off to one side, the average is unavoidable here — there is no stem separation — so expect that part to come back quieter in velocity than it sounds.

Level: velocity is absolute, so normalise before you convert

This is the most common cause of "the velocities all look the same". The mapping above reads the note's RMS in dBFS — decibels relative to full scale — not its level relative to the rest of the file. Loudness in the room does not enter into it; the numbers in the file do.

Velocity this converter writes for a given note RMS, from the mapping vel = round(20 + (dB + 60) × (100 / 54)).
Note RMSVelocityNote RMSVelocity
0 dBFS127−18 dBFS98
−3.01 dBFS126−24 dBFS87
−6 dBFS120−30 dBFS76
−10 dBFS113−40 dBFS57
−12 dBFS109−60 dBFS20

Two readings from that table are worth internalising. Velocity tops out at 127 for anything at or above −2.22 dBFS RMS, and bottoms out at 1 for anything at or below about −70.26 dBFS RMS. A sine wave's RMS sits 3.01 dB under its peak, so a sine peaking at full scale reads −3.01 dBFS and returns velocity 126 — reaching a full 127 essentially requires clipping.

So: normalise the file before you convert. A WAV that peaks around −1 dBFS will spread its notes across most of the velocity range; one that peaks at −18 dBFS will compress everything into the 90s and below, and no amount of moving the sensitivity slider will fix that, because sensitivity does not touch velocity.

One caveat on RMS: it is measured across the whole signal in the window, not just the pitch being tracked. A rumbling low end, a fan, or a loud accompaniment in the same file raises the RMS of every frame it overlaps, and therefore inflates the velocity of notes that are themselves quiet. Cleaning the file helps velocity as much as it helps detection.

Bit depth: it genuinely does not matter here

Given the floor above, this is short. Velocity reaches its minimum at about −70.26 dBFS RMS, and 16-bit audio carries roughly 96 dB of range below full scale — about 26 dB more than the mapping can use. Exporting 24-bit instead of 16-bit cannot change a single velocity value on this chain, and it cannot change a note either, since the FFT works on data that has already been decoded to floating point. Save the disk space.

Noise floor: the gate is set from your file, not from a constant

Before any note exists, the converter sorts every frame's RMS level, takes the value at the 10th percentile as a floor, and sets a threshold partway between that floor and the loudest frame in the file:

gate = floor + (loudest − floor) × (0.32 − 0.30 × sensitivity)

At the default sensitivity of 60 that is 0.86 × floor + 0.14 × loudest: the threshold sits 14% of the way up from the quiet tenth of the file to its loudest frame. Two consequences follow, and both are about preparation:

  1. A single loud transient raises the bar for everything else. The loudest frame sets the top of the range. A door slam, a click, or a drum hit at the start of the take pushes the threshold up, and quiet notes that would otherwise have passed fall below it. Trim or fade those out.
  2. Constant background noise lifts the floor. Hiss, hum, air conditioning and DC offset add energy to every frame, so both the floor and the threshold rise with them. High-pass filtering and DC removal before conversion is not cosmetic here — it moves the threshold down.

Note the side effect of aggressive silence trimming: the bottom tenth of the file becomes quiet-but-real material instead of digital silence, which raises the floor and therefore the threshold slightly. Trim obvious noise, but re-check your result after doing it.

Timing: your settings are rounded to whole frames

At 22 050 Hz one frame is 11.610 ms, and both timing controls are converted to an integer number of frames before they are applied:

So a passage played with gaps shorter than about 81 ms between repeated pitches will come back as one long note, and anything shorter than about 58 ms will not come back at all. If your material is very staccato, lower the shortest-note value before you conclude the conversion is wrong — and if it is very legato with tiny breathing gaps, expect notes to run together.

The two edges of the file

Loudness is measured on the raw samples, but the spectrum is measured through a Hann window whose weight is 0 at its outermost sample and 0.147 by 256 samples in. The first frame covers file samples 0–2047, so a note that begins at exactly 0.000 s is analysed at almost no weight. If your take starts on the downbeat with no lead-in, adding a short silent lead-in gives the detector a full window for that first note.

The other edge is length. If the whole file is shorter than 2048 samples — 92.88 ms at 22 050 Hz — it is zero-padded up to one window. Very short test files still convert, but they produce one frame's worth of evidence.

Preparation checklist

  1. Export lossless. WAV, FLAC or AIFF. If the source is already lossy, do not re-encode it on the way out.
  2. Sample rate 22 050 Hz or higher. Anything above that is resampled to it anyway. Do not bother with 96 kHz for conversion, and do not drop below 22 050 Hz without testing.
  3. Mono for a single part. Stereo is averaged, at a cost of 6.02 dB — about 11 velocity steps — to anything present in only one channel.
  4. Normalise so peaks land near −1 dBFS. Velocity is absolute; this is the step that decides whether your velocities use their range.
  5. High-pass and remove DC. Both lower the frame floor, and the gate is placed relative to that floor.
  6. Cut clicks and bangs. One loud transient raises the gate for the whole file.
  7. Leave a short lead-in if the first note starts at 0.000 s.
  8. Check shortest-note and separation against your playing style, remembering they land on 58.05 ms and 81.27 ms at the defaults.

How to check any of this on your own file

None of the above needs to be taken on trust, and you should not trust published accuracy numbers you cannot reproduce. Convert the file, download the .csv alongside the MIDI, and read it. The columns are index,midi_note,note_name,start_sec,end_sec,duration_sec,velocity.

Questions

Should I convert my 96 kHz master down to 44.1 kHz first?

It makes no difference to the result. Both are resampled to 22 050 Hz on arrival, and from that point the analysis is identical: 10.7666 Hz bins, 11.610 ms frames.

Is 24-bit better than 16-bit for this?

No. Velocity bottoms out around −70.26 dBFS RMS, and 16-bit audio already carries about 96 dB of range. The decoded samples are floating point before any analysis happens either way.

Why are all my velocities around 90?

Because velocity is computed from absolute RMS in dBFS. Around −21 dBFS RMS maps to velocity 98. Normalise the file so peaks sit near −1 dBFS and the spread returns.

Does normalising change which notes are detected?

It should not, and that is worth verifying rather than assuming: the note gate is placed relative to levels inside the file, so scaling the whole file scales the floor and the loudest frame together. Export both versions and diff the note_name columns to confirm it on your material.

My stereo mix converts worse than the mono bounce. Why?

The channels are averaged before analysis. Anything panned to one side loses 6.02 dB, and any stereo widening or polarity difference between channels changes what the average looks like. A mono bounce removes that step entirely.

Does trimming silence help?

Partly. It removes frames that contribute nothing, but it also changes which frames make up the quietest tenth of the file, and the gate is anchored to that. Trim obvious noise and clicks, then re-check the piano roll rather than assuming the edit helped.

Convert a WAV file now — runs in your browser, nothing is uploaded.