The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

midiedit - Edits a MIDI file

SYNOPSIS

 midiedit filename.mid       # uses the new Curses app, with sound
 midiedit -o 128:0 filename.mid    # uses ALSA port 128:0 as synth
 midiedit -d filename.mid  # uses your EDITOR on a MIDI::Perl dump
 midiedit -v               # prints the Version number

DESCRIPTION

Midiedit is a MIDI-file editor which now (since version 1.3) has a choice of two user-interface modes.

In the new default mode, it uses Curses to offer a purpose-designed user-interface and MIDI::ALSA to play the notes to your synth.

In the older lower-tech mode, it uses your favourite text-editor to edit the human-readable text-format provided by MIDI::Perl's $opus->dump function.

CURSES MODE

In the Curses mode, which is the default, midiedit edits a MIDI file with a purpose-designed user-interface which re-uses some keystrokes inspired by vi: for example, i=insert m=mark k/Up/j/Down=+-1event u=undo ^R=redo /=find ?=reversefind n=findnext N=findprevious w=write q=quit .=last_edit_again, plus a few others, e.g.: e=edit_event, D=delete_event, R=define_a_range, r=operate_on_that_range, f=file_operations, z=all_sounds_off, and ^H/Backspace=return_where_you_were_before_the_Find

As in mplayer, the spacebar toggles between Play and Pause, the Left and Right arrow keys move by 1 second, the Up and Down arrow keys move by 10 seconds, and the Home and End keys move to the start and end of the file, and [ and ] or { and } change the Replay-speed.

The available keystrokes are displayed in the bottom four lines of the screen.

The events are displayed in note-form, i.e. with a start-time and a duration. There are no separate note_on and note_off events, which solves the matching-ons-and-offs problem. All times are displayed in milliseconds.

The start-times can be displayed either as incremental times (since the previous event), or as absolute times (since the beginning). The + and - keys switch between these modes; the default mode is incremental. The behaviour of Edit, Insert and Delete adapts to the display-mode; for example with incremental times, deleting a note shortens the whole file by the deleted millisecond increment, but with absolute times deleting a note just removes that note and leaves the duration of the whole file unchanged.

Since version 3.0, /=find allows search criteria such as >62 or <25 or >=60 or <=72 or !=9 or >59&<73 which, when combined with .=last_edit_again make it easier to do things like "move that high bit of the piano solo into a different channel".

Since version 4.5, a Range can be defined by pressing upper-case R once at each end of the desired range. Once defined, the Range can be operated on, using a lower-case r, in various ways ( c=compand d=delete m=mixer p=pitch q=quantise r=repeat t=tempo v=vol w=write_to_file ) largely modelled on the corresponding midisox effects. For details of what the compand effect does, see: midisox --help-effect=compand

Since version 7.7, after a Find (/, ?, n or N), ctrl-H or Backspace returns you to where you were before the Find.

You can specify your choice of synth at the command line with a -o 128:0 option, or else with the ALSA_OUTPUT_PORTS environment variable. The special value -o 0 silences the output (e.g. you might want to edit something while listening to something else). Since Version 2.4, you may supply a comma-separated list of ports, e.g. -o 20,128:1

As well as the MIDI-Perl CPAN module, this mode also uses the Curses module for the user-interface, and the MIDI::ALSA module to play the file to your synth.

DUMP MODE

In the older, low-tech -d mode, midiedit edits a MIDI file in the human-readable text-format provided by MIDI::Perl's $opus->dump function.

The text format representing the MIDI is executable Perl source, so as you edit, you should preserve valid Perl syntax. If the edited file has syntax errors, you will be asked if you want to re-edit it, and if you reply No then the original file will not get over-written.

If you've changed the text, and then decide you want to quit without overwriting the MIDI file, then you have to deliberately mess up the Perl syntax (e.g. make sure the brackets are unbalanced).

Assuming you've installed MIDI::Perl, then perldoc MIDI::Event should document the format in which the various MIDI-events are represented. They are represented with incremental times (in ticks) and with separate note_on and note_off events, so you have to keep track of matching note_ons and note_offs.

CHANGES

 7.8 20160701, -d with multi-track midi-files resets ticks to 0 each track
 7.7 20151106, after a Find, ctrl-H or Backspace returns to where you were
 7.6 20151105, finding a marker matches on a substring
 7.5 20151031, like 7.4, except it also works for multiple un-do's
 7.4 20151030, 'u' leaves Ievent as before last edit, not after the previous
 7.3 20151008, edit_again now works for markers and text events
 7.2 20151003, fix bug which introduced undefined events
 7.1 20151002, event2str defends against unprintable chars in text events
 7.0 20150513, displays also Metronome Click and Metronome Bell
 6.9 20150411, all_sounds_off also turns all notes off
 6.8 20150223, display channel_after_touch column-aligned as cha_aftertouch
 6.7 20141201, skip refreshes if <10ms to next event
 6.6 20141104, removed misleading 'm=mark' help-text
 6.5 20140703, controller_change events display controller-names
 6.4 20140702, display_events patch_change events display GM patch-names
 6.3 20140612, ask_filename does backspace, range_write won't overwrite
 6.2 20140611, range_write appends marker to represent time-to-next-note
 6.2 20140611, filename-completion gets its trailing space stripped
 6.2 20140611, File Include works, corresponding to range_write
 6.1 20140610, range_write no longer has big pause at the start
 6.0 20130404, display_events remembers the Ped/* state by channel
 5.9 20130323, find_marker with null text finds the next marker
 5.8 20130321, bug fixed in range_quantise effect
 5.7 20130302, range_repeat moves cursor down if it lay after RangeEnd
 5.6 20130301, range_delete moves cursor up if it lay after RangeEnd
 5.5 20130218, u=undo and ^R=redo seem to work
 5.4 20121028, replay_setup outputs bankchange before the patchchange
 5.3 20121001, replay_setup (hence time_travel) works for- and backward
 5.2 20120930, KEY_UP uses event_travel() to cope with dt=0
 5.1 20120930, works with MIDI::ALSA 1.15; PolyOn=127 fixed
 5.0 20120916, edit_event uses p=pitch not n=note
 4.9 20120910, f=file_menu: f=fork n=new s=save q=quit
 4.8 20120908, KEY_UP uses time_travel(), so as to get the right patch
 4.7 20120903, display_events clears lines after EOF, range_delete
 4.6 20120628, rw = range_write now works
 4.5 20120624, R and r range-operations largely work
 4.4 20120613, event-fields correctly displayed also in edit-mode
 4.3 20120612, consistent redo and undo; find_event uses time_travel
 4.2 20120609, can search for long gaps or short gaps
 4.1 20120608, becomes Paused at EOF; channel,note in bold if note-on
 4.0 20120604, j,k keys also available in Edit Mode
 3.9 20120604, '.'=repeat also offered in Edit Mode, if applicable
 3.8 20120604, find offers s=short_gap, l=long_gap and t=time (==go_to)
 3.7 20120604, '.' repeats also edit of dt if IncrementalTimes
 3.6 20120529, tracks shorter than screen-height don't get extended
 3.5 20120527, add g = go_to()
 3.4 20120525, displays most recent Ped and *
 3.3 20120510, displays currently on notes
 3.2 20120502, can now insert bank_change (= 2 control_changes)
 3.1 20120326,  # ] and [ or } and { change the ReplaySpeed
 3.0 20120110, find_match gives find >5&<15&!=9 searches
 2.9 20120108, '.' repeats last edit (if event-types match)
 2.8 20111126, find works if cha=0 or value=0
 2.7 20111107, edit_event dialogue updated as changes are made
 2.6 20111103, use the new MIDI-ALSA 1.11 to handle portnames
 2.5 20111029, column-titles better reflect the event-types
 2.4 20111028, OutputPort can be a comma-separated list
 2.3 20111027, merges multiple tracks; z=all_sounds_off
 2.2 20111027, entering PAUSED mode causes all_sounds_off
 2.1 20111027, displays note-string in main window
 2.0 20111027, doesn't try to connect if $OutputPort undefined or "0"
 1.9 20111022, Phaser Depth and Poly On displayed correctly
 1.8 20111021, displays notes with ~ and _ correctly
 1.7 20110926, handles non-millisec-tick files correctly
 1.6 20110917, display_this_event shows changes as they are made
 1.5 20110910, Up/Down in edit-mode play the new note
 1.4 20110909, in edit mode, Up and Down don't leave edit-mode
 1.3 20110820, the new Curses app is the default
 1.2 20110708, displays helpful comments
 1.1 20060728, first working version

AUTHOR

Peter J Billam http://www.pjb.com.au/comp/contact.html

CREDITS

Based on the MIDI::Perl and Curses and MIDI::ALSA CPAN modules. The non-Curses mode also uses Peter Billam's Term::Clui CPAN module.

SEE ALSO

 http://search.cpan.org/perldoc?MIDI
 http://search.cpan.org/perldoc?Curses
 http://search.cpan.org/perldoc?MIDI::ALSA
 http://search.cpan.org/perldoc?Term::Clui
 http://www.pjb.com.au/muscript
 http://www.pjb.com.au/midi