Post by cundo on Feb 11, 2023 17:50:03 GMT -5
I made this code in 2016. It's full of flaws, and I can't fix it right now because I can't remember anything about the code hahaha. Ok, really, tablatures don't have a file definition, so could be hundreds, infinite ways to write them.
This code uses piano bas as a building block.
Download some tabs, in txt format from www.classtab.org/
Beware!!! this program will fail to interpret many things.,
This code uses piano bas as a building block.
Download some tabs, in txt format from www.classtab.org/
Beware!!! this program will fail to interpret many things.,
' copyright 2023 by cundo
' this code is so old, but I'm gonna post it anyway.
' tab player by cundo
' requires Liberty BASIC v4.5.1
' find me at libertybasiccom.proboards.com
' midi code thanks to Alyce and her piano.bas
' download some tabs from :https://www.classtab.org/
WindowWidth=640 : WindowHeight=420
gosub [initVariables]
texteditor #1.t1, 16, 32, 600, 320
button #1.b1 "open",[fileOpen],ul,1,1
button #1.b2 "play",[calculation],ul,50,1
button #1.b3 "stop",[StopCalc],ul,100,1
open "" for window as #1
#1.ins "select Accoustic Nylon Guitar"
#1 "trapclose [quit]"
#1.t1 "!font courier_new 7"
[fileOpen]
gosub [stopNote]
filedialog "open" ,lastPath$;"*.txt",f$
if f$="" then [quit]
open f$ for input as #g
txt$ = input$(#g, lof(#g))
close #g
#1.t1 "!cls"
#1.t1 txt$
#1.t1 "!origin 1 1"
lastPath$=f$ ' full inlcudes filename ***********
lastPath$ = GiveMePath$( f$ )
[calculation]
cls
'init variables:
locateTabsCount=0
locateTunningCount=0
startReadingAt=0
tabAtPosition=0
gosub [locateTunning]
[again]
gosub [locateTabs]
x=0 : y= 0
startReadingAt=tabAtPosition
#1.t1 "!line "; startReadingAt; " gl$"
gl$ = replstr$( gl$, "h", "-" )
gl$ = replstr$( gl$, "p", "-" )
gl$ = replstr$( gl$, "s", "-" )
sLenght = len( gl$ )
for i = 1 to sLenght step 2 ' go tru each 2 characters by line, mostly variable.
' step=2 because the fret can be two digits
'x=x+1
'y = startReadingAt
#1.t1 "!origin ";i-2;" ";startReadingAt
scan
for u = startReadingAt to startReadingAt + 5 ' go tru each line :6 strings guitar, is a constant usually
#1.t1 "!line ";u;" gl$"
gl$=trim$(gl$)
if gl$="" then exit for
atThisPosition$ = mid$( gl$ , i , 2 )
'y=y+1
'locate x,y
newNote$= ""
'doNotPrint=0
IsNote$= ""
toThis$= ""
atThisPosition$ = remchar$( atThisPosition$ , "-|/\*=_")
if isNumber( atThisPosition$ ) then
stringPlayedNumber = u-startReadingAt + 1
stringPlayedName$ = word$(standard$,stringPlayedNumber)
stringPlayedMidiValue$ = word$(word$(standard$,2,chr$(0)),stringPlayedNumber)
listOfNotes$ = "e f f#g g#a a#b c c#d d#"
len.listOfNotes = len( listOfNotes$ )
find = instr( listOfNotes$, lower$(stringPlayedName$) ;" " )
find = find + val( atThisPosition$ )*2
if find>len.listOfNotes then
find = find-len.listOfNotes
end if
IsNote$ = str$(val(stringPlayedMidiValue$) +val( atThisPosition$ ))
print IsNote$,stringPlayedNumber,stringPlayedName$,stringPlayedMidiValue$
end if
mnote=0
if IsNote$<>"" then
if isNumber( IsNote$ ) then mnote=val(IsNote$)
if mnote<>0 then
gosub [stopNote]
gosub [newNote]
end if
end if
'if u <startReadingAt + 5 then call Sleep 10
[jmp]
next u
if i<sLenght then call Sleep 215
next i
goto [again]
wait
[StopCalc]
Timer 0
gosub [stopNote] 'stop all output
#1.t1 "!origin 1 1"
wait
[quit]
timer 0
gosub [stopNote] 'stop all output
gosub [stopPlay]
CallDLL #winmm, "midiOutClose", hMidiOut As ulong,_
ret As ulong
close #1
end
[locateTabs]
Timer 0
'scan
locateTabsCount = locateTabsCount + 1
#1.t1 "!lines countVar"
if locateTabsCount >countVar then
print "No more lines to read from",countVar
wait
end if
#1.t1 "!line "; locateTabsCount ;" gl$"
locateEmptySymbol=instr( gl$ , "-" )
if locateEmptySymbol then
for iz= 1 to 5
#1.t1 "!line "; locateTabsCount +iz;" g$"
' verificar q siempre busque una columnma de 6 '-' en cualquier posicion no sola la 1a q encuentre
if instr( g$ , "-" ) =locateEmptySymbol then
tabAtPosition=locateTabsCount
else
tabAtPosition=0
exit for
end if
next iz
end if
if tabAtPosition=0 then
'try searching again
goto [locateTabs]
end if
return
[locateTunning]
scan
locateTunningCount= locateTunningCount+1
dim tunning$(10)
#1.t1 "!lines countVar"
if locateTunningCount>countVar-6 then
print "Couldn't find the strings tunning"
return
end if
#1.t1 "!line "; locateTunningCount;" LT$"
standard$ = "E B G D A E";chr$(0);"64 59 55 50 45 40"
dropD$ = "E B G D A D";chr$(0);"64 59 55 50 45 38"
for i = 1 to 6
curNoteToFind$ = word$( standard$, i )
locateCurNote= instr( LT$ , curNoteToFind$ )
if locateCurNote then
locateTunningLetters=locateTunningLetters+1
if i = 1 then TunningBarStartsAt= locateTunningCount ' the line were the tunning bar is
end if
next i
if locateTunningLetters<6 then
goto [locateTunning]
else
curTunning$=standard$
end if
return
[initVariables]
note=0 'will contain value for note
BLACK=0 'color value for black keys
WHITE=hexdec("FFFFFF") 'color value for white keys
Dim ins$(128) 'names of instruments
'read instrument name data into array for combobox
For vc = 0 to 127
Read data$
ins$(vc)=data$
Next vc
'combobox index is 1-based, instrument voices are 0-based
instrum=1 'select first instrument voice
voice=0 'voice 0 = instrum 1
'open midi device and obtain handle
'midi functions return 0 if successful
struct m, a$ As ptr
CallDLL #winmm, "midiOutOpen",_
m As struct,-1 As long,0 As long,_
0 As long,0 As long,ret As long
hMidiOut=m.a$.struct 'handle to midi device
Combobox #1.ins, ins$(,[instrument],200, 2, 220,400
return
[instrument]'user selected an instrument voice
#1.ins "selectionindex? instrum"
gosub [doChange] 'change voice
Wait
[newNote] 'mouse clicked to start new note
note=mnote 'set note to match piano key clicked by mouse
gosub [playNewNote]'play new note
return
[cutOff]'stop note played by typing on keyboard
gosub [stopNote]
wait
[endNote]'stop note when mouse button is released
gosub [stopNote]
Wait
[playNewNote]'play new note:
gosub [stopNote]
event=144 'event 144 = play on channel 1
low=(note*256)+event
velocity=127 'original 127
hi=velocity*256*256
dwMsg=low+hi
CallDLL #winmm, "midiOutShortMsg",hMidiOut As ulong,_
dwMsg As ulong, ret As ulong
RETURN
[stopNote]'stop note from playing
timer 0
event=144 'event 144 = play on channel 1
low=(note*256)+event
hiZero=0 'stop note from sounding by setting velocity to 0
dwMsg=low+hiZero
CallDLL #winmm, "midiOutShortMsg",hMidiOut As ulong,_
dwMsg As ulong, ret As ulong
RETURN
[stopPlay]'stop all notes from playing
event=128 'event 128 = stop play
low=(note*256)+event
dwMsg=low+hi
CallDLL #winmm, "midiOutShortMsg",hMidiOut As ulong,_
dwMsg As ulong, ret As ulong
timer 0
RETURN
[doChange]'signal a voice change:
event=192 'event 192 = change
voice=instrum-1
velocity=127
low=(voice*256)+event
hi=velocity*256*256
dwMsg=low+hi
CallDLL #winmm, "midiOutShortMsg",hMidiOut As ulong,_
dwMsg As ulong, ret As ulong
RETURN
[findNote]'determine piano key pressed by mouse to set note
'note value will be in mnote
'MX=MouseX:MY=MouseY
noteCodes$="48 72"
If keyColor=BLACK Then 'black keys
If MX<=54 Then mnote = 49 : RETURN 'c#
If MX<=97 Then mnote = 51 : RETURN 'd#
If MX<=183 Then mnote = 54 : RETURN 'f#
If MX<=226 Then mnote = 56 : RETURN 'g#
If MX<=266 Then mnote = 58 : RETURN 'a#
If MX<=354 Then mnote = 61 : RETURN 'c#
If MX<=397 Then mnote = 63 : RETURN 'd#
If MX<=483 Then mnote = 66 : RETURN 'f#
If MX<=527 Then mnote = 68 : RETURN 'g#
If MX<=566 Then mnote = 70 : RETURN 'a#
return
end if
if keyColor=WHITE then 'white keys
If MX<=43 Then mnote = 48 : RETURN 'c
If MX<=86 Then mnote = 50 : RETURN 'd
If MX<=129 Then mnote = 52 : RETURN 'e
If MX<=172 Then mnote = 53 : RETURN 'f
If MX<=215 Then mnote = 55 : RETURN 'g
If MX<=258 Then mnote = 57 : RETURN 'a
If MX<=300 Then mnote = 59 : RETURN 'b
If MX<=343 Then mnote = 60 : RETURN 'c
If MX<=386 Then mnote = 62 : RETURN 'd
If MX<=429 Then mnote = 64 : RETURN 'e
If MX<=472 Then mnote = 65 : RETURN 'f
If MX<=515 Then mnote = 67 : RETURN 'g
If MX<=558 Then mnote = 69 : RETURN 'a
If MX<=600 Then mnote = 71 : RETURN 'b
If MX<=638 Then mnote = 72 : RETURN 'c
return
End If
RETURN
Sub Sleep value
CallDLL #kernel32, "Sleep",value As Long,r As Void
End Sub
Function GiveMePath$( lastPath$ )
[charless]
lastPath$=mid$( lastPath$,1, len(lastPath$)-1)
if right$(lastPath$,1)<>"\" then [charless]
' after that, it is just the path. *************
GiveMePath$=lastPath$
End Function
Function isNumber( tellMe$ )
if tellMe$ = str$(val(tellMe$)) then isNumber=1
End Function
'list of 128 voices, in order of their MIDI indexes
Data "Grand Piano","Bright Grand","Electric Grand","Honky Tonk"
Data "Rhodes","Chorus Piano","Harpsichord","Clavinet"
Data "Celesta","Glockenspiel","Music Box","Vibraphone"
Data "Marimba","Xylophone","Tubular Bells","Dulcimer"
Data "Hammond Organ","Percussion Organ","Rock Organ"
Data "Church Organ","Reed Organ","Accordian","Harmonica"
Data "Tango Accordian","Accoustic Nylon Guitar"
Data "Accoustic Steel Guitar","Electric Jazz Guitar"
Data "Electric Clean Guitar","Electric Mute Guitar"
Data "Overdrive Guitar","Distorted Guitar","Guitar Harmonic"
Data "Accoustic Bass","Electric Bass Finger","Electric Bass Pick"
Data "Fretless Bass","Slap Bass One","Slap Bass Two"
Data "Synth Bass One","Synth Bass Two","Violin","Viola","Cello"
Data "Contrabass","Tremolo Strings","Pizzicato Strings"
Data "Orchestra Harp","Timpani","String Ensemble One"
Data "String Ensemble Two","Synth Strings One","Synth Strings Two"
Data "Choir Ahhs","Voice Oohs","Synth Voice","Orchestra Hit"
Data "Trumpet","Trombone","Tuba","Mute Trumpet","French Horn"
Data "Brass Section","Synth Brass One","Synth Brass Two"
Data "Soprano Sax","Alto Sax","Tenor Sax","Bari Sax","Oboe"
Data "English Horn","Bassoon","Clarinet","Piccolo","Flute"
Data "Recorder","Pan Flute","Bottle Blow","Shakuhachi","Whistle"
Data "Ocarina","Square Wave","Sawtooth","Caliope","Chiff Lead"
Data "Charang","Solo Synth VX","Brite Saw","Brass and Lead"
Data "Fantasia Pad","Warm Pad","Poly Synth Pad","Space Vox Pad"
Data "Bowd Glas Pad","Metal Pad","Halo Pad","Sweep Pad"
Data "Ice Rain","Sound Track","Crystal","Atmosphere","Brightness"
Data "Goblin","Echo Drops","Star Theme","Sitar","Banjo","Shamisen"
Data "Koto","Kalimba","Bagpipe","Fiddle","Shanai"
Data "Tinkle Bell","Agogo","Steel Drums","Wood Block","Taiko Drum"
Data "Melodic Tom","Synth Drum","Rev Cymbal"
Data "Guitar Fret Noise","Breath Noise","Sea Shore","Bird Tweet"
Data "Phone Ring","Helicopter","Applause","Gunshot"