26 files pushed through the real converter: 17 containers, plus the same MP3 under nine different names. The name never changed anything. The browser did.
Short answer: this page never looks at your file's name or its type. Its only check
is size - above 80 MiB it turns the file away, and that is the whole gate. Everything else is decided
by your browser's own decoder. I gave one 65,244-byte MP3 nine different
extensions - .txt, .pdf, .mid, .mp4,
.wav, .MP3, and none at all - and all nine converted to the
same 8 notes. I also fed it video: an MP4, a MOV,
an MKV and a WebM all converted, because the browser pulls the
audio track out of the container before the page ever sees the data. Of 17 containers, four
were refused: AIFF, WMA, AMR, and a video file with no audio track.
Everything below was measured on this page's own converter running in a real browser at
easyaudiotomidi.com. Real files were pushed into the file input, the real Convert button
was clicked, and the page's own status line and readouts were read back. The one exception is the drop
zone, where I dispatched a real drop event carrying a real File object - noted again where
it matters.
This is the root of everything else, so it is worth stating precisely. There is exactly one place in the page where a file type appears, and it is an attribute on the hidden file input:
<input type="file" id="file" accept="audio/*" hidden>
The function that receives the file does not read file.type, and neither does anything
else. It checks one thing:
function acceptFile(file) {
if (!file) { return; }
if (file.size > MAX_BYTES) { ...turn it away... return; }
currentName = file.name;
... fr.readAsArrayBuffer(file);
}
From there the raw bytes go straight into the browser's decoder, with no format check in between:
p = ctx.decodeAudioData(arrayBuffer, resolve, reject);
So the sequence is: size check, then hand the bytes to the browser and see what happens. The file information line under the drop zone reflects that - it prints the name and the size in KB and nothing else, so the page never shows you a type either.
To test this directly I took one MP3 file (65,244 bytes) and made byte-identical copies with different names, then ran each through the converter. The right-hand column is the browser's own guess at the type, which is derived from the name - and which the decoder then ignores.
| Name given to the file | Type the browser reported | Result |
|---|---|---|
| mp3_128.mp3 | audio/mpeg | Converted 8 note(s), Range C4 - C5 |
| mp3_as.txt | text/plain | identical |
| mp3_as.pdf | application/pdf | identical |
| mp3_as.mid | audio/mid | identical |
| mp3_as.mp4 | video/mp4 | identical |
| mp3_as.wav | audio/wav | identical |
| mp3_as_upper.MP3 | audio/mpeg | identical |
| mp3_noext | (empty) | identical |
| wav_as.mp3 (WAV bytes) | audio/mpeg | identical |
"Identical" means all of it: the same Converted 8 note(s) from 4.0 s of audio message, the
same Range C4 - C5 readout, and the same decoded buffer handed to the page - 1 channel,
44,100 Hz, 176,400 samples, in every one of the nine cases. The last row is the interesting one: those
are WAV bytes wearing an .mp3 name, the browser called them audio/mpeg, and
they still decoded as WAV. The name did not change what the file was, and it did not change what the
page did with it.
What this does not prove. These files were set into the input programmatically,
which bypasses the file dialog and therefore bypasses the accept filter. So this
measures the decode path, not the picker. The picker is covered separately below, where the answer
turns out to be different.
All of these were generated from the same 4-second monophonic melody, so the audio content is the same throughout and only the container or codec changes. Every row was pushed into the input and converted on the live page.
| Container / codec | Result on the page |
|---|---|
| WAV, 16-bit PCM | Converted 8 note(s), C4 - C5 |
| WAV, 32-bit float | Converted 8 note(s), C4 - C5 |
| WAV, 8 kHz | Converted 8 note(s), C4 - C5 |
| WAV, 6 channels (5.1) | Converted 8 note(s), C4 - C5 |
| MP3, 128 kbps | Converted 8 note(s), C4 - C5 |
| FLAC | Converted 8 note(s), C4 - C5 |
| OGG Vorbis, q5 | Converted 8 note(s), C4 - C5 |
| WebM / Opus, 96 kbps | Converted 8 note(s), C4 - C5 |
| M4A (MP4 container) / AAC | Converted 8 note(s), C4 - C5 |
| Raw AAC, ADTS framing | Converted 8 note(s), C4 - C5 |
| MP4 container, audio only | Converted 8 note(s), C4 - C5 |
| MP4 video, H.264 + AAC | Converted 8 note(s), C4 - C5 |
| MOV video, H.264 + AAC | Converted 8 note(s), C4 - C5 |
| MKV video, H.264 + AAC | Converted 8 note(s), C4 - C5 |
| WebM video, VP9 + Opus | Converted 8 note(s), C4 - C5 |
| AIFF, 16-bit PCM | Could not decode this file. |
| WMA v2 (ASF container) | Could not decode this file. |
| AMR-NB, 8 kHz | Could not decode this file. |
| MP4 video, no audio track | Could not decode this file. |
The AIFF refusal is worth pausing on, because AIFF is an uncompressed format and people reasonably
expect it to work. It is the browser that will not open it, not this page - the decoder raised
EncodingError: Unable to decode audio data before any pitch detection ran.
One detail fell out of the measurement that explains more than it looks like. The page resamples whatever it gets down to 16 kHz, and its own code compares the source rate against that target. But the buffer the browser hands over was reported as 44,100 Hz in every single case - including the 8 kHz WAV and the 48 kHz Opus. That is the audio context's rate on this machine, not your file's. So by the time the page's own resampler runs, the rate is already normalised. What the mixdown and resample do after that point is measured in what sample rate and channels do before detection.
The browser did not downmix the 5.1 WAV - it handed the page all six channels. The page then averaged them, and because all of the signal sat in one channel, the average came out at one sixth of the original level: 0.3322 RMS per channel became 0.0554 after averaging. The notes survived it, but the velocities did not. The same melody as a mono WAV came back with every note at velocity 100; the 6-channel version came back with the same eight notes at the same times and velocities from 68 to 93.
The FAQ on the converter says there is no video button and that the page does not demux video, and that is accurate - there is no video button and the page has no demuxer. But "the page does not demux" is not the same as "video will not work", because the browser's decoder does the demuxing for it.
An MP4 with H.264 video and an AAC audio track converted to 8 notes, and I ran it twice to confirm it was not a fluke. A MOV, an MKV and a WebM with VP9 video and Opus audio converted too. In each case the page received a clean 1-channel, 44,100 Hz, 4.0-second buffer - the video track was simply discarded before the page ever saw the data.
The boundary is the audio track, not the extension. An MP4 holding only video, with no audio stream at all, failed with the same cannot-decode message as the AIFF. That is the honest shape of it: if the container holds audio your browser understands, you get notes; if it holds no audio, you get an error.
The accept="audio/*" attribute on the input is not decoration. It is what your operating
system's file dialog uses to decide which files to show you when you click the drop zone to browse.
That is the only place a type check exists in the whole flow, and it is enforced by the browser and the
OS, not by the page.
The drop zone itself has no filter. Dragging a file onto it goes through a different handler that
receives the file directly and passes it to the same acceptFile function, with nothing in
between. I tested that by dispatching a real drop event carrying a real File object:
| Dropped onto the zone | Result |
|---|---|
MP3 renamed melody.txt (declared text/plain) | Converted 8 note(s), C4 - C5 |
MP3 renamed melody.pdf (declared application/pdf) | Converted 8 note(s), C4 - C5 |
MP3 named melody.mp3 (control) | Converted 8 note(s), C4 - C5 |
Real MP4 video, holiday.mp4 | Converted 8 note(s), C4 - C5 |
Real MOV video, clip.mov | Converted 8 note(s), C4 - C5 |
| WMA (control for failure) | Could not decode this file. |
One detail from that run is the cleanest proof of the whole mechanism. While those files were being
dropped, the hidden file input still held the previous file - webm_video.webm -
and the information line showed the dropped name instead. The drop path never touches the input
element, so the accept attribute cannot constrain it. A drop ends at the decoder, exactly
like a browsed file does, which is why the WMA drop failed in the same way the WMA upload did.
All four refusals - AIFF, WMA, AMR and the audio-less MP4 - produced the identical text, and that text names WMA specifically:
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
So an AIFF file is told that WMA is a common case. The message is a fixed string with the browser's own error text appended, not a diagnosis of the file you actually handed over. What the page leaves behind after that message - the previous note list, the previous .mid, and the file input still holding the refused file - is measured message by message in every failure message and what it leaves behind.
accept filter, so those 26 results describe the decode path. I did not
open an operating system file dialog, so I am not claiming how your OS presents the audio filter -
only what the page declares.File objects carried real bytes, but no human
dragged anything.