Old 12-29-2024, 10:05 AM   #1
krahosk
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,492
Default req: script for MIDI guitar chords via user input

Is it possible to have a script that does the following:

1.
- Enter the guitar strings/fret chord form in the following format: 1 3 3 2 1 1 or X X X 2 1 1
- the chord would be inserted in a MIDI item as notes
- the string number would be assigned to a MIDI channel (1 to 6) as an option
- note value attributed at the beginning with a backslash character ex. 8/ X 3 2 0 1 X or 1/ X 3 2 0 1 X (eighth = 8/ whole = 1/)

2.
- Enter the guitar strings/fret in the following format: 1-2-6-9-0-3-6-2-6-2
- the individual numbers would be inserted in a MIDI item as individual notes one after the other
- MIDI channel would always be 1 in that case
- note value attributed at the beginning with a backslash character ex. 4/ 6-3-7-3-5-7 or 2/ 8-4-6-645-2-12-9-5-3 (quarter= 4/ half= 2/)

This script would be extremely useful for guitar players like me to enter guitar chords and notes in Reaper.

Much obliged if that is something that can be easily done!

Last edited by krahosk; 12-29-2024 at 10:18 AM.
krahosk is offline   Reply With Quote
Old 12-29-2024, 12:22 PM   #2
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

I'm not a guitarist, so I'm not sure if the below will give you the right result...
But it's a start ;o)



Code:
local r=reaper
local ctx=r.ImGui_CreateContext('TK_GTR_COMBINED')
local font=r.ImGui_CreateFont('Arial',14)
r.ImGui_Attach(ctx,font)
local input_sequence=""
local input_chord=""
local selected_duration="4"
local selected_string=1
local base_notes={40,45,50,55,59,64}
local string_names={"E (Low)","A","D","G","B","E (High)"}
function CreateMIDIItem()
    local track=r.GetSelectedTrack(0,0)
    if not track then return end
    local cursor_pos=r.GetCursorPosition()
    local ppq=960
    local beats=4/tonumber(selected_duration)
    local item=r.CreateNewMIDIItemInProj(track,cursor_pos,cursor_pos+beats/2)
    local take=r.GetActiveTake(item)
    return item,take,ppq*beats
end
function InsertSequence(take,notes,note_length)
    local base_note=base_notes[selected_string]
    local position=0
    local idx=0
    local note_count=0
    for _ in notes:gmatch("([^-]+)")do note_count=note_count+1 end
    local item=r.GetMediaItemTake_Item(take)
    r.SetMediaItemInfo_Value(item,"D_LENGTH",(note_length*note_count)/960/2)
    r.SetMediaItemInfo_Value(item,"B_LOOPSRC",0)
    r.SetMediaItemInfo_Value(item,"B_LOOP",0)
    for note in notes:gmatch("([^-]+)")do
        local midi_note=base_note+tonumber(note)
        r.MIDI_InsertNote(take,false,false,position,note_length,0,midi_note,100,false)
        local retval,selected,muted,startppq,endppq,chan,pitch,vel=r.MIDI_GetNote(take,idx)
        if retval then r.MIDI_SetNote(take,idx,false,false,position,position+note_length,0,midi_note,100,true)end
        position=position+note_length
        idx=idx+1
    end
    r.MIDI_Sort(take)
end
function InsertChord(take,frets,note_length)
    for string_num,fret in ipairs(frets)do
        if fret~="X"then
            local note=base_notes[string_num]+tonumber(fret)
            r.MIDI_InsertNote(take,false,false,0,note_length,string_num-1,note,100,false)
        end
    end
    r.MIDI_Sort(take)
end
function MainLoop()
    r.ImGui_SetNextWindowSize(ctx,400,400)
    local window_flags=r.ImGui_WindowFlags_NoTitleBar()|r.ImGui_WindowFlags_NoResize()
    r.ImGui_PushStyleVar(ctx,r.ImGui_StyleVar_WindowRounding(),12.0)
    local visible,open=r.ImGui_Begin(ctx,'Guitar MIDI Input',true,window_flags)
    if visible then
        r.ImGui_PushFont(ctx,font)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_WindowBg(),0x000000FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_Button(),0x1A1A1AFF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_ButtonHovered(),0x333333FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_ButtonActive(),0x404040FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_FrameBg(),0x1A1A1AFF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_FrameBgHovered(),0x333333FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_FrameBgActive(),0x404040FF)
        r.ImGui_PushStyleVar(ctx,r.ImGui_StyleVar_FrameRounding(),6.0)
        r.ImGui_Text(ctx,"Note Duration:")
        local active_color = 0xFF0000FF
        if selected_duration == "1" then
            r.ImGui_PushStyleColor(ctx, r.ImGui_Col_Button(), active_color)
            if r.ImGui_Button(ctx, "1/1") then selected_duration = "1" end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx, "1/1") then selected_duration = "1" end
        end
        r.ImGui_SameLine(ctx)
        if selected_duration == "2" then
            r.ImGui_PushStyleColor(ctx, r.ImGui_Col_Button(), active_color)
            if r.ImGui_Button(ctx, "1/2") then selected_duration = "2" end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx, "1/2") then selected_duration = "2" end
        end
        r.ImGui_SameLine(ctx)
        if selected_duration == "4" then
            r.ImGui_PushStyleColor(ctx, r.ImGui_Col_Button(), active_color)
            if r.ImGui_Button(ctx, "1/4") then selected_duration = "4" end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx, "1/4") then selected_duration = "4" end
        end
        r.ImGui_SameLine(ctx)
        if selected_duration == "8" then
            r.ImGui_PushStyleColor(ctx, r.ImGui_Col_Button(), active_color)
            if r.ImGui_Button(ctx, "1/8") then selected_duration = "8" end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx, "1/8") then selected_duration = "8" end
        end
        r.ImGui_Spacing(ctx)
        r.ImGui_Separator(ctx)
        r.ImGui_Spacing(ctx)
        r.ImGui_Text(ctx,"Select base string:")
        if r.ImGui_BeginCombo(ctx,"##stringselect",string_names[selected_string])then
            for i,name in ipairs(string_names)do
                if r.ImGui_Selectable(ctx,name,selected_string==i)then selected_string=i end
            end
            r.ImGui_EndCombo(ctx)
        end
        r.ImGui_Spacing(ctx)
        r.ImGui_Text(ctx,"Enter sequence (format: 1-2-6-9-0-3):")
        _,input_sequence=r.ImGui_InputText(ctx,"##sequence",input_sequence)
        if r.ImGui_Button(ctx,"Insert Sequence")then
            local item,take,note_length=CreateMIDIItem()
            if take then InsertSequence(take,input_sequence,note_length)end
        end
        r.ImGui_Spacing(ctx)
        r.ImGui_Separator(ctx)
        r.ImGui_Spacing(ctx)
        r.ImGui_Text(ctx,"Enter chord (format: 1 3 3 2 1 1 or X X X 2 1 1):")
        _,input_chord=r.ImGui_InputText(ctx,"##chord",input_chord)
        if r.ImGui_Button(ctx,"Insert Chord")then
            local item,take,note_length=CreateMIDIItem()
            if take then
                local frets={}
                for fret in input_chord:gmatch("%S+")do table.insert(frets,fret)end
                InsertChord(take,frets,note_length)
            end
        end
        r.ImGui_PopStyleVar(ctx,2)
        r.ImGui_PopStyleColor(ctx,7)
        r.ImGui_PopFont(ctx)
        r.ImGui_End(ctx)
    end
    if open then r.defer(MainLoop)end
end
r.defer(MainLoop)
Hopefully this is somewhat what you are looking for, otherwise please let me know. 😁

Last edited by Touristkiller; 12-29-2024 at 02:03 PM.
Touristkiller is offline   Reply With Quote
Old 12-29-2024, 02:09 PM   #3
krahosk
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,492
Default

Quote:
Originally Posted by Touristkiller View Post
I'm not a guitarist, so I'm not sure if the below will give you the right result...
But it's a start ;o)
Hopefully this is somewhat what you are looking for, otherwise please let me know. 😁

Wow! Thank you so much. It seems to be doing what I need. I will give more feedback later on. Thanks again!

Last edited by krahosk; 12-29-2024 at 02:16 PM.
krahosk is offline   Reply With Quote
Old 12-29-2024, 02:11 PM   #4
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Yep... let me know what else might need to be done and what is and isn't correct. 👍
Is the input correct as you want it or should it perhaps be different?

Extended version...


Code:
local r=reaper
local ctx=r.ImGui_CreateContext('TK_GTR_COMBINED')
local font=r.ImGui_CreateFont('Arial',12)
r.ImGui_Attach(ctx,font)
local input_sequence=""
local input_chord=""
local selected_duration="4"
local selected_string=1
local base_notes={64,59,55,50,45,40}
local string_names={"E (High)","B","G","D","A","E (Low)"}
local tunings={
    ["Standard (EADGBE)"]={64,59,55,50,45,40},
    ["Drop D (DADGBE)"]={64,59,55,50,45,38},
    ["Open G (DGDGBD)"]={62,59,55,50,43,38},
    ["Open D (DADF#AD)"]={62,57,54,50,45,38},
    ["DADGAD"]={62,57,55,50,45,38}
}
local selected_tuning="Standard (EADGBE)"
base_notes=tunings[selected_tuning]
function CreateMIDIItem()
    local track=r.GetSelectedTrack(0,0)
    if not track then return end
    local cursor_pos=r.GetCursorPosition()
    local ppq=960
    local beats=4/tonumber(selected_duration)
    local item=r.CreateNewMIDIItemInProj(track,cursor_pos,cursor_pos+beats/2)
    local take=r.GetActiveTake(item)
    return item,take,ppq*beats
end
function InsertSequence(take,notes,note_length)
    local base_note=base_notes[selected_string]
    local position=0
    local idx=0
    local note_count=0
    for _ in notes:gmatch("([^-]+)")do note_count=note_count+1 end
    local item=r.GetMediaItemTake_Item(take)
    r.SetMediaItemInfo_Value(item,"D_LENGTH",(note_length*note_count)/960/2)
    r.SetMediaItemInfo_Value(item,"B_LOOPSRC",0)
    r.SetMediaItemInfo_Value(item,"B_LOOP",0)
    for note in notes:gmatch("([^-]+)")do
        local midi_note=base_note+tonumber(note)
        r.MIDI_InsertNote(take,false,false,position,note_length,0,midi_note,100,false)
        local retval,selected,muted,startppq,endppq,chan,pitch,vel=r.MIDI_GetNote(take,idx)
        if retval then r.MIDI_SetNote(take,idx,false,false,position,position+note_length,0,midi_note,100,true)end
        position=position+note_length
        idx=idx+1
    end
    r.MIDI_Sort(take)
end
function GetNoteName(midi_note)
    local notes={"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"}
    local note_index=(midi_note%12)+1
    return notes[note_index]
end
function InsertChord(take,frets,note_length)
    local reversed_frets={}
    for i=#frets,1,-1 do
        reversed_frets[#frets-i+1]=frets[i]
    end
    for string_num,fret in ipairs(reversed_frets)do
        if fret~="X"then
            local note=base_notes[string_num]+tonumber(fret)
            r.MIDI_InsertNote(take,false,false,0,note_length,string_num-1,note,100,false)
        end
    end
    r.MIDI_Sort(take)
end
function HandleFretboardClick(ctx,startX,startY,width,height,isChord,rightClick)
    local mouseX,mouseY=r.ImGui_GetMousePos(ctx)
    local winX,winY=r.ImGui_GetWindowPos(ctx)
    local num_strings=6
    local num_frets=12
    local string_spacing=height/(num_strings-1)
    local fret_spacing=width/num_frets
    mouseX=mouseX-(winX+startX)
    mouseY=mouseY-(winY+startY)
    if mouseX>=0 and mouseX<=width+20 and mouseY>=0 and mouseY<=height+20 then
        local raw_fret=mouseX/fret_spacing
        local fret=math.min(math.floor(raw_fret),num_frets)
        local string_num=math.min(math.floor(mouseY/string_spacing),num_strings-1)
        if string_num>=num_strings then
            string_num=num_strings-1
        end
        if isChord then
            local num_frets=5
            local string_spacing=width/(num_strings-1)
            local fret_spacing=height/num_frets
            local string_num=math.floor(mouseX/string_spacing)+1
            local fret=math.floor(mouseY/fret_spacing)
            if fret>=0 and fret<=num_frets and string_num>=1 and string_num<=num_strings then
                local frets={"X","X","X","X","X","X"}
                local i=1
                for existing_fret in input_chord:gmatch("%S+")do
                    frets[i]=existing_fret
                    i=i+1
                end
                frets[string_num]=rightClick and"X"or tostring(fret)
                input_chord=table.concat(frets," ")
            end
        else
            if rightClick then
                local notes={}
                local clickX=mouseX
                local clickY=mouseY
                local radius=12
                local i=1
                for note in input_sequence:gmatch("([^-]+)")do
                    local noteX=(tonumber(note)*fret_spacing)+(fret_spacing/2)
                    local noteY=string_num*string_spacing
                    local distance=math.sqrt((clickX-noteX)^2+(clickY-noteY)^2)
                    if distance>radius then
                        table.insert(notes,note)
                    end
                    i=i+1
                end
                input_sequence=table.concat(notes,"-")
            else
                if input_sequence==""then
                    input_sequence=tostring(fret)
                else
                    input_sequence=input_sequence.."-"..tostring(fret)
                end
            end
            selected_string=string_num+1
        end
        return true
    end
    return false
end
function DrawFretboard(ctx,startX,startY,width,height)
    local draw_list=r.ImGui_GetWindowDrawList(ctx)
    local winX,winY=r.ImGui_GetWindowPos(ctx)
    startX=winX+startX
    startY=winY+startY
    local num_strings=6
    local num_frets=12
    local string_spacing=height/(num_strings-1)
    local fret_spacing=width/num_frets
    for i=0,num_strings-1 do
        local y=startY+(i*string_spacing)
        r.ImGui_DrawList_AddLine(draw_list,startX,y,startX+width,y,0xFFFFFFFF)
        local note_name=GetNoteName(base_notes[i+1])
        r.ImGui_DrawList_AddText(draw_list,startX-25,y-6,0xFFFFFFFF,note_name)
    end
    for i=0,num_frets do
        local x=startX+(i*fret_spacing)
        r.ImGui_DrawList_AddLine(draw_list,x,startY,x,startY+height,0xFFFFFFFF)
        r.ImGui_DrawList_AddText(draw_list,x-3,startY+height+5,0xFFFFFFFF,tostring(i))
    end
    if r.ImGui_IsMouseClicked(ctx,0)then
        HandleFretboardClick(ctx,startX-winX,startY-winY,width,height,false,false)
    elseif r.ImGui_IsMouseClicked(ctx,1)then
        HandleFretboardClick(ctx,startX-winX,startY-winY,width,height,false,true)
    end
    local notes=input_sequence:gmatch("([^-]+)")
    local string_idx=selected_string-1
    local x=0
    for fret in notes do
        local fret_num=tonumber(fret)
        if fret_num then
            local note_x=startX+(fret_num*fret_spacing)
            local note_y=startY+(string_idx*string_spacing)
            r.ImGui_DrawList_AddCircleFilled(draw_list,note_x,note_y,6,0xFF0000FF)
        end
        x=x+1
    end
end
function DrawChordboard(ctx,startX,startY,width,height)
    local draw_list=r.ImGui_GetWindowDrawList(ctx)
    local winX,winY=r.ImGui_GetWindowPos(ctx)
    startX=winX+startX+15
    startY=winY+startY
    local num_strings=6
    local num_frets=5
    local string_spacing=width/(num_strings-1)
    local fret_spacing=height/num_frets
    for i=0,num_strings-1 do
        local x=startX+(i*string_spacing)
        r.ImGui_DrawList_AddLine(draw_list,x,startY,x,startY+height,0xFFFFFFFF)
        local note_name=GetNoteName(base_notes[num_strings-i])
        r.ImGui_DrawList_AddText(draw_list,x-5,startY-20,0xFFFFFFFF,note_name)
    end
    for i=0,num_frets do
        local y=startY+(i*fret_spacing)
        r.ImGui_DrawList_AddLine(draw_list,startX,y,startX+width,y,0xFFFFFFFF)
        r.ImGui_DrawList_AddText(draw_list,startX-20,y-8,0xFFFFFFFF,tostring(i))
    end
    if r.ImGui_IsMouseClicked(ctx,0)then
        HandleFretboardClick(ctx,startX-winX,startY-winY,width,height,true,false)
    elseif r.ImGui_IsMouseClicked(ctx,1)then
        HandleFretboardClick(ctx,startX-winX,startY-winY,width,height,true,true)
    end
    for string_num=1,num_strings do
        local fret=string.match(input_chord,string.rep("%S+%s",string_num-1)..("(%S+)"))
        if fret and fret~="X"then
            local fret_num=tonumber(fret)
            if fret_num then
                local x=startX+(string_num-1)*string_spacing
                local y=startY+(tonumber(fret)*fret_spacing)
                r.ImGui_DrawList_AddCircleFilled(draw_list,x,y,6,0xFF0000FF)
            end
        end
    end
end
function MainLoop()
    r.ImGui_SetNextWindowSize(ctx,360,600)
    local window_flags=r.ImGui_WindowFlags_NoTitleBar()|r.ImGui_WindowFlags_NoResize()
    r.ImGui_PushStyleVar(ctx,r.ImGui_StyleVar_WindowRounding(),12.0)
    local visible,open=r.ImGui_Begin(ctx,'Guitar MIDI Input',true,window_flags)
    if visible then
        r.ImGui_PushFont(ctx,font)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_WindowBg(),0x000000FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_Button(),0x1A1A1AFF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_ButtonHovered(),0x333333FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_ButtonActive(),0x404040FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_FrameBg(),0x1A1A1AFF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_FrameBgHovered(),0x333333FF)
        r.ImGui_PushStyleColor(ctx,r.ImGui_Col_FrameBgActive(),0x404040FF)
        r.ImGui_PushStyleVar(ctx,r.ImGui_StyleVar_FrameRounding(),6.0)
        r.ImGui_Text(ctx,"TK GUITAR 2 MIDI INPUT")
        r.ImGui_Separator(ctx)
        r.ImGui_Text(ctx,"Note Duration:")
        local active_color=0xFF0000FF
        if selected_duration=="1"then
            r.ImGui_PushStyleColor(ctx,r.ImGui_Col_Button(),active_color)
            if r.ImGui_Button(ctx,"1/1")then selected_duration="1"end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx,"1/1")then selected_duration="1"end
        end
        r.ImGui_SameLine(ctx)
        if selected_duration=="2"then
            r.ImGui_PushStyleColor(ctx,r.ImGui_Col_Button(),active_color)
            if r.ImGui_Button(ctx,"1/2")then selected_duration="2"end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx,"1/2")then selected_duration="2"end
        end
        r.ImGui_SameLine(ctx)
        if selected_duration=="4"then
            r.ImGui_PushStyleColor(ctx,r.ImGui_Col_Button(),active_color)
            if r.ImGui_Button(ctx,"1/4")then selected_duration="4"end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx,"1/4")then selected_duration="4"end
        end
        r.ImGui_SameLine(ctx)
        if selected_duration=="8"then
            r.ImGui_PushStyleColor(ctx,r.ImGui_Col_Button(),active_color)
            if r.ImGui_Button(ctx,"1/8")then selected_duration="8"end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx,"1/8")then selected_duration="8"end
        end
        r.ImGui_SameLine(ctx)
        if selected_duration=="16"then
            r.ImGui_PushStyleColor(ctx,r.ImGui_Col_Button(),active_color)
            if r.ImGui_Button(ctx,"1/16")then selected_duration="16"end
            r.ImGui_PopStyleColor(ctx)
        else
            if r.ImGui_Button(ctx,"1/16")then selected_duration="16"end
        end
        r.ImGui_Spacing(ctx)
        r.ImGui_Text(ctx,"Tuning:")
        r.ImGui_SameLine(ctx)
        if r.ImGui_BeginCombo(ctx,"##tuning",selected_tuning)then
            for tuning_name,_ in pairs(tunings)do
                if r.ImGui_Selectable(ctx,tuning_name,selected_tuning==tuning_name)then
                    selected_tuning=tuning_name
                    base_notes=tunings[tuning_name]
                end
            end
            r.ImGui_EndCombo(ctx)
        end
        r.ImGui_Spacing(ctx)
        r.ImGui_Text(ctx,"Transpose:")
        r.ImGui_SameLine(ctx)
        if r.ImGui_Button(ctx,"-1")then
            local new_seq={}
            for note in input_sequence:gmatch("([^-]+)")do
                local n=tonumber(note)
                if n>0 then
                    table.insert(new_seq,tostring(n-1))
                else
                    table.insert(new_seq,"0")
                end
            end
            input_sequence=table.concat(new_seq,"-")
            local new_chord={}
            for fret in input_chord:gmatch("%S+")do
                if fret~="X"then
                    local n=tonumber(fret)
                    if n>0 then
                        table.insert(new_chord,tostring(n-1))
                    else
                        table.insert(new_chord,"0")
                    end
                else
                    table.insert(new_chord,"X")
                end
            end
            input_chord=table.concat(new_chord," ")
        end
        r.ImGui_SameLine(ctx)
        if r.ImGui_Button(ctx,"+1")then
            local new_seq={}
            for note in input_sequence:gmatch("([^-]+)")do
                table.insert(new_seq,tostring(tonumber(note)+1))
            end
            input_sequence=table.concat(new_seq,"-")
            local new_chord={}
            for fret in input_chord:gmatch("%S+")do
                if fret~="X"then
                    table.insert(new_chord,tostring(tonumber(fret)+1))
                else
                    table.insert(new_chord,"X")
                end
            end
            input_chord=table.concat(new_chord," ")
        end
        r.ImGui_Spacing(ctx)
        r.ImGui_Separator(ctx)
        r.ImGui_Spacing(ctx)
        r.ImGui_Text(ctx,"Enter sequence (format: 1-2-6-9-0-3):")
        _,input_sequence=r.ImGui_InputText(ctx,"##sequence",input_sequence)
        DrawFretboard(ctx,30,r.ImGui_GetCursorPosY(ctx)+10,300,120)
        r.ImGui_Dummy(ctx,0,150)
        if r.ImGui_Button(ctx,"Insert Sequence")then
            local item,take,note_length=CreateMIDIItem()
            if take then InsertSequence(take,input_sequence,note_length)end
        end
        r.ImGui_Separator(ctx)
        r.ImGui_Spacing(ctx)
        r.ImGui_Text(ctx,"Enter chord (format: 1 3 3 2 1 1 or X X X 2 1 1):")
        _,input_chord=r.ImGui_InputText(ctx,"##chord",input_chord)
        DrawChordboard(ctx,10,r.ImGui_GetCursorPosY(ctx)+20,120,120)
        r.ImGui_Dummy(ctx,0,150)
        if r.ImGui_Button(ctx,"Insert Chord")then
            local item,take,note_length=CreateMIDIItem()
            if take then
                local frets={}
                for fret in input_chord:gmatch("%S+")do table.insert(frets,fret)end
                InsertChord(take,frets,note_length)
            end
        end
        r.ImGui_PopStyleVar(ctx,2)
        r.ImGui_PopStyleColor(ctx,7)
        r.ImGui_PopFont(ctx)
        r.ImGui_End(ctx)
    end
    if open then r.defer(MainLoop)end
end
r.defer(MainLoop)

Last edited by Touristkiller; 12-29-2024 at 08:34 PM.
Touristkiller is offline   Reply With Quote
Old 12-29-2024, 06:34 PM   #5
krahosk
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,492
Default

Amazing! Such a useful tool!
I notice that the MIDI item's length does not correspond exactly to the note value when we insert the chord. For example, for a whole note, there's an extra 8th note added, for the half note, there's an extra 16th note, and so on.
For the note sequence, it depends how many notes we enter: the MIDI item's length increased in the same ratio as cited above proportionally to the number of notes.
It would be great if the play cursor would move automatically at the end of the inserted MIDI item after inserting.
Thank you for taking the time for this. The fretboard update is something I wouldn't have dared to ask - incredible!

Last edited by krahosk; 12-29-2024 at 07:08 PM.
krahosk is offline   Reply With Quote
Old 12-29-2024, 08:40 PM   #6
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Quote:
Originally Posted by krahosk View Post
Amazing! Such a useful tool!
I notice that the MIDI item's length does not correspond exactly to the note value when we insert the chord. For example, for a whole note, there's an extra 8th note added, for the half note, there's an extra 16th note, and so on.
For the note sequence, it depends how many notes we enter: the MIDI item's length increased in the same ratio as cited above proportionally to the number of notes.
It would be great if the play cursor would move automatically at the end of the inserted MIDI item after inserting.
Thank you for taking the time for this. The fretboard update is something I wouldn't have dared to ask - incredible!
Hey krahosk,

I'll look into it asap to hopefully fix the midi item length and to move the play cursor automatically 😁👍
Touristkiller is offline   Reply With Quote
Old 12-30-2024, 10:16 AM   #7
krahosk
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,492
Default

I'm trying out the extended version.
- There are some hits and misses when we click the fretboard: sometimes the dot appears on the adjacent fret or string.
- Is it possible to extend the fretboard for the chords? This way we could draw chord shapes beyond the 5th fret.
- Is it also possible to insert the chord form in the take name when inserted (1 3 3 2 1 1, for example?) This would allow readout later on.
- Eventually, inserting the chord name in the take name (I can participate in inserting the data in the script if you give me an example of a code line that does that). What I mean is, for example, 1 3 3 2 1 1 is F, so eventually, the take name would indicate both "1 3 3 2 1 1" and "F".


Again, thanks for this script, it improves a guitarist's workflow!

Last edited by krahosk; 12-30-2024 at 12:53 PM.
krahosk is offline   Reply With Quote
Old 12-30-2024, 03:16 PM   #8
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Quote:
Originally Posted by krahosk View Post
I'm trying out the extended version.
- There are some hits and misses when we click the fretboard: sometimes the dot appears on the adjacent fret or string.
- Is it possible to extend the fretboard for the chords? This way we could draw chord shapes beyond the 5th fret.
- Is it also possible to insert the chord form in the take name when inserted (1 3 3 2 1 1, for example?) This would allow readout later on.
- Eventually, inserting the chord name in the take name (I can participate in inserting the data in the script if you give me an example of a code line that does that). What I mean is, for example, 1 3 3 2 1 1 is F, so eventually, the take name would indicate both "1 3 3 2 1 1" and "F".


Again, thanks for this script, it improves a guitarist's workflow!
... working by clicking on the frets does not work completely well yet. Once you know where to click, it is workable, but can certainly use some refinement 😉

As for the other points.... I'm going to party and have a few drinks on the new year first and when the drinking has worn off a bit I'll continue to figure this out.
I'm also learning something from it, because I have to delve a bit into the do's and don'ts of guitar notation 😂

As for the chord name, it should be easy to do. So that will work out....

Hopefully you can get by with the simple or slightly more extensive version for now, but as I said I'll continue with it after the new year 👍😊
Touristkiller is offline   Reply With Quote
Old 12-30-2024, 05:31 PM   #9
krahosk
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,492
Default

Happy New Year, Touristkiller! Enjoy the new year's celebration and take your time.
krahosk is offline   Reply With Quote
Old 12-30-2024, 07:33 PM   #10
Sid
Human being with feelings
 
Join Date: Apr 2018
Posts: 836
Default

In case you find this old project interesting, I'm reposting it here:

MIDI Guitar Chord Tool
https://forum.cockos.com/showthread.php?t=192481
Sid is online now   Reply With Quote
Old 12-31-2024, 12:11 PM   #11
krahosk
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,492
Default

I didn't know this guitar script existed! However, it doesn'T do the same thing as the above script.
Composing from the guitar directly, it is more useful to enter the guitar shape after having found it on a real guitar. Especially since I can't determine the chord name immediately all around the fret board. MIDI Guitar Chord Tool cannot do 2nd, 3rd or 4th position chord forms either. It's for people who don't play the guitar.

Last edited by krahosk; 12-31-2024 at 01:13 PM.
krahosk is offline   Reply With Quote
Old 12-31-2024, 01:27 PM   #12
Sid
Human being with feelings
 
Join Date: Apr 2018
Posts: 836
Default

Quote:
Originally Posted by krahosk View Post
I didn't know this guitar script existed! However, it doesn't do the same thing as the above script.
No it is different.
Quote:
Originally Posted by krahosk View Post
MIDI Guitar Chord Tool cannot do 2nd, 3rd or 4th position chord forms either.
Can you explain what you mean by 2nd, 3rd or 4th position chord forms? It gives the E chord shape, A chord shape, D, G and C, and various inversions.

From what I have read, in G Major, the G,C and D chord, for example in
position 1
G major chord with the root on the 3rd fret of the 6th string (E shape)
C major chord with the root on the 3rd fret of the 5th string (A shape)
D major chord with the root on the 5th fret of the 5th string (C shape)
position 2
G major chord with the root on the 5th fret of the 4th string (D shape)
C major chord with the root on the 8th fret of the 6th string (G shape)
D major chord with the root on the 5th fret of the 5th string (A shape)
position 3
G major chord with the root on the 10th fret of the 5th string (C shape)
C major chord with the root on the 8th fret of the 6th string (E shape)
D major chord with the root on the 10th fret of the 6th string (G shape)
position 4
G major chord with the root on the 10th fret of the 5th string (A shape)
C major chord with the root on the 10th fret of the 4th string (D shape)
D major chord with the root on the 10th fret of the 6th string (E shape)

Is that what you mean?

Quote:
Originally Posted by krahosk View Post
It's for people who don't play the guitar.
I play the guitar, and I use it, but you do you. It is based on the CAGED system which may be different from how you learned to play. I downloaded Touristkiller's script and have been playing with that also. The more tools the better!

Last edited by Sid; 12-31-2024 at 02:18 PM.
Sid is online now   Reply With Quote
Old 01-02-2025, 07:31 PM   #13
krahosk
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,492
Default

Quote:
Originally Posted by Sid View Post
No it is different.


Can you explain what you mean by 2nd, 3rd or 4th position chord forms? It gives the E chord shape, A chord shape, D, G and C, and various inversions.

From what I have read, in G Major, the G,C and D chord, for example in
position 1
G major chord with the root on the 3rd fret of the 6th string (E shape)
C major chord with the root on the 3rd fret of the 5th string (A shape)
D major chord with the root on the 5th fret of the 5th string (C shape)
position 2
G major chord with the root on the 5th fret of the 4th string (D shape)
C major chord with the root on the 8th fret of the 6th string (G shape)
D major chord with the root on the 5th fret of the 5th string (A shape)
position 3
G major chord with the root on the 10th fret of the 5th string (C shape)
C major chord with the root on the 8th fret of the 6th string (E shape)
D major chord with the root on the 10th fret of the 6th string (G shape)
position 4
G major chord with the root on the 10th fret of the 5th string (A shape)
C major chord with the root on the 10th fret of the 4th string (D shape)
D major chord with the root on the 10th fret of the 6th string (E shape)

Is that what you mean?


I play the guitar, and I use it, but you do you. It is based on the CAGED system which may be different from how you learned to play. I downloaded Touristkiller's script and have been playing with that also. The more tools the better!

I agree. Thank you!
krahosk is offline   Reply With Quote
Old 01-02-2025, 08:10 PM   #14
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 7,566
Default

I'm only passingly interested in this thread and can't really help, but I think that's mostly handled anyway, and you hit me in the peeves with
Quote:
Originally Posted by krahosk View Post
- note value attributed at the beginning with a backslash character...
All of your examples show forward slashes, which we generally don't have to qualify because it's the default slash. It leans forward in the direction of our left>right writing. It happens way too often that somebody will be reading off an URL like "blah dot com backslash stuff", I have to assume in order to sound smart, except that can't possibly work because urls use forward slashes and we can just say "slash". The only time we really ever use backslashes is in windows network and file system addresses.
ashcat_lt is online now   Reply With Quote
Old 01-05-2025, 08:52 AM   #15
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Hey krahosk

Just wanted to let you know that I haven't forgotten this one. 😁

Hope to continue working on it soon.....
__________________
++|TRACKNAME|FX BROWSER|MEDIA BROWSER|GTR2MIDI|++
Touristkiller is offline   Reply With Quote
Old 01-09-2025, 01:14 PM   #16
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Progress update...



Also Shows (chord)sequence, chord and fingering in generated midi file name
__________________
++|TRACKNAME|FX BROWSER|MEDIA BROWSER|GTR2MIDI|++

Last edited by Touristkiller; 01-09-2025 at 01:51 PM.
Touristkiller is offline   Reply With Quote
Old 01-09-2025, 01:45 PM   #17
Sid
Human being with feelings
 
Join Date: Apr 2018
Posts: 836
Default

Quote:
Originally Posted by Touristkiller View Post
Progress update...
Looks great. Are those colors limited to one dot only? We don't want to forget about Barre chords.


https://andylemaire.com/bar-chord-hand-positions/
Sid is online now   Reply With Quote
Old 01-09-2025, 02:03 PM   #18
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Quote:
Originally Posted by Sid View Post
Looks great. Are those colors limited to one dot only? We don't want to forget about Barre chords.
.... of course we won't forget barre 😉

But... pffff... this is a different story for a non-guitarist (I'm a drummer, so that's a whole different blood group 😂😂 )
__________________
++|TRACKNAME|FX BROWSER|MEDIA BROWSER|GTR2MIDI|++
Touristkiller is offline   Reply With Quote
Old 01-09-2025, 02:06 PM   #19
Sid
Human being with feelings
 
Join Date: Apr 2018
Posts: 836
Default

Quote:
Originally Posted by Touristkiller View Post
.... of course we won't forget barre 😉
Nice, I'm so looking forward to this!
Sid is online now   Reply With Quote
Old 01-09-2025, 02:33 PM   #20
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

__________________
++|TRACKNAME|FX BROWSER|MEDIA BROWSER|GTR2MIDI|++
Touristkiller is offline   Reply With Quote
Old 01-10-2025, 02:35 PM   #21
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Last bit before new update....
....the most boring part 🥴.
Nope this is not machine code... just chords 🙄 😂
__________________
++|TRACKNAME|FX BROWSER|MEDIA BROWSER|GTR2MIDI|++

Last edited by Touristkiller; 01-10-2025 at 05:02 PM.
Touristkiller is offline   Reply With Quote
Old 01-10-2025, 05:55 PM   #22
Touristkiller
Human being with feelings
 
Touristkiller's Avatar
 
Join Date: Apr 2023
Location: Netherlands
Posts: 992
Default

Released on Reapack and therefore created a new forum Thread for the script...

https://forum.cockos.com/showthread....81#post2837281
__________________
++|TRACKNAME|FX BROWSER|MEDIA BROWSER|GTR2MIDI|++
Touristkiller is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 09:44 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, vBulletin Solutions Inc.