# Convert MP3 file to MIDI — should you slow the recording first?

Measured2026-11-12. This is a source-speed preprocessing experiment on real human audio, not a new converter, speed-control feature or recommended universal setting. Start with the original single-note recording in the existing converter; if you test a slower copy, compare its time-restored draft with the original-speed output before editing. Production detection remains monophonic, one pitch at a time; simultaneous polyphonic transcription requires another processing path.

## Source, rights and fixed selection

Xi and colleagues’ GuitarSet1.1.0, DOI https://doi.org/10.5281/zenodo.3371780, CC BY4.0 https://creativecommons.org/licenses/by/4.0/. Full attribution and modifications: ATTRIBUTION.md. Recording00_BN1-129-Eb_solo_mic.wav is a human acoustic guitar microphone performance; no MIDI rendering or synthesized instrument replaces it. The same source and first20seconds were used in prior site work; this is disclosed reuse, not a new performance or new annotation. Source samples and inherited settings are not credited as original sentences.

Existing full public originals:

- https://audiotomidinow.com/guitar-to-midi/files/00_BN1-129-Eb_solo_mic.wav
- https://audiotomidinow.com/guitar-to-midi/files/00_BN1-129-Eb_solo.jams

The complete WAV SHA256 is `2a6057d0485d8ee2f4a04175ee085d610c0f7a13194e083b13ce803bec091d43`; annotation SHA256 is `2258ef6f5dc58437f2807dfc0c05416ad8498cd345f95d6563b13d19283e6d54`. Four windows [0,5),[5,10),[10,15),[15,20)seconds are A/B/C/D, fixed before new outputs in experiment-plan.json. They are correlated windows of one performance, not four independent subjects. Each source crop is44100Hz mono PCM16,220500samples. `source-check.py` verifies complete source hashes, exact crop samples and every cropped reference interval against original JAMS.

## Six conditions,24 raw conversions

`generate.py` encodes each source crop once to192kb/s MP3 and decodes one common signed16bit PCM baseline. All speed transformations start from that common decode, not independently re-encoded versions. No normalization or subsequent MP3 re-encode of transformed WAVs.

| Condition | Audio treatment | MIDI inverse mapping |
| --- | --- | --- |
| baseline | Common MP3 decode,44100Hz PCM16 | times×1, pitch unchanged |
| tempo100 | FFmpeg atempo=1.0,44100Hz PCM16 | times×1, pitch unchanged |
| tempo075 | FFmpeg atempo=0.75,44100Hz PCM16 | times×0.75, pitch unchanged |
| tempo050 | FFmpeg atempo=0.5,44100Hz PCM16 | times×0.5, pitch unchanged |
| rate050 | Identical baseline PCM samples written at22050Hz deliberately, changing interpreted speed and pitch | times×0.5, note numbers+12 |
| tempo125 | FFmpeg atempo=1.25,44100Hz PCM16 | times×1.25, pitch unchanged |

The tempo filter is tested as a tempo-changing preprocessing path; actual output pitches, duration and MIDI are measured, not assumed preserved. Official references: https://ffmpeg.org/ffmpeg-filters.html#atempo and https://ffmpeg.org/ffmpeg-filters.html#asetrate. The latter documents that rate reinterpretation changes speed and pitch without changing PCM; that general arithmetic is known and not originality credit. The archived installed encoder build and hash are recorded in inputs.json; latest documentation does not promise byte identity with this older build. Pinned FFmpeg binary SHA256: `c8abc49e7be62dde8e12972af373959e0076a7b8dc8040eb45978e0608f8781e`.

All24 raw WAV conditions pass through the unchanged production downsample/detectNotes/buildMidi snapshot, fixed Balanced2. Callbacks are harmless local harness stubs, not algorithm edits. Rate050 is an offline control; no rate-changing feature was added to the browser tool. Existing guitar lag diagnosis is not reopened and no new high-event acoustic cause is asserted.

## Keep raw output, then map its clock explicitly

Raw MIDI files remain untouched. Each `*-restored.mid` is separately derived by `map_midi.py`. The production exports use Standard MIDI format0, one track,480PPQ and one500000microseconds/quarter tempo event. The second file changes only that tempo to500000×declared speed and, for rate050 only, note-on/off pitch bytes+12. This preserves event ticks, lengths, velocities and all other bytes. Raw and restored files are independently parsed and checked for exact intended time/transpose relationships. The resulting tempo values are coordinate corrections, not a measurement of the source performance’s BPM; the filename’s129 is not used to fit anything. Standard MIDI context: https://midi.org/standard-midi-files.

Seconds =ticks×microseconds-per-quarter÷PPQ÷1000000; milliseconds =seconds×1000. A raw slower-file event at t seconds maps to t×declared speed on the original timeline. No fitted global offset, endpoint stretching, per-note alignment or optimal transposition is used. Input actual duration is measured from saved sample frames/rate, not assumed to equal five/speed exactly. `inputs.json` and `comparisons.json.durations` disclose that distinction. Inverse mapping cannot remove detector errors or promise to reconstruct the original performance.

## Independent reference and editing checks

`midi_reader.py` reads stored SMF headers, tempo, note on/off and times independently of the JavaScript writer. `analyze.py` makes a raw and inverse-mapped pitch/time table and original-time Piano Roll for every condition. Generated SVGs are plots, not DAW screenshots. Reference intervals crossing a crop boundary remain in plots, while carried-in notes are excluded from the new-attack matching denominator.

The fixed matcher follows reference chronological order, pairs exact integer pitch to the nearest unused output onset within150ms, one-to-one, and imposes no duration or octave-equivalence acceptance rule. Reference attack IDs are zero-based within each crop's new-attack list, after carried-in intervals are excluded. A matched attack is not proof of a good release, sound or held-note duration. GuitarSet labels are largely automated with known errors and overlapping ringing-string intervals; these are inherited labels, not freshly hand-checked musical truth. A change in accepted reference identity under this matcher is disclosed, not called a universal transcription improvement.

`compare.py` records counts, unmatched outputs, gained/lost reference attack identities and shared attack start/duration/velocity differences. `verify-claims.py` independently checks the article’s specific numeric claims from parsed events, declared mappings and inherited references; findings.json records all14 grouped findings. The MIDI velocities are stored integer event values, not acoustic loudness measurements. Changed velocity ordering is not a listening-preference conclusion.

## Actual browser operations and reproduction

Four actual production file-chooser conversions/downloads used A recorded MP3, A tempo050 WAV, C tempo075 WAV and C tempo050 WAV at Balanced2. Their saved raw MIDI files contain8,9,11,13events respectively and are byte-identical to corresponding offline raw outputs. The other20conditions, including allrate050cases, are numerical offline runs; no DAW import, competitor submission, listening study or network-privacy test was performed.

Download all manifest.json files into one directory. With Python3, Node and a trusted FFmpeg with libmp3lame/atempo, run:

```text
python source-check.py
python generate.py --ffmpeg /path/to/ffmpeg
node convert.mjs
python analyze.py
python compare.py
python browser-compare.py
python verify-claims.py
```

The source checker accepts `--original /path/to/original.wav --annotation /path/to/source.jams`; otherwise it obtains the two already-public originals above and verifies hashes first. Browser comparison requires the four archived unmodified browser MIDI downloads. Regeneration requires the four source WAVs, experiment plan, references, detector/parser/mapping/generator/checker scripts. A fresh-directory rerun with the same archived build reproduced all132 numerical input/MP3/WAV/raw MIDI/restored MIDI/CSV/SVG/results listed in reproduction.json. The browser downloads are archived comparisons, not counted as regenerated outputs. Different builds may produce different samples and downstream events.

## Research, originality and limits

Today’s actual Google query used hl=en,gl=us,pws=0; physical country is not independently established. Page1 ordinary ordering is preserved, then page2 suppliesCraftMusic as original10. Original5Reddit returned403 and remains unknown; observed-order11MusicCreator is the tenth readable body. First3 and ten complete readable extracts were read and LF-byte hashes verified. No snippets, ads, AI overview citations or inaccessible source are substituted as ordinary-body proof. research-review.json and primary-sources.json limit every coverage/absence statement to actual inspected material, not worldwide uniqueness.

The new question is slowing audio before detection and checking the nominally restored draft, not the old synthetic quiet-note, PPQ, bar-meter, source-label or retained-PCM padding studies. Existing source/baseline material, coordinate arithmetic, setup, source/license, necessary instructions and limits are not counted as original discoveries. Full-main sentence and block ledgers retain all necessary prose, with explicit exclusions for headings/commands/pure file labels. Acceptance requires both5*O>2*N and5*(O-2)>2*N without rounding; no word-count substitute, claim splitting or denominator removal. One correlated performance, one archived build and one fixed detector cannot establish a universal best speed or cross-instrument cause.
