AudioToMidiNow Use the MP3 to MIDI converter

MIDI CC · CHECK THE CONTROL EVENTS

MIDI CC: Why Do the Notes Match but the Controls Don't?

MIDI CC means Control Change: check the channel, controller number and value. Correct notes do not prove that expression data survived a handoff. Our seven downloadable MIDI files preserve every note event while changing control messages. Three one-byte edits isolate the wrong channel, the wrong controller and a different value.

Read a CC message without mixing up its fields

In MIDI 1.0, B0 0B 20 means channel 1, controller 11, value 32. These are hexadecimal bytes: 0B is decimal 11 and 20 is decimal 32. B1 selects channel 2. Controller numbers and ordinary single-byte values range from 0 to 127; channel labels run from 1 to 16. A controller number identifies a control, not a channel or a note.

The MIDI Association status table distinguishes Control Change from Note On, Program Change and Pitch Bend. The official controller table assigns controller functions. What a particular instrument implements still needs its own documentation.

CCConventional functionCheck before relying on it
1ModulationWhich destination is mapped?
7Channel volumeSeparate it from expression.
10PanCheck the receiver's routing.
11ExpressionDoes the receiver support it?
64Damper/sustainConventional switch: below 64 off, otherwise on.
120–127Channel ModeDo not treat these as spare knobs.

For preset selection, see Program Change. To separate a track label from the message destination, see MIDI channels. A wheel that bends pitch uses a separate Pitch Bend message, rather than an ordinary CC number.

Experiment 1: change one byte, keep every note

We generated format-0 files at 480 ticks per quarter note with a fixed tempo of 500,000 microseconds per quarter. Two channel-1 notes start at ticks 0 and 960, pitches 60 and 64, each with velocity 80 and duration 480 ticks. The control event sits at tick 240, between the first note's start and release. No converter or instrument was used to construct them.

DownloadMessage at tick 240Isolated change
Channel 1 expressionB0 0B 20Reference: CC11 = 32
Channel 2 expressionB1 0B 20Only the destination channel
Channel 1 volumeB0 07 20Only the controller number
Expression value 96B0 0B 60Only the value

Each file in this four-file comparison is 57 bytes. Against the reference, each variant differs at exactly one zero-based byte offset: 35 for the channel, 36 for the controller, or 37 for the value. That gives you a small control case to compare with an event-list display. If its controller label changes while the channel stays fixed, you changed a different field from a channel-routing repair.

Our reference reader initializes channel 1 to CC11 = 127 and CC7 = 100. Replaying the reference leaves CC11 at 32. The channel-2 variant leaves channel-1 CC11 at 127. The volume variant leaves CC11 at 127 but changes CC7 to 32. The value variant leaves CC11 at 96. Those are separate state entries; a viewer displaying only note rectangles would hide all three distinctions. The initialization is a stated model choice, not a claim about every synthesizer's startup state.

Experiment 2: the same tick can contain two orders

Download CC before Note On and CC after Note On. Both contain CC11 = 32 and the first Note On at tick zero, with the same tempo, pitches, velocities and note lengths. Their difference is the order of those two events in one track.

The independent reader processes the saved track in order. Starting from CC11 = 127, it sees 32 at the first note's start in the before file and 127 at that instant in the after file. Both end at 32. A final-value check therefore passes while a note-start-state check distinguishes them. If an exported clip has a control change on its opening tick, inspect the ordering as well as the timestamp.

This result describes the reader's event state, not an audible difference. An instrument may smooth expression or apply later messages during a sounding note. We did not measure that behavior. Events spread across multiple tracks also require the application's merge policy; this single-track experiment makes no claim about their order.

Experiment 3: audit notes and controls separately

The seventh file, notes only, has no CC messages. The independent decoder extracts absolute tick, message type, channel, pitch and velocity for every note-on and note-off, then hashes that ordered note ledger. All seven files have the same note fingerprint. Their full-file hashes differ because the control streams differ.

Use that separation when checking a transcription handoff: first compare the note ledger, then list the CC events, including their positions relative to Note On. Matching pitches, velocities and note lengths cannot establish that a pedal or expression curve was preserved. Conversely, different full-file hashes alone cannot establish that any note changed. Our fixtures demonstrate the distinction without guessing what expression an audio detector should infer.

The decoded report includes each note ledger, control message, one-byte difference and modeled note-start value. The file manifest provides SHA256 values for the exact downloads. These are checkable local artifacts, not a transcription-accuracy score.

Check a real handoff in this order

  1. Keep the original export. Inspect the channel, CC number and decimal value in an event list or MIDI monitor.
  2. Confirm that the destination supports the requested controller. Receiving notes does not establish CC support.
  3. Compare opening control events with the first note, including event order when their ticks match.
  4. Compare notes and controls separately before editing the pitches. Check the receiving application's own mapping and automation path.

Ableton's CC documentation illustrates why that last step matters: remote mapping and controller messages sent through a track are different control paths. A valid file cannot establish how an application mapped it.

Reproduce the files and the readout

Save experiment.py and inspect.mjs into a fresh folder. Run python experiment.py, followed by node inspect.mjs. The Python generator writes the seven fixtures. The separate JavaScript reader decodes the saved bytes and checks the note fingerprints, one-byte differences and event-order cases. A second generation in a separate directory was compared byte for byte.

Limits: these are constructed MIDI 1.0 files and an explicitly initialized reference state model. We did not record hardware, measure loudness, import into a DAW, test MIDI 2.0 or evaluate any audio-to-MIDI detector. We used explicit status bytes, one track and a fixed tempo. The experiments isolate data representation; they do not promise that an arbitrary receiver will sound a particular way.

Use the private MP3 to MIDI converter