import io def transpose_midi(midi_bytes: bytes | None) -> bytes | None: """ Transpose all MIDI notes by +2 semitones (clamped to 0-127). Args: midi_bytes: Raw MIDI file bytes from the frontend Returns: Transposed MIDI file bytes """ if midi_bytes is None: return None try: import mido # Parse the MIDI file from bytes midi_file = mido.MidiFile(file=io.BytesIO(midi_bytes)) # Create a new MIDI file with transposed notes new_midi = mido.MidiFile(ticks_per_beat=midi_file.ticks_per_beat) for track in midi_file.tracks: new_track = mido.MidiTrack() for msg in track: if msg.type in ('note_on', 'note_off'): # Transpose by +2 semitones, clamped to valid MIDI range new_note = min(127, max(0, msg.note + 2)) new_msg = msg.copy(note=new_note) new_track.append(new_msg) else: # Copy non-note messages as-is new_track.append(msg.copy()) new_midi.tracks.append(new_track) # Write to bytes output = io.BytesIO() new_midi.save(file=output) return output.getvalue() except Exception as e: print(f"Error processing MIDI: {e}") return midi_bytes # Return original on error