The short answer: a chord identifier built on this converter does not name chords. It detects up to 6 pitches per analysis frame, writes each one as a MIDI note, and stops there. There is no chord dictionary, no Roman-numeral labeller, and no text event in the exported file — we checked, and a two-note export contains exactly 71 bytes with only tempo, time-signature and end-of-track meta events. Naming the chord is a step you do after the fact, by looking at the notes in a piano roll. What the engine can do is find the pitches that make up a chord: a clean C major triad (C4 + E4 + G4) played on its own comes back as all three notes, correctly pitched and correctly timed. What it cannot do is find those same notes when they are buried in a full mix — in our song test the chords came back at 10 of 24 when mixed with bass, melody and drums, against 24 of 24 when converted alone. It also cannot find a chord whose notes are harmonics of a lower note: play C4 and C5 together and the harmonic-suppression rule collapses them into a single C4, because C5 is the second harmonic of C4 and the detector cannot tell them apart. So the honest answer to “can it identify chords” is: it can find the notes, under the right conditions, and you name the chord.
What the engine actually does when it sees a chord
Before asking what a chord identifier can name, it helps to know what the detection pipeline does with a frame that contains more than one pitch. This converter resamples audio to 22 050 Hz, reads it with a 2048-point FFT stepped forward 256 samples at a time, and produces one frame every 11.610 ms (86.13 frames per second). In polyphonic mode, each frame can emit up to 6 spectral peaks — the six loudest candidates above a relative threshold. Each peak is then refined with parabolic interpolation across three neighbouring bins and rounded to the nearest MIDI key. That is where notes come from: not from a chord table, but from a peak picker running on a short slice of spectrum.
Three built-in rules shape which peaks survive:
- Relative-to-peak threshold. A candidate must reach
0.14 − 0.11 × sensof the frame’s loudest peak — 7.4% at the default sensitivity of 60. A chord partial quieter than that is discarded before it ever becomes a note. - Harmonic suppression. When two peaks sit in a harmonic relationship (one is an integer multiple of the other), the lower one absorbs the higher one. This is what makes C4 + C5 collapse to a single C4: C5 is the second harmonic of C4, and the detector has no way to know that both were played intentionally.
- Six-voice ceiling. The peak picker stops at six candidates per frame. A seven-note chord produces six notes plus fragmentation; an eight-note chord produces ten note objects with three fragments. The ceiling is per frame, not per file — a chord that holds for one second spans 86 frames, and each one independently picks its six.
None of those rules look up a chord name. They are spectral operations. The chord name is something a human applies after reading the notes — or something a separate analysis tool does on top of the exported MIDI, not something this engine writes into the file.
Clean triads, measured: what comes back when nothing competes
To get a baseline, we ran isolated synthesised chords through this site’s own analyser (dsp.js). Every chord was played as three sine partials at equal amplitude, 0.60 seconds long, with known pitches so “correct” is not a matter of opinion:
| chord | written notes | notes found | pitches returned | correct |
|---|---|---|---|---|
| C major (C4 + E4 + G4) | 3 | 3 | C4, E4, G4 | 3 / 3 |
| F major (F4 + A4 + C5) | 3 | 3 | F4, A4, C5 | 3 / 3 |
| G major (G3 + B3 + D4) | 3 | 3 | G3, B3, D4 | 3 / 3 |
| A minor (A3 + C4 + E4) | 3 | 3 | A3, C4, E4 | 3 / 3 |
| E minor (E3 + G3 + B3) | 3 | 3 | E3, G3, B3 | 3 / 3 |
| D minor (D3 + F3 + A3) | 3 | 3 | D3, F3, A3 | 3 / 3 |
Every triad came back complete. The notes were pitched correctly and started within 7–12 ms of their written onset — within the 11.610 ms frame grid, which is the best the engine can do. A four-note seventh chord (C4 + E4 + G4 + B4) also returned all four pitches. So the ceiling for a clean, isolated chord is not three notes; it is six, and common four-note voicings are within it.
A chord progression tells you whether the timing holds across changes. We ran C–G–Am–F, one bar each at 120 BPM, and got 12 notes out of 12 expected: 8 distinct pitches, all correct, 0 extra notes, with onsets 7–12 ms from each bar line. That is the case where a chord identifier built on this engine works: the notes are there, the timing is frame-accurate, and you can read the chords off the piano roll.
The harmonic suppression rule: when a chord stops being a chord
The one built-in behaviour that silently destroys chords is harmonic suppression. When two notes in a chord sit in a harmonic relationship, the lower one absorbs the higher one, because the detector cannot distinguish “an overtone” from “a note that was played”. We measured three cases:
| interval played | notes in | notes out | what survived |
|---|---|---|---|
| C4 + C5 (octave) | 2 | 1 | C4 only — C5 is the 2nd harmonic of C4 |
| G3 + G4 (octave) | 2 | 1 | G3 only — same rule |
| E2 + E4 (double octave) | 2 | 1 | E2 only — E4 is the 4th harmonic of E2 |
| C4 + E4 + G4 + C5 (C major with octave) | 4 | 3 | C4, E4, G4 — top C5 absorbed by C4 |
| B3 + D4 + G4 (non-harmonic voicing) | 3 | 3 | B3, D4, G4 — no harmonic relationship, all kept |
The rule is simple: if one note’s frequency is an integer multiple of another’s, the higher one gets absorbed. A C major triad with a doubled root (C4 + E4 + G4 + C5) comes back as three notes, not four. A power chord (root + fifth) survives because the fifth is not an integer multiple of the root. But any voicing that stacks octaves — and many guitar and piano voicings do — will lose the doubled notes. This is not a setting you can turn off; it is how the harmonic-comb scoring works. If your chord identifier needs every note, keep the voicing within one octave.
What happens when the chord is inside a mix
The clean-triad test is the best case. Real audio usually has other instruments playing at the same time, and that is where chord identification falls apart — not because the engine cannot find chords, but because the relative-to-peak threshold silences chord partials that are quieter than the loudest thing in the frame. We built a 16-second song with known answers — 16 bass notes, 24 chord notes, 32 melody notes — and converted it as a full mix and then each stem alone. The chord numbers tell the story:
| condition | chord notes written | chord notes found | recall |
|---|---|---|---|
| chords alone (no bass, no melody, no drums) | 24 | 24 | 100% |
| chords + bass | 24 | 11 | 45.8% |
| chords + bass + melody | 24 | 10 | 41.7% |
| full mix (all six stems) | 24 | 10 | 41.7% |
The chords lost 13 of 24 notes the moment the bass joined them — not because of the drums, not because of the melody, but because the kick drum peaks at 0.90 amplitude while the chord stem sits at 0.42. At the default sensitivity, a partial must clear 7.4% of the frame’s loudest peak to count. The chord partials are still in the spectrum; they simply do not clear that line when something louder is present. Adding the melody and the drums did not make it worse — the damage was done by the first loud neighbour.
This is why a chord identifier from audio works on a solo piano recording and fails on a finished song. If you want to identify the chords in a full mix, the path that actually works is to isolate the chord stem first — using a source-separation tool, an EQ cut, or simply converting the section where only the chords are playing — and then run the converter on that. The engine can find the notes; it cannot find quiet notes next to loud ones. For more on this, Song to MIDI: what a full mix comes back as breaks down the entire 197-note export.
The low-register limit: chords below 181 Hz
Even in isolation, a chord has to sit in a region where the FFT can separate its notes. Each FFT bin at this converter’s settings is 10.77 Hz wide. A semitone is 5.95% of a frequency, so below 181 Hz (approximately F#3) two neighbouring semitones fall inside the same bin. A low chord like E2 + G2 + B2 (an E minor triad in first inversion on a guitar’s low strings) has its notes at 82, 98 and 124 Hz — the semitone gaps are 4.9 and 5.8 Hz, both under one bin. The detector may return the right notes by luck of the parabolic interpolation, or it may return one note that is the average of two. This is not a chord-specific limitation; it is the same arithmetic that makes any low note hard to read — the 181 Hz resolution line applies to single notes and chords equally.
| chord | lowest note | freq (Hz) | semitone gap (Hz) | gap in bins | verdict |
|---|---|---|---|---|---|
| E minor (E2 + G2 + B2) | E2 | 82.41 | 4.90 | 0.45 | under 1 bin — unreliable |
| A minor (A2 + C3 + E3) | A2 | 110.00 | 6.54 | 0.61 | under 1 bin — unreliable |
| F major (F3 + A3 + C4) | F3 | 174.61 | 10.38 | 0.96 | borderline — 1 bin |
| C major (C4 + E4 + G4) | C4 | 261.63 | 15.56 | 1.45 | over 1 bin — readable |
| G major (G4 + B4 + D5) | G4 | 392.00 | 23.31 | 2.17 | well separated |
Practical rule: if the lowest note of the chord is below F#3 (~185 Hz), the chord identifier may return the right pitch class but the wrong octave, or merge two notes into one. Transpose the audio up before converting if the chord matters, then transpose the MIDI back — though any note that was misread at the original pitch is still misread, just shifted.
What is in the file, and what is not
If the engine does not name chords, what does it write? We parsed the exported MIDI file event by event rather than scanning raw bytes, because a raw byte scan mistakes velocity values for status bytes. A two-note export is 71 bytes and contains:
| property | value |
|---|---|
| SMF format / MTrk chunks / division | format 1 / 2 / 480 TPQ |
| note-on events | 2 |
| note-off events | 2 |
| tempo meta events (0x51) | 1 |
| time-signature meta events (0x58) | 1 |
| key-signature meta events (0x59) | 0 |
| text meta events (0x01) | 0 |
| lyric meta events (0x05) | 0 |
| track-name meta events (0x03) | 0 |
| program-change events | 0 |
| distinct MIDI channels carrying notes | 1 (channel 0) |
One note track, one channel, no instrument assignment, no key signature, no text, no lyrics, no track name. The writer in midi.js emits only 0x90 (note on) and 0x80 (note off) for the note track, plus three meta events: tempo, time signature, and end of track. There is no code path that writes a chord name, a chord symbol, or any analytical label. If you need “C major” written somewhere, you do it in your DAW after importing the MIDI — the engine does not detect the key either, so there is no key for a chord-naming tool to work against.
What this means for chord identification: the converter gives you the raw pitches and the timing. You read them in a piano roll, recognise the stack as a chord, and name it. Or you feed the MIDI into a separate tool that does chord analysis on a note list. The engine is a front end — it turns sound into notes — not a theory engine.
When it works, when it does not, and what to do instead
| situation | does it find the chord notes? | what to do |
|---|---|---|
| Isolated chord, notes above F#3, no octave doubles | Yes — 3/3 to 6/6 | Convert, read the piano roll, name the chord |
| Isolated chord with octave doubles (e.g. C4 + C5) | Partially — doubled notes absorbed | Keep voicing within one octave, or accept fewer notes |
| Chord progression, clean source | Yes — 12/12 on C–G–Am–F | Convert the section, identify each bar |
| Chord buried in a full mix | Partially — 10/24 (41.7%) | Isolate the chord stem first, then convert |
| Low chord below 181 Hz (E2/G2/B2 region) | Unreliable — under 1 bin per semitone | Transpose up before converting, then shift back |
| 7+ note chord | Capped at 6 notes per frame + fragmentation | Accept 6 notes, or split the voicing |
| Chord with fast changes (< 60 ms per chord) | May merge — 11.61 ms grid + 60 ms min note | Use shorter minimum note setting, expect more debris |
The pattern is consistent: the engine finds pitches when they are the loudest thing in the frame, when they are above the 181 Hz resolution floor, and when they are not octave doubles of each other. When any of those conditions fail, you lose notes — and a chord with a missing note is not the same chord. The fix is almost always before conversion: isolate the source, transpose if needed, and choose a voicing the engine can separate. After conversion, the five-pass cleanup handles the debris that polyphonic mode adds, and polyphonic is the only mode that can see a chord at all — monophonic commits to one pitch per frame and returns zero chord tones by construction.
How to test it on your own audio
You do not need to trust the numbers above — run your own. This takes about two minutes:
- Find a short section of audio where a chord is playing and little else — a piano intro, a guitar chord stab, a sustained pad.
- Convert it here in polyphonic mode with the default settings (sensitivity 60, shortest note 60 ms).
- Download the .csv alongside the MIDI. The columns are
index,midi_note,note_name,start_sec,end_sec,duration_sec,velocity. - Sort by
start_sec. Notes that start within 50 ms of each other are likely from the same chord. - Read the
note_namecolumn for that cluster. If you see C4, E4, G4, that is a C major triad — the engine found the notes, you named the chord. - If notes are missing, check the register (below F#3?), the mix (is something louder playing?), and the voicing (are there octave doubles?).
The CSV is the fastest way to see what the engine actually found, because the piano roll can hide short notes in a dense display. If you want to compare two chords, convert each section separately and diff the note lists.
Questions people actually ask
Can this converter tell me what chord is playing?
No — it finds the pitches and writes them as MIDI notes, but it does not name the chord. There is no chord dictionary and no text event in the file. You read the notes in a piano roll and identify the chord yourself, or you feed the MIDI into a separate chord-analysis tool. On an isolated triad above F#3 the notes come back complete (3 of 3 in our tests), so the identification is straightforward; on a buried chord in a mix, notes go missing and the remaining notes may not form a recognisable chord.
Why did my chord come back with fewer notes than I played?
Three reasons, in order of likelihood. First, harmonic suppression: if one note is an octave (or any integer multiple) of another, the lower one absorbs the higher one — C4 + C5 returns only C4. Second, the relative-to-peak threshold: in a mix, chord partials quieter than 7.4% of the frame’s loudest peak are discarded. Third, the low-register limit: below 181 Hz, two semitones fit inside one FFT bin, so the detector may merge notes. Check the voicing, the mix level, and the register, in that order.
Does it work on guitar chords?
It can, with caveats. Guitar chords often use octave doubles across strings, which harmonic suppression will collapse. Low voicings on the low E and A strings (below 181 Hz) may not separate cleanly. And bent strings produce one MIDI note per semitone crossed — a bend is not a bent note, it is a chromatic run. A clean, open-position chord with no bends, played on its own, will come back with the right pitches.
Can it identify chords from a full song?
Poorly. In our 16-second song test, the chords came back at 10 of 24 notes when mixed with bass, melody and drums — against 24 of 24 when converted alone. The loss happens because the kick and bass are louder than the chord partials, and the relative-to-peak threshold discards anything under 7.4% of the loudest peak. To identify chords from a song, isolate the chord section or stem first, then convert that. See Song to MIDI for the full breakdown.
What is the maximum number of notes in a chord it can find?
Six per analysis frame — the peak picker stops at six candidates. A three-note triad and a four-note seventh chord are within the ceiling. A seven-note chord produces six notes plus one fragment; an eight-note chord produces ten note objects with three fragments. The ceiling is per 11.610 ms frame, not per file, so a sustained chord is re-evaluated 86 times per second. More detail on the ceiling is in how many notes a converter can hold at once.
Will it write the chord name into the MIDI file?
No. The exported file contains note-on and note-off events, one tempo event, one time-signature event, and an end-of-track marker. There are zero text events, zero lyric events, zero track-name events, and zero key-signature events — we verified this by parsing the bytes. If you need chord symbols in the file, add them in your DAW after importing. The engine is a pitch detector, not a notation tool.
Convert a file now — runs in your browser, nothing is uploaded. Use polyphonic mode and read the CSV to see the chord notes.
Related guides
- Mono vs polyWhy monophonic mode returns zero chord tones
- Song to MIDIWhat a full mix comes back as, measured
- Guitar to MIDIWhat a bend does to your notes
- Key & scale detectionWhy the file records pitches, not an analyzed key
- MIDI converterWhat is actually inside a MIDI file
- Clean up a converted MIDIThe 5 passes that turn a raw export into a usable part
- Audio to MIDI softwareHow many notes it can hold at once
- MP3 to MIDIThe 181 Hz resolution line and what it means for bass