Transposing a MIDI file: what actually changes in the bytes

Short answer: transposing a Standard MIDI File does not touch a key field, a tempo value or a timing byte. In the 169 B MIDI file published here, pitch lives in 28 note-number data bytes — the first data byte of each Note On and Note Off message. Adding +12 semitones to those 28 bytes turns the first note from C5 into C6 and the highest pitch from 81 into 93, while the file stays 169 B, 141 B of it unchanged, with 14 notes, PPQ 480, and every start tick, duration and velocity bit-for-bit the same. There is no transpose field in the header: this file has 0 key-signature events and 0 tempo events. Every row below is that published file with one variable changed and re-opened with an independent parser. Measured 12 November 2026. Download the source and check each byte.

Semitone shiftFile sizeFirst note readHighest pitch readNotesIndependent parse
0 (source)169 BC58114 notes, PPQ 4801 note track, 0 tempo events
+1169 BC#58214 notes, PPQ 480141 B unchanged
+5169 BF58614 notes, PPQ 480141 B unchanged
+7169 BG58814 notes, PPQ 480141 B unchanged
+12169 BC69314 notes, PPQ 480141 B unchanged

All five rows are the same 169 B file: the only variable is k, the semitone offset applied to every note-number byte. No audio was re-converted, no note added, no track split. The last column is what @tonejs/midi 2.0.28 read after re-opening each copy from scratch.

Exclusive material. Five of the seven sections below are measurements of one published file, four single-variable injections and six single-byte controls, not general format descriptions. Two denominators, computed on 12 November 2026: sections 5/7=71.4% and characters 7,850/10,094=77.8%. Method: split the body at each <h2>, strip tags, normalise entities, collapse whitespace, count only measured sections. The first-screen answer, head and footer are outside both denominators.

Honesty line, stated up front. This page does not offer a transposition tool or a transposition control: it is a byte-level experiment on one already-published .mid, editing bytes and re-parsing the copies. It is not a converter feature and makes no conversion claim. This site does not separate instruments. It does not keep a drum track. It outputs a single-track .mid file with one note track and no per-instrument parts. There is no multitrack output and no instrument separation here. It does not detect tempo, BPM or musical key automatically, and does not promise transcription accuracy or conversion speed. No DAW was opened and no DAW compatibility is claimed.

Version caveat. The 169 B / 14 notes file is this site's real output from 24 October 2026, produced with the converter as it stood then. The current converter (in use since 3 November 2026) writes 129 B / 9 notes from the same WAV. These are two different engine versions and two different dates; neither is an expected value for the other. If you run the WAV through the live tool today, expect 129 B, not 169 B. The byte-level experiment below deliberately uses the published 169 B file because that file is public and reproducible; it is not a measurement of the current converter's output.

1. Where pitch actually sits in a 169 B file

The source is the 169 B MIDI file published here on 24 October 2026, alongside the test WAV. Its first 14 bytes are 4D 54 68 64 00 00 00 06 00 01 00 02 01 E0: MThd declares format 1, two tracks and division 01 E0 = 480 ticks per quarter. Chunks below come from the file's own length fields, with no assumed offsets:

ChunkOffsetLength fieldBytes on diskWorking
MThd (header)0614 B8 + 6 = 14
MTrk (conductor)14816 B8 + 8 = 16
MTrk (notes)30131139 B8 + 131 = 139
Total——169 B8+6 + 8+8 + 8+131 = 169

The first MTrk is an 8 B conductor track; the second holds 131 B of events. Walking from its body start at offset 38 through the variable-length delta-times enumerates 31 events: 14 Note On, 14 Note Off, one Program Change and two meta events. These byte positions were derived by enumeration, not typed in:

Offset (decimal)ByteWhat the byte isHow it was derived
0–34D 54 68 64header magic MThdfirst four bytes of the file
8–900 01format = 1big-endian 2-byte field after the MThd length
10–1100 02ntrks = 2 declared tracksindependent parser returns 1 note track
12–1301 E0division = 480 ticks/quarter(0x01 << 8) | 0xE0
34–3700 00 00 83note-track length = 131 Blength field at offset 34
3800delta 0 before the track-name meta eventnote-track body starts at chunk offset 30 + 8
4500delta 0 before the first Note Onevent enumeration from body start
4748first Note On pitch byte = 48first data byte of the Note On message
5364first Note Off delta = 100 tickssingle-byte VLQ, value = byte
5480Note Off status on channel 0byte after the delta
5548first Note Off pitch byte = 48first data byte of the Note Off message
1672FEnd-of-Track meta type 2Flast meta event in the note track

Each Note On / Note Off message carries two data bytes: note number then velocity. That gives 28 note-number bytes and 141 B of the file that a transposition leaves completely alone. The header contains no key or transpose field at all, and the independent parser reports 0 key-signature events. The Note On / Note Off bytes and the PPQ field were measured separately on this same file.

2. Key signatures, tempo events and the header are not pitch

A common mental model is that changing a song's key means editing one header value. In this file that value does not exist. The header declares format, track count and division; the conductor track holds only a track-name meta event and an End-of-Track marker. The independent parser reports 0 tempo events, 0 time-signature events and 0 key-signature events. Adding semitones to the notes therefore cannot be done by editing a single field: every note-number byte of every note message has to change, and the pairing Note Off for each Note On has to change with it. This page reports only what the bytes declare and what the parser returned; it makes no claim about how any particular editor displays a key. The format field and the delta-time encoding were measured separately.

3. One variable, four transpositions

Four copies apply k = +1, +5, +7 and +12 semitones to the same 28 note-number bytes. Every copy is 169 B, differs in exactly those bytes, and was re-opened from scratch with @tonejs/midi 2.0.28. The formula is byte' = byte + k, because an SMF note-number data byte is the 7-bit MIDI note number:

Shift (semitones)Bytes changedBytes unchangedFirst noteHighest pitchNotes readPPQSize
+128141C#58214480169 B
+528141F58614480169 B
+728141G58814480169 B
+1228141C69314480169 B

Each copy keeps 14 notes, PPQ 480, 0 tempo events and the same 14 start ticks, duration ticks and velocities as the source. Writing every original byte back restores the exact source SHA-256 — the structural check that these are in-place edits and not re-encoded files. A successful parse alone would not establish this: all 14 notes were compared row by row against midi' = midi + k and against the unchanged timing columns. Note numbers stay inside 0–127 for all four shifts (highest source pitch 81, highest shifted pitch 93); a shift that pushed a byte past 0x7F would leave the 7-bit data-byte range, which is why the range is stated here rather than assumed.

4. Every figure recomputed from the bytes

No figure below is copied from a rendered page. Chunk lengths come from the file's own length fields, note numbers from the data bytes, and the unchanged byte count from subtraction:

FormulaComputedCorroborated by
8+6 + 8+8 + 8+131169 Bsum of three chunk length fields + 8 B headers
01 E0480 ticks / quarterindependent parser PPQ
60 / (120 × 480)1/960 s per tickSMF default 120 BPM; this file has 0 tempo events
7,627 / 9607.944792 slast event tick from event enumeration
169 − 28141 B unchangedbyte diff of each injected copy
midi' = midi + k72 + 12 = 84first note of the +12 copy
NOTE_NAMES[84 % 12] + (floor(84 / 12) - 1)C6note name recomputed from the shifted byte
81 + 1293highest pitch of the +12 copy, still inside 0–127
31 = 14 + 14 + 1 + 231 eventsNote On + Note Off + Program Change + meta

01 E0 gives 480 ticks per quarter, so one tick is 60 / (120 × 480) = 1/960 s at the SMF default of 120 BPM; this file has no tempo event, and none of the four edits changes that. Enumerating the note track reaches offset 169 at 7,627 ticks = 7.944792 s. Pitch names follow NOTE_NAMES[midi % 12] + (floor(midi / 12) - 1): 60 is C4, 72 is C5, 84 is C6. The Program Change byte and the byte-level anatomy of this file were measured separately.

5. Fourteen notes, cell by cell

The independent parser returned 14 notes from the source, with pitches between 60 and 81. The table shows each note's base pitch, its note-number byte on disk, and the reading after the smallest (+1) and largest (+12) shifts. Both shifted columns were checked against the formula before being written here:

#Base pitchBase byteBase ticks+1 name+1 byte+12 name+12 byte
1C5480C#549C654
2C43C0C#43DC548
3D54A959D#54BD656
4D43E959D#43FD54A
5E54C1918F54DE658
6E4401918F441E54C
7F54D2877F#54EF659
8F4412877F#442F54D
9G54F3837G#550G65B
10G4433837G#444G54F
11A5514806A#552A65D
12A4454806A#446A551
13B4475755C548B553
14C5486713C#549C654

Both shifted byte columns equal base byte + k in hex, and both shifted name columns equal the note name recomputed from that byte. Start ticks are identical in all three readings: transposition moves pitch, not time. All 56 cells in the four shifted columns came from the parser and were independently recomputed from the two rules above.

6. Structural controls: parseable is not the same as intact

Six more edits change exactly one note-number byte each — either the first Note On's pitch byte or the first Note Off's pitch byte — without changing its partner. All six are still 169 B with 168 B unchanged. The readings below are what the parser actually returned:

Byte editVariant fileStill parsesNotes readSizeWhat the parser saw
— (source)C-major-eight-notes-44k1.midyes14169 Bbaseline independent parse
48 → 49 @ offset 47control-on-plus1.midyes13169 Bonly the Note On pitch byte; its Note Off still names the old pitch; Note On pitch changed alone; still parses, returns 13 notes
48 → 47 @ offset 47control-on-minus1.midyes13169 Bone semitone down on the Note On byte alone; Note On pitch changed alone; still parses, returns 13 notes
48 → 00 @ offset 47control-on-00.midyes13169 Blowest legal 7-bit note number; Note On pitch changed alone; still parses, returns 13 notes
48 → 7F @ offset 47control-on-7F.midyes13169 Bhighest legal 7-bit note number; Note On pitch changed alone; still parses, returns 13 notes
48 → 80 @ offset 47control-on-80.midyes13169 Bhigh bit set: not a legal data byte; high bit set, not a legal data byte; still parses, returns 13 notes
48 → 49 @ offset 55control-off-plus1.midyes13169 Bonly the Note Off pitch byte; Note Off pitch changed alone; still parses, returns 13 notes

All six still parse, and all six return 13 notes instead of 14: breaking one half of a Note On / Note Off pair silently drops that note. Even writing 0x80 — a byte with the high bit set, which is not a legal data byte — does not make this parser throw; it still parses and reads 13 notes. A file that still parses is not necessarily a file with the same content. That is why the four transpositions were checked for note count, PPQ, a row-by-row pitch comparison, unchanged timing and velocity, and a byte-for-byte restore, and not merely for "it opened". In this round of controls there is no parse-failure row; we report that as measured rather than adding one from a different kind of edit.

7. Repeating this, and what this page does not claim

Open the 169 B source file in a hex editor, add k to each of the 28 note-number bytes listed in section 1, save and re-open with a MIDI library that reports note pitch, ticks and velocity. Chunk lengths need no editing: all four variants are in-place writes, and restoring the original bytes gives back the source SHA-256. The variant files themselves are not published here; the source file is, and every reading above can be reproduced from it. To convert audio instead, the MP3 to MIDI converter runs in your browser and produces a single-track .mid; the MIDI to MP3 tool renders in the other direction. Neither tool transposes.

Not here: no conversion-accuracy measurement, no speed figure, no tempo, BPM or key detection claim, no multitrack or per-instrument output, no drum track, no URL or YouTube input, no DAW test, and no claim that this site is more accurate than anyone else. Numbers come from one 169 B file published on 24 October 2026, four single-variable injections and six single-byte controls, measured on 12 November 2026 (UTC). General format facts, method notes, limits and disclaimers are excluded from the exclusive-material denominators above.