Here are some detailed descriptions and pseudo-code for multi-item MIDI editing.
New functionality required
Method to easily select and change which items are visible in MIDI Editor.
Method to easily select and change which items are active for editing in MIDI Editor. Notes/events of inactive visible items are grayed out and locked.
Possible actions/options/mousemodifiers/menus/toolbarbuttons for item visibility and edit activation:
- all
- all on selected tracks
- all on last touched track
- selected
- last touched
Item Border Lock option to disbale automatic extending of items.
Multi Track Edit option to allow free editing of active items on different tracks. If this is disabled, then all editing actions are directed to a single track.
Insert Note
Methods to insert notes
- Double-click piano-roll (default action)
- Live recording. Some special rules are needed for inserting notes while recording. -> Definition of live recording behaviour is not included here.
- Step recording (function keys or MIDI input)
- Action (toolbar button, keyboard shortcut, mouse modifiers)
Behaviour
SL = Start Location (note on)
EL = End Location (note off)
IBL = Item Border Lock
LTI = Last Touched Item
MTE = Multi Track Edit
NISD = nearest item search distance (How far to search for nearest item. NISD should be configurable in the MIDI editor)
Only final location of note is used to define SL and EL. Intermediate note positions and lengths during insert operation (mouse drag) are not used.
Code:
insertNoteAction()
targetItem = findNearestItem(noteToBeInserted)
if targetItem == null
targetItem = createNewItem(location of noteToBeInserted)
insertNote(noteToBeInserted, targetItem)
procedure insertNote(NOTE, ITEM)
if (NOTE.SL is inside ITEM) and (NOTE.EL is inside ITEM)
insert NOTE to ITEM
else if (NOTE.SL is inside item)
if IBL == enabled
shorten NOTE (set NOTE.EL to end of ITEM)
insert NOTE to ITEM
else
extend end of ITEM to NOTE.EL
insert NOTE to ITEM
else if (NOTE.EL is inside ITEM)
if IBL == enabled
discard NOTE
else
extend start of ITEM to NOTE.SL
insert NOTE to ITEM
else // start and end of note outside item
if IBL == enabled
discard NOTE
else if (NOTE.SL is after ITEM)
extend end of ITEM to NOTE.EL
insert NOTE to ITEM
else if (NOTE.EL is before ITEM)
extend start of ITEM to NOTE.SL
insert NOTE to ITEM
else // note spans over item
extend end of ITEM to NOTE.EL
extend start of ITEM to NOTE.SL
insert NOTE to ITEM
function findNearestItem(NOTE) return item
if MTE == enabled
searchArea = all active items on active tracks
else
searchArea = all active items on LTI.track
if NOTE.SL is inside LTI
return LTI
else
itemlist = find items that have NOTE.SL inside them
if itemlist.length == 0
itemlist = find nearest item start or end within NISD
if itemlist.length == 0
return null
else if itemlist.length == 1
return itemlist[0]
else // multiple items within same distance
// continue search
else if itemlist.length == 1
return itemlist[0]
else // NOTE.SL is inside multiple items
itemlist = find item from the itemlist that has earliest start
if itemlist.length == 1
return itemlist[0]
else // multiple items with same start location
//continue search
itemlist2 = find item in itemlist that has notes nearest NOTE.pitch (search within 1 octave)
if itemlist2.length == 0
return itemlist[0] // Stop searching. Just return the first item from itemlist.
else if itemlist2.length == 1
return itemlist2[0]
else // multiple items with notes in the same pitch distance
return itemlist2[0] // Stop searching. Just return the first item from itemlist2.
//TODO: Add multi track search cases. Prefer items on same track as LTI.
Copy/Cut
Store Source Item information of each copied/cut note to clipboard.
Paste
Add copied/cut notes from clipboard to items using same rules as in insert note action.
Options for paste target item behaviour:
1. Last touched item. (default)
- All notes will be pasted to the same item.
- Cursor location is used as reference point when searching the nearest item.
2. Source item.
- Paste each note separately so that each note's source item is used as the last touched item when searching the target item for that note.
Move
Same item target behaviour as in Paste operation except that "Source item" shoud be the default target.
Ctrl+drag copy
Same item target behaviour as in Paste operation except that "Source item" shoud be the default target.
Change note length
Extending note length beyond item end will extend the item if IBL is not enabled
Select note(s)
Change Last Touched Item.
What is the Last Touched Item if notes in different items are selected.?
Move cursor
Change Last Touched Item to the item under cursor.
If there is no item under cursor then do not change Last Touched Item.
Record
TBD
CC events, Program changes, etc.
Inserting works like inserting notes (no length -> event start location == event end location)
Any other actions to be considered in detail?
jnif