-- $NWCUT$CONFIG: FileText $ nwcut.setlevel(2) nwcut.status = nwcut.const.rc_Report nwcut.status = nwcut.const.rc_Succes local MAXMIDINOTE = 128 local progname = 'SplitStaff.lua' local HelpMsg = [[ This tool evaluates the current staff and its notes are copied in "midi_xx-staves" added at the end of the score. Enharmonic notations will be collected in the same staff. This tool can be executed several times To undo, just deleted the "midi_xx-staves" which were added at the end of the score. Bart & Flurmy (08-2019) ]] -------------------------------------- local InstrumentsTable = { -- 13..87 -- XG [13] = 'XG Surdo Muted', [14] = 'XG Surdo Open', [15] = 'XG Hi Q', [16] = 'XG Whip Slap', [17] = 'XG Scrath Push', [18] = 'XG Scrath Pull', [19] = 'XG Finger Snap', [20] = 'XG Click', [21] = 'XG Metro Clock', [22] = 'XG Metro Bell', [23] = 'XG Sequencer Click Low', [24] = 'XG Sequencer Click High', [25] = 'XG Brush Tap', [26] = 'XG Brush Swirl Low', -- GM2 & GS [27] = 'GM2-GS High Q', -- 'Brush Slap' { XG } [28] = 'GM2-GS Slap', -- 'Brush Swirl High' { XG } [29] = 'GM2-GS Scratch Push', -- 'Snare Roll' { XG } [30] = 'GM2-GS Scratch Pull', -- 'Castanet' { XG } [31] = 'GM2-GS Sticks', -- 'Low Snare' { XG } [32] = 'GM2-GS Square Click', -- 'Sticks' { XG } [33] = 'GM2-GS Metronome Click', -- 'Low Bass Drum' { XG } [34] = 'GM2-GS Metronome Bell', -- 'Open Rim' { XG } -- GM [35] = 'Acoustic Bass Drum', [36] = 'Bass Drum', [37] = 'Side Stick', [38] = 'Acoustic Snare', -- 'Brush Tap' { GM2 Brush Set } [39] = 'Hand Clap', -- 'Brush Slap' { GM2 Brush Set } [40] = 'Electric Snare', -- 'Brush Swirl' { GM2 Brush Set } [41] = 'Low Floor Tom', [42] = 'Closed Hi Hat', [43] = 'High Floor Tom', [44] = 'Pedal Hi-Hat', [45] = 'Low Tom', [46] = 'Open Hi-Hat', [47] = 'Low-Mid Tom', [48] = 'Hi Mid Tom', [49] = 'Crash Cymbal 1', [50] = 'High Tom', [51] = 'Ride Cymbal 1', [52] = 'Chinese Cymbal', [53] = 'Ride Bell', [54] = 'Tambourine', [55] = 'Splash Cymbal', [56] = 'Cowbell', [57] = 'Crash Cymbal 2', [58] = 'Vibraslap', [59] = 'Ride Cymbal 2', [60] = 'Hi Bongo', [61] = 'Low Bongo', [62] = 'Mute Hi Conga', [63] = 'Open Hi Conga', [64] = 'Low Conga', [65] = 'High Timbale', [66] = 'Low Timbale', [67] = 'High Agogo', [68] = 'Low Agogo', [69] = 'Cabasa', [70] = 'Maracas', [71] = 'Short Whistle', [72] = 'Long Whistle', [73] = 'Short Guiro', [74] = 'Long Guiro', [75] = 'Claves', [76] = 'Hi Wood Block', [77] = 'Low Wood Block', [78] = 'Mute Cuica', [79] = 'Open Cuica', [80] = 'Mute Triangle', [81] = 'Open Triangle', -- GM2 - XG - GS [82] = 'GM2-XG-GS Shaker', [83] = 'GM2-XG-GS Jingle Bells', [84] = 'GM2-XG-GS Bell Tree', -- GM2 - GS [85] = 'GM2-GS Castanets', [86] = 'GM2-GS Mute Surdo', [87] = 'GM2-GS Open Surdo' } -------------------------------------- -- function modified2rest -------------------------------------- local function modified2rest (p_item) lv_item = nwcItem.new("|Rest") lv_item:Provide("Dur",p_item.Opts.Dur) lv_item:Provide("Visibility","Never") return lv_item end--function -------------------------------------- -- function modified2note -------------------------------------- local function modified2note (p_item,p_pos) lv_item = nwcItem.new(tostring(p_item)) if p_item:Is("Chord") or p_item:Is("RestChord") then lv_item = nwcItem.new("|Note"); lv_item:Provide("Pos",p_pos) ; lv_item:Provide("Dur",p_item.Opts.Dur); end--if return lv_item end--function -------------------------------------- -- Main processing ------------------- -------------------------------------- assert(nwcut.getprop('Mode') == nwcut.const.mode_FileText, "Input type must be 'File Text' - adapt user tool config") assert(nwcut.getprop('ReturnMode') == nwcut.const.mode_FileText, "Under 'Options', check 'Returns File Text'") ASI = 0 -- Active Staff Parameters CSI = 0 -- Current Staff Parameters CloneStaff = {} -- for duplicated active staff MidiStaff = {} -- for gathering notes in staves to be added Processed = {} InUse = {} ; for i=1,MAXMIDINOTE,1 do InUse[i]=0 ; end--for i playContext = nwcPlayContext.new() for item in nwcut.items() do print(item) playContext:put(item) if item:Is('Editor') then ASI = item.Opts.ActiveStaff + 0 ; end--if if item:Is('AddStaff') then CSI = CSI + 1 ; end--if if CSI == ASI then table.insert(CloneStaff,item) -- only duration items can split (grace notes ignored) if item:HasDuration() then for p in item:AllNotePositions() do lv_midi = playContext:GetNoteMidiPitch(p) if lv_midi > 0 and lv_midi < MAXMIDINOTE then InUse[lv_midi] = 1 else InUse[MAXMIDINOTE] = 1 end--if end--for p end--if end--if end--for item -------------------------------------- for k = 1,MAXMIDINOTE,1 do if InUse[k] == 1 then MidiStaff[k] = {} if k == MAXMIDINOTE then lv_staffname = "Percussion_overflow" else lv_staffname = "Midi_"..k; end lv_item = nwcItem.new("|AddStaff"); lv_item:Provide("Name",lv_staffname); lv_item:Provide("Group","MidiStaff"); if (k >= 13) and (k <= 87) then lv_item:Provide("Label",InstrumentsTable[k]); else lv_item:Provide("Label",lv_staffname); end table.insert (MidiStaff[k],lv_item); lv_item = nwcItem.new("|StaffProperties") ; lv_item:Provide("Color","Default") ; lv_item:Provide("BoundaryTop","10") ; table.insert (MidiStaff[k],lv_item) ; lv_item = nwcItem.new("|StaffProperties") ; lv_item:Provide("Device","0") ; lv_item:Provide("Channel","10") ; table.insert (MidiStaff[k],lv_item) ; lv_item = nwcItem.new("|StaffInstrument") ; lv_item:Provide("DynVel","10,30,45,60,75,92,108,127") ; lv_item:Provide("Trans","0") ; table.insert (MidiStaff[k],lv_item) ; end--if end--for k -------------------------------------- -- clone notes in corresponding midi-note tables for k = 1,#CloneStaff,1 do item = CloneStaff[k] playContext:put(item) for n,v in pairs(MidiStaff) do Processed[n] = 0 ; end--for n,v -- only duration items can split (grace notes ignored) if item:HasDuration() then if (item:Is("Rest") or item:Is("RestMultiBar")) then for n,v in pairs(MidiStaff) do table.insert (MidiStaff[n],item) ; Processed[n] = 1 end--for n,v end--if for p in item:AllNotePositions() do lv_midi = playContext:GetNoteMidiPitch(p) for n,v in pairs(MidiStaff) do if n == lv_midi then table.insert (MidiStaff[n],modified2note(item,p)) ; Processed[n] = 1 ;end--if end--for n,v end--for p else for n,v in pairs(MidiStaff) do Processed[n] = 1 ; if (not (item:Is("AddStaff")) and not (item:Is("StaffProperties")) and not (item:Is("StaffInstrument")) ) then table.insert (MidiStaff[n],item) ; end--if end--for n,v end--if for n,v in pairs(MidiStaff) do if Processed[n] == 0 then table.insert (MidiStaff[n],modified2rest(item)) ; end--if end--for n,v end--for k -------------------------------------- for n,v in pairs(MidiStaff) do for z = 1,#v,1 do print(v[z]) end--for z end--for n,v