Summary
normalize_midi_messages() in pedalboard/midi_utils.py silently discards any MIDI message it cannot recognise — wrong tuple length, bare bytes without a timestamp, unknown object type — instead of raising an error. The caller receives a shorter output list with zero indication that events were lost.
Steps to reproduce
from pedalboard.midi_utils import normalize_midi_messages
messages = [
(bytes([0x90, 60, 64]), 0.0), # ✅ valid note-on
(bytes([0x90, 62, 64]),), # ❌ 1-tuple — timestamp accidentally omitted
(bytes([0x80, 60, 64]), 1.0), # ✅ valid note-off
]
result = normalize_midi_messages(messages)
print(len(result)) # prints 2 — the bad message was silently dropped
Expected behaviour
A TypeError raised at the point of the malformed message, including the index and the offending value so the caller can fix their data.
Actual behaviour
The malformed message is dropped. No exception is raised. result silently contains 2 entries instead of 3.
Root cause
The loop uses if / elif with no else branch:
for message in _input:
if hasattr(message, "bytes") and hasattr(message, "time"):
output.append(...)
elif (isinstance(message, tuple) or isinstance(message, list)) and len(message) == 2:
...
output.append(...)
# ← anything else falls through silently
Impact
- Silent data loss that is impossible to detect without manually diffing input and output lengths.
- Affects any caller that passes a list containing even a single malformed element (1-tuple with missing timestamp, 3-tuple with extra field, raw
bytes, bare integer, None, etc.).
- Produces incorrect audio output with no traceback to debug from.
Environment
pedalboard v0.9.23 (current master)
- Python 3.10+
- Reproducible on all platforms
Summary
normalize_midi_messages()inpedalboard/midi_utils.pysilently discards any MIDI message it cannot recognise — wrong tuple length, bare bytes without a timestamp, unknown object type — instead of raising an error. The caller receives a shorter output list with zero indication that events were lost.Steps to reproduce
Expected behaviour
A
TypeErrorraised at the point of the malformed message, including the index and the offending value so the caller can fix their data.Actual behaviour
The malformed message is dropped. No exception is raised.
resultsilently contains 2 entries instead of 3.Root cause
The loop uses
if / elifwith noelsebranch:Impact
bytes, bare integer,None, etc.).Environment
pedalboardv0.9.23 (currentmaster)