Six ways a conversion can fail or come back empty, the exact wording the page uses for each, and what is still loaded afterwards. The messages are the easy part.
Short answer: a failed conversion does not clear anything. I converted an 8-note file, then selected an 85 MiB file and had it turned away - and the page then converted the old file again and handed back the old .mid, byte for byte, while the file input was holding the rejected one. A file the browser cannot decode behaves the same way: the message goes red and the result card hides, but the previous note list and .mid are still sitting there to download. Clear is the only control that drops them. And when a conversion succeeds but finds zero notes, Download still writes a 33-byte .mid file, while Copy note list does nothing at all and says nothing about it.
Everything below was measured on this page's own converter while it ran in a real browser: real files pushed into the file input, the real buttons clicked, and the page's own status text, buttons, result card and output files read back afterwards. Nothing here is inferred from the way the code looks.
The status line under the buttons has three visual states - neutral grey, green for success, and red for a problem. These are the messages, quoted exactly as the page renders them. Where the page breaks a message across lines, I have kept its line breaks.
| What happened | What the page says | Colour |
|---|---|---|
| File is over the size limit | That file is 85.0 MB. This page turns files away above 80 MB, because the browser has to
hold the whole decoded track in memory. |
red |
| The browser refuses to decode the file | Could not decode this file.Your browser refused it, which usually means the format is not one it can decode (WMA is a
common case).Detail: Unable to decode audio data |
red |
| It decoded, but no steady pitch was found | Decoded 2.0 s of audio, but no steady pitch was found.This detector tracks one pitch at a time, so dense mixes, chords and percussion usually
come back empty. Try a clearer single-line recording, or lower the sensitivity. |
red |
| Copy note list, but the browser refused the clipboard | Copy failed - your browser blocked clipboard access. |
red |
| The page cannot reach the microphone API at all | This browser does not expose microphone recording to the page. |
red |
| A file was read from disk and is waiting | Ready: ok.wav. Press Convert to MIDI. |
grey |
| Clear was pressed | Cleared. Choose a file to begin. |
grey |
| A conversion finished with notes in it | Converted 8 note(s) from 4.0 s of audio in 0.1 s.Range C4 - C5. Download the .mid below. |
green |
Two things are worth noticing in that list. The first is that "Ready" is grey, not green
- it is not a promise that the file will convert, and the next section shows why. The second is that
the last line of the decode message is not written by the page. The page writes
Detail: and then prints whatever error the browser's decoder produced. In Chrome 153 that
string is Unable to decode audio data; a different browser will word it differently.
This is the part that is worth knowing before you go looking for a bug. The page keeps four separate pieces of state: the file's bytes, the detected notes, the .mid it built, and what is drawn on screen. A failure only touches the last of those.
I ran one file through the whole sequence - success, then a rejected file, then an undecodable file, then a different file with no conversion, then a conversion that found nothing, then Clear - and read the page's state after each step. The note list and the .mid are the same objects throughout:
| Step | Status | Result card | Notes | Download gives | Copy gives |
|---|---|---|---|---|---|
| Converted an 8-note file | green | shown | 8 | 105 bytes | 9 lines |
| Then selected an 85 MiB file (rejected) | red | shown | 8 | 105 bytes, identical | identical to above |
| Then selected a file the browser cannot decode | red | hidden | 8 | 105 bytes, identical | 9 lines |
| Then selected a silent file, without converting | grey | hidden | 8 | 105 bytes, identical | 9 lines |
| Then converted that silent file (0 notes) | red | shown | 0 | 33 bytes | nothing |
| Then pressed Clear | grey | hidden | 0 | no file at all | nothing |
Read the second and third rows again. After the 85 MiB file was turned away, the .mid that Download produced was byte-for-byte identical to the one from the run before it, and the copied note list was character-for-character identical. After the undecodable file failed, the same was still true - the result card had been hidden, but the outputs behind it had not moved. And after selecting a completely different file, they still had not moved.
The "Notes" column is the giveaway. Even in the rows where the result card is hidden, the numbers inside it are still the previous run's numbers; hiding the card does not rewrite them.
The practical consequence, measured. I converted a file called ok.wav and downloaded
ok.mid, 105 bytes. Then I selected a different file, silence.wav, without
converting it, and pressed Download again: I got a 105-byte file called
silence.mid - the previous conversion's notes, carrying the new file's name.
After notaudio.wav failed to decode, the download was called
notaudio.mid and still held those same 105 bytes. The file name comes from
whatever you selected last; the contents come from the last conversion that succeeded. Check the
note count in the status line before you trust a download.
Selecting an oversized file is the same gesture every time, but what is left behind depends entirely on what was on the page before it. I ran it both ways.
| Nothing loaded before | A finished result on screen | |
|---|---|---|
| Status message | identical - the red "turns files away above 80 MB" line | |
| Convert button | disabled | still enabled |
| Result card | hidden | still showing the old result |
| File info line | No file chosen yet. |
still ok.wav - 125.0 KB |
In the second column the rejection message is the only thing that changed. The file input was
holding oversize.wav, 89,128,960 bytes of it, while the line underneath it still read
ok.wav - 125.0 KB. So I pressed Convert again, and the page reported
Converted 8 note(s) from 4.0 s of audio in 0.1 s - it had re-run the old file. Download
gave 105 bytes, byte-identical to before.
Nothing is broken here in the sense of lost work: you did not lose your previous conversion, which is the friendlier of the two possible behaviours. But the page is now showing you two different answers to "which file am I working on" at the same time, and the one that matters - the one Convert will use - is the one that is not named in the file info line. If you want to be sure you are starting clean, press Clear.
The size limit itself is a byte count, not a duration, and what it means in minutes depends entirely on your format - the same 80 MiB is 7.9 minutes of stereo WAV and about 1.5 hours of 128 kbps MP3.
The page does not validate the format when you choose a file. It checks the size, reads the bytes with
FileReader, and reports ready. I took a 312-byte ASCII text file, renamed it to
notaudio.wav, and loaded it:
file info line : notaudio.wav - 0.3 KB
status : Ready: notaudio.wav. Press Convert to MIDI.
Convert button : enabled
Then I pressed Convert and got the red decode message with
Detail: Unable to decode audio data. Pressing Convert again produced the identical message,
so this is not a transient failure that a retry will fix - the file is simply not audio the browser can
read. The format check is the browser's decoder, and it runs at conversion time, not at selection time.
This is also why the page cannot give you a list of supported formats in advance. It has no list of its own; the list is whatever your browser happens to decode, which is why WAV, MP3, OGG, M4A, FLAC and WebM or Opus work in current browsers while WMA generally does not.
Running out of notes is not treated as a failure - the result card opens anyway. I converted a 2-second file of pure silence:
| Readout | Value |
|---|---|
| Notes found | 0 |
| Duration | 2.0 s |
| Pitch range | - |
| Analysis time | 0.0 s |
| Piano roll | blank white, 0 of 135,000 pixels drawn on |
Now the two output buttons, pressed in that same state.
Download .mid still writes a file. It came out at 33 bytes, and it is a structurally valid MIDI file - format 0, one track, 480 ticks per quarter note - whose entire content is a tempo event of 500,000 microseconds (120 BPM) and an end-of-track marker:
4d 54 68 64 00 00 00 06 00 00 00 01 01 e0
4d 54 72 6b 00 00 00 0b
00 ff 51 03 07 a1 20 tempo, 500000 us
00 ff 2f 00 end of track
No note events at all. I parsed it with two independent parsers and they agree: 2 messages on the track, a set_tempo and an end_of_track, total playback length 0.0000 seconds. It will open in a DAW and look like an empty region, which is at least honest, but it is a file that says nothing about why the conversion came back empty.
Copy note list does nothing whatsoever. I checked both ends of it. No clipboard write happened at all, and the message on screen did not change - it was still the red "no steady pitch was found" line before and after the click. The copy handler returns immediately when the note list is empty, before it reaches the code that would report anything. So the button is not broken; it is silent in exactly the state where you would most want it to tell you something.
If you get zero notes and want to know what happened, do not reach for Copy - it will not answer. Use the four readouts instead. The note count and the pitch range together tell you whether the detector heard nothing at all or heard the wrong thing, and the checks that separate those two cases are all numeric.
Only Clear does. Measured on the live page, one click of Clear:
No file chosen yet.;Cleared. Choose a file to begin.Two things Clear does not do, both of which are visible in the table above: it leaves the numbers inside the hidden result card untouched, and it does not erase the canvas - the old piano roll is still in the pixels, just not on screen. It also does not reset the four controls, so whatever you typed into Tempo, Confidence, Transpose and Shortest note is still in place for your next run. The canvas behaviour is measured in detail here.
Choosing a different file is not a reset either. It hides the result card, but the stored note list and .mid survive, which is the whole reason the table above has three identical 105-byte rows in it.
File object sitting in the input along with its byte size, the
four readouts, and the canvas contents.URL.createObjectURL was wrapped so the
exact bytes of the .mid the page writes could be read, and
navigator.clipboard.writeText was hooked so the exact text it copies could be read. The
byte comparisons above are of those captured bytes, not of files that were saved to disk.Detail: is the browser's, not the page's, and will differ elsewhere.writeText with a function that
rejects; for the microphone message I removed navigator.mediaDevices before clicking.
Those two are code-path tests and I am labelling them as such. The size rejection, the decode
failure and the empty result all happened for real, with real files.