Format 0, one track, 480 ticks per quarter note - read back byte by byte from a real output file.
Short answer: you get a standard MIDI file in format 0, with one track and 480 ticks per quarter note, on MIDI channel 1. Inside it there are exactly four kinds of event: one tempo event, the note-on and note-off pairs, and end of track. There is no instrument, no track name, no time signature, no key signature and no sustain pedal. I ran this converter's own writer outside the browser and read the resulting bytes, twice, with two independent parsers.
The rest of this page is the file itself. Everything below is either a byte sequence taken from a real
.mid produced by this converter's code, or a number derived from those bytes.
Every MIDI file starts with a header chunk. For a file made from an 8-note scale at 120 BPM, these are the first fourteen bytes, and they are the same fourteen bytes in every file this converter writes:
4d 54 68 64 00 00 00 06 00 00 00 01 01 e0
M T h d length = 6 fmt0 tracks1 division
| Bytes | Meaning | Value here |
|---|---|---|
| 4d 54 68 64 | The ASCII tag MThd | always |
| 00 00 00 06 | Header length in bytes | 6 |
| 00 00 | MIDI file format | 0 (single track) |
| 00 01 | Number of track chunks | 1 |
| 01 e0 | Division: ticks per quarter note | 0x01E0 = 480 |
Then comes one track chunk: the tag MTrk, a four-byte length, and the events. The eight-note test
file is 105 bytes in total - 14 for the header, 8 for the track tag and length, and 83 for the events.
Format 0 is worth pausing on. There is a second common layout, format 1, where each instrument gets its own track. Format 0 is the single-track layout: everything lives in one stream. That is the right choice for a monophonic detector, because there is only ever one note at a time to put there.
I parsed the output with two independent readers. Both report the same four event types and nothing else:
| Event | Count in the 8-note file | What it carries |
|---|---|---|
| Tempo | 1 | Microseconds per quarter note, at tick 0 |
| Note on | 8 | Channel 1, note number, velocity from loudness |
| Note off | 8 | Channel 1, note number, velocity 64 |
| End of track | 1 | Nothing - the terminator |
Here is that file read back, with each event at its absolute tick position:
tick 0 Tempo 500000 us/quarter (= 120 BPM)
tick 0 NoteOn C4 (60) vel=100
tick 461 NoteOff C4 (60) vel=64
tick 476 NoteOn D4 (62) vel=100
tick 937 NoteOff D4 (62) vel=64
...
tick 3348 NoteOn C5 (72) vel=100
tick 3794 NoteOff C5 (72) vel=64
tick 3794 End of Track
This is the part that surprises people when they open the file in a DAW:
None of that is a defect in the file - it is a faithful record of what a monophonic pitch detector can actually know. It finds notes. It does not find an instrument, a key, or a pedal.
The division field says 480 ticks per quarter note. To turn seconds into ticks, the writer uses:
ticksPerSec = (bpm / 60) * 480
At the default 120 BPM that is 960 ticks per second, so one tick is about 1.04 ms. Every note boundary is rounded onto that grid. I fed the writer three notes with deliberately awkward times and checked where each one landed:
| Note start | Tick at 60 BPM | Tick at 120 BPM | Tick at 200 BPM |
|---|---|---|---|
| 0.0000 s | 0 | 0 | 0 |
| 0.3333 s | 160 | 320 | 533 |
| 0.7777 s | 373 | 747 | 1244 |
| 1.0004 s | 480 | 960 | 1600 |
Different tick numbers - but divide each one back by that BPM's ticks-per-second and you get the same seconds every time. 160/480, 320/960 and 533/1600 are all 0.3333 s. That is the point: the BPM control rescales the grid and the tempo event together, so the wall-clock timing of your notes does not change. A half-second note is half a second at any setting:
| BPM setting | Ticks for a 0.5 s note | Tempo event written | Playback length |
|---|---|---|---|
| 60 | 240 | 1,000,000 µs/quarter | 0.5 s |
| 120 | 480 | 500,000 µs/quarter | 0.5 s |
| 200 | 800 | 300,000 µs/quarter | 0.5 s |
So what does the setting change? Two things, and both are practical:
If you were choosing the BPM expecting it to make the file play faster or slower, it will not. Change the project tempo in your DAW afterwards if that is what you want - the file will follow it.
Note-off velocity is 64, not 0. In the bytes, a note-off is
80 3c 40 - status, note number, and a velocity of 64. MIDI allows any release velocity there;
this writer always uses 64. It has no audible effect in most instruments, but it is why a note-off line in a
MIDI editor does not read zero.
At the same tick, note-off is written before note-on. The events are sorted by tick and then by status byte, and note-off (0x80) sorts ahead of note-on (0x90). You can see it at tick 3348 in the test file, where B4 is released and C5 starts at the same instant. That ordering is what you want: if the note-on came first, a repeated note on the same pitch would be cut off immediately.
If a note's start and end round to the same tick, the writer forces the end one tick later. A note listed from 1.0000 s to 1.0004 s at 120 BPM lands on tick 960 both times, and comes out as a single tick - about 1 ms. Nothing in the file is zero-length, but nothing stops a very short note being written either. The 60 ms minimum you set on the page is what keeps those out, not the file format.
If the detector finds nothing at all, you still get a valid file rather than an error: 33 bytes containing a tempo event and end of track, with no notes in it.
The converter is a single HTML file, and its MIDI writer is plain JavaScript. Rather than describe it, I
extracted that writer and the detector verbatim from the page source and ran them in Node - outside the
browser, on the same code the page ships. Then I parsed the resulting .mid files twice: once with
a reader I wrote from the MIDI specification, and once with mido, an unrelated third-party MIDI
library. Both agree on format, track count, division, tick positions and event types.
Inputs used: a 4-second C major scale as raw 16 kHz mono samples for the real end-to-end run, and a set of single 440 Hz tones at twelve amplitudes for the velocity measurements.
What the detector can and cannot hear in the first place is covered in how the pitch detection works and where the 2000 Hz ceiling falls.