Jump to content

Recommended Posts

I feel honoured to receive your feedback about this. I'm having one of the best birthdays ever today. I'm really not joking. Thanks to all. :)

Now I get the birthday reference. Happy birthday!

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Unfortunately I've no talent in creating music - what a pity.

Thanks for sharing.

 

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

wow
but

Why not  automaic change the instrument

I wanted to try all the instruments

happy birthday

thank you now

#include-once
#include <Array.au3>
local $aSystemshaqy =StringSplit("pno,br pno,e pno,h-t pno,hpsd,clav,cel,glock,mus box,vib,marim,xyl,chimes,dulc,ham org,perc org,org,harm,accord,mouth org,tango acc,gtr,a gtr,jazz gtr,e gtr,mut gtr,fuzz gtr,a bass,e bass,bass,f bass,sl bass,vln,vla,vc,db,hp,timp,tpt,tbn,tba,mut tpt,hn,s sax,a sax,sax,b sax,ob,eng hn,bsn,cl,picc,fl,rec,pan,bottle,shaku,whistle,oc,sitar,banjo,shamisen,koto,Kalimba,bagp,fiddle,shanai,bell,st drum,w bl,taiko,tom-t",",")  
for $aa=1 to $aSystemshaqy[0]
$source = "<"&$aSystemshaqy[$aa]&">;=125 (G -G) Q | ;A G 1, C' | +'B' :| 2, D' | +C DC | Q ;G' E C | 'B' A (F' -F) | ;E C D | +C "
tooltip($aSystemshaqy[$aa])
_MusPlusPlus($source )
Sleep(600)
next

Func _MusPlusPlus($sSource) ; Parse mus++
    $sSource = _InitialTidySource($sSource)
    If @error Then Return SetError(1, 0, 0)

    Local $iParts = 8, $aSystems = StringSplit($sSource, @LF & @LF, 1)
    Local $aVoices[$iParts] = ["","","","","","","",""], $aStaves
    For $i = 1 To $aSystems[0]
        $aStaves = StringSplit($aSystems[$i], @LF)
        If $i = 1 And $aStaves[0] <= 8 Then
            $iParts = $aStaves[0]
            ReDim $aVoices [$iParts]
        ElseIf $iParts <> $aStaves[0] Then
            Return SetError (2, 0, 0) ; Inconsistant number of voices
        EndIf
        For $j = 0 To $iParts -1
            $aVoices[$j] &= " " & $aStaves[$j +1]
        Next
    Next

    Local $aTimeLine, $aRepeat[1][11], $iInstance, $vCurrInstrument, $vCurrKey, $sCurrNote, $iCurrOctave, $sLookFor, $sSegnoInstrument, _
    $sSegnoKey, $iSegnoOctave, $sSegnoNote, $iLatestInstrument, $iLatestKey, $iCurrRepeat, $iEndings, $iSegno, $iDalSegno, $iDaCapo, _
    $aAccidentals[7], $sSegnoAccidentals, $sAtTempo, $vCurrTempo, $aNotePart, $sSkipIndex, $sWarnings = "", $sErrors = "", $iTuplet, _
    $bTie, $bRest, $iPitch, $iBound =1, $aInstrument[$iParts], $iHangCheck, $iRepeats, $iCurrTime, $aMessage[$iParts][1][2] ;==> voice|instance|params=time/msg

    Local Enum $iEntry = 0, $iEntryInstrument, $iEntryKey, $iEntryOctave, $iEntryNote, $iFirstExit, $iFirstExitOctave, _
    $iFirstExitNote, $iFinalExit, $iFinalExitInstrument, $iFinalExitKey

    For $i = 0 To $iParts -1
        $aInstrument[$i] = 0xC0
    Next

    ; Parsing begins here
    For $i = 0 To $iParts -1
        _ClearAccidentals($aAccidentals)
        $aVoices[$i] = StringStripWS($aVoices[$i], 3)
        StringReplace($aVoices[$i], "|:", "") ; Get loop entry points
        If @extended Then ReDim $aRepeat[@extended +1][11]

        $iInstance = 0 ; bar repeat sections encountered
        $vCurrInstrument = "<pno>" ; piano
        $vCurrKey = "0#" ; C major / A minor
        $sCurrNote = ";" ; quarter note
        $iCurrOctave = 4
        $sLookFor = "" ; Look for Q or fin within a DC or DS section repeat

        ; Bar repeat data
        $aRepeat[$iInstance][$iEntry] = $iInstance
        $aRepeat[$iInstance][$iEntryInstrument] = $vCurrInstrument
        $aRepeat[$iInstance][$iEntryKey] = $vCurrKey
        $aRepeat[$iInstance][$iEntryOctave] = $iCurrOctave
        $aRepeat[$iInstance][$iEntryNote] = $sCurrNote
        $aRepeat[$iInstance][$iFirstExit] = $iInstance
        $aRepeat[$iInstance][$iFirstExitOctave] = $iCurrOctave
        $aRepeat[$iInstance][$iFirstExitNote] = $sCurrNote
        $aRepeat[$iInstance][$iFinalExit] = ""
        $aRepeat[$iInstance][$iFinalExitInstrument] = $vCurrInstrument
        $aRepeat[$iInstance][$iFinalExitKey] = $vCurrKey

        $iCurrRepeat = 1 ; First iteration of a bar repeat sequence
        $iEndings = 1 ; no separate bar repeat endings encountered yet

        $aTimeLine = StringRegExp($aVoices[$i], "[^\h]+", 3)
        $aVoices[$i] = ""

        $sSegnoInstrument = $vCurrInstrument ; Section repeat data
        $sSegnoKey = $vCurrKey ; Section repeat data =>
        $iSegnoOctave = $iCurrOctave
        $sSegnoNote = $sCurrNote
        $sSegnoAccidentals = ",,,,,," ; array is needed when $ occurs after an accidental
        $iLatestInstrument = 0 ; position in timeline
        $iLatestKey = 0 ; position in timeline
        $iSegno = -1 ; position of $
        $iDalSegno = -1 ; position of DS
        $iDaCapo = -1 ; position of DC
        $sAtTempo = ";=100"
        $vCurrTempo = ";=100"
        $sSkipIndex = "|"

        For $j = 0 To UBound($aTimeLine) -1
            If StringInStr($sSkipIndex, "|" & $j & "|") Then ContinueLoop
            $iHangCheck = $j -1
            Select
                Case _IsInstrument($aTimeLine[$j])
                    If $j > $iLatestInstrument Then $iLatestInstrument = $j
                    _UpdateCurrentAttrib($vCurrInstrument, $aVoices, $aTimeLine[$j], $i)

                Case _IsKeySig($aTimeLine[$j])
                    If $j > $iLatestKey Then $iLatestKey = $j
                    _UpdateCurrentAttrib($vCurrKey, $aVoices, $aTimeLine[$j], $i)

                Case _IsTempoMark($aTimeLine[$j])
                    If Not StringRegExp($aVoices[$i], "[A-Go\+;\-~\\\?]") Then
                        $sAtTempo = $aTimeLine[$j]
                    EndIf
                    _UpdateCurrentAttrib($vCurrTempo, $aVoices, $aTimeLine[$j], $i)

                Case _IsAtTempo($aTimeLine[$j])
                    _UpdateCurrentAttrib($vCurrTempo, $aVoices, $sAtTempo, $i)

                Case _IsSegno($aTimeLine[$j])
                    $sSegnoKey = $vCurrKey
                    $sSegnoInstrument = $vCurrInstrument
                    $iSegnoOctave = $iCurrOctave
                    $sSegnoNote = $sCurrNote
                    $iSegno = $j
                    $sSegnoAccidentals = ""
                    For $k = 0 To 5
                        $sSegnoAccidentals &= $aAccidentals[$k] & ","
                    Next
                    $sSegnoAccidentals &= $aAccidentals[6]

                Case _IsBarLine($aTimeLine[$j])
                    _ClearAccidentals($aAccidentals)

                Case _IsStartRepeat($aTimeLine[$j])
                    _ClearAccidentals($aAccidentals)
                    $iInstance += 1
                    If $j > $iDaCapo And $j > $iDalSegno Then
                        $aRepeat[$iInstance][$iEntry] = $j
                        $aRepeat[$iInstance][$iEntryInstrument] = $vCurrInstrument
                        $aRepeat[$iInstance][$iEntryKey] = $vCurrKey
                        $aRepeat[$iInstance][$iEntryOctave] = $iCurrOctave
                        $aRepeat[$iInstance][$iEntryNote] = $sCurrNote
                        $iCurrRepeat = 1
                        $iEndings = 1
                    EndIf

                Case _Is2ndTimeRound($aTimeLine[$j])
                    If $j > $iDaCapo And $j > $iDalSegno Then
                        If $aRepeat[$iInstance][$iFinalExit] = "" Then
                            $aRepeat[$iInstance][$iFirstExit] = $j
                            $aRepeat[$iInstance][$iFirstExitOctave] = $iCurrOctave
                            $aRepeat[$iInstance][$iFirstExitNote] = $sCurrNote
                        EndIf

                        $iRepeats = StringTrimRight($aTimeLine[$j], 1) ; string to number
                        If $iEndings < $iRepeats Then $iEndings = $iRepeats
                        If $iCurrRepeat > $iRepeats Then
                            If $vCurrKey <> $aTimeLine[$iLatestKey] Then
                                If _IsKeySig($aTimeLine[$iLatestKey]) Then
                                    $vCurrKey = $aTimeLine[$iLatestKey]
                                    $aVoices[$i] &= $vCurrKey & " "
                                EndIf
                            EndIf
                            _UpdateCurrentAttrib($vCurrInstrument, $aVoices, $aTimeLine[$iLatestInstrument], $i)
                            _ClearAccidentals($aAccidentals)
                            $j = $aRepeat[$iInstance][$iFinalExit] ; Go to the next end repeat mark
                        EndIf
                    Else
                        $j = $aRepeat[$iInstance][$iFinalExit] ; Go directly to the last end section
                        _ClearAccidentals($aAccidentals)
                        _UpdateCurrentAttrib($vCurrKey, $aVoices, $aRepeat[$iInstance][$iFinalExitKey], $i)
                        _UpdateCurrentAttrib($vCurrInstrument, $aVoices, $aRepeat[$iInstance][$iFinalExitInstrument], $i)
                    EndIf

                Case _IsTie($aTimeLine[$j]) Or _IsStartTuplet($aTimeLine[$j]) Or _IsEndTuplet($aTimeLine[$j])
                    $aVoices[$i] &= $aTimeLine[$j] & " "

                Case _IsNote($aTimeLine[$j])
                    $aNotePart = _NoteSplit($aTimeLine[$j])
                    If $aNotePart[0] <> "" Then
                        $sCurrNote = _GetCurrNote($aNotePart[0])
                    EndIf
                    If $aNotePart[1] <> "" Then
                        If StringInStr($aNotePart[1], "'") Then
                            $iCurrOctave = _GetOctave($aNotePart[1])
                        EndIf
                        If StringRegExp($aNotePart[1], "[#bxz]") Then
                            _UpdateAccidentals($aAccidentals, $aNotePart[1])
                        Else
                            _GetAccidental($aAccidentals, $aNotePart[1])
                        EndIf
                    EndIf
                    $aVoices[$i] &= $aNotePart[0] & $aNotePart[1] & " "

                Case _IsEndRepeat($aTimeLine[$j])
                    If $j > $iDaCapo And $j > $iDalSegno Then
                        _ClearAccidentals($aAccidentals)
                        If $iCurrRepeat = $iEndings Then
                            $aRepeat[$iInstance][$iFinalExit] = $j
                            $aRepeat[$iInstance][$iFinalExitInstrument] = $vCurrInstrument
                            $aRepeat[$iInstance][$iFinalExitKey] = $vCurrKey
                        EndIf
                        If $iCurrRepeat <= $iEndings Then ; Go back to the start of the loop
                            $j = $aRepeat[$iInstance][$iEntry] ; $j will be incremented on the next pass ^^
                            $iCurrRepeat += 1
                            _UpdateCurrentAttrib($vCurrKey, $aVoices, $aRepeat[$iInstance][$iEntryKey], $i)
                            _UpdateCurrentAttrib($vCurrInstrument, $aVoices, $aRepeat[$iInstance][$iEntryInstrument], $i)
                            _UpdateCurrentAttrib($iCurrOctave, $aVoices, $aRepeat[$iInstance][$iEntryOctave], $i, "{", "} ")
                            _UpdateCurrentAttrib($sCurrNote, $aVoices, $aRepeat[$iInstance][$iEntryNote], $i, "{", "} ")
                        EndIf
                    EndIf

                Case _IsDalSegno($aTimeLine[$j])
                    If $iDalSegno < $j Then
                        If $iSegno = -1 Then
                            $sWarnings &= "Voice " & $i +1 & " Warning => Expected $ sign before DS " & @CRLF
                            ConsoleWrite($sWarnings) ; deal with this later
                            ExitLoop ; further parsing of this voice is meaningless
                        EndIf
                        $iDalSegno = $j
                        $j = $iSegno
                        $sLookFor = "DS"
                        _UpdateCurrentAttrib($vCurrKey, $aVoices, $sSegnoKey, $i)
                        _UpdateCurrentAttrib($vCurrInstrument, $aVoices, $sSegnoInstrument, $i)
                        _UpdateCurrentAttrib($iCurrOctave, $aVoices, $iSegnoOctave, $i, "{", "} ")
                        _UpdateCurrentAttrib($sCurrNote, $aVoices, $sSegnoNote, $i, "{", "} ")
                        $aAccidentals = StringSplit($sSegnoAccidentals, ",", 2)
                        For $iInstance = $iInstance To 0 Step -1
                            If $iSegno > $aRepeat[$iInstance][$iEntry] Then ExitLoop
                        Next
                    EndIf

                Case _IsDaCapo($aTimeLine[$j])
                    If $iDaCapo < $j Then
                        _ClearAccidentals($aAccidentals)
                        $iDaCapo = $j
                        $j = -1
                        $sLookFor = "DC"
                        $iInstance = 0
                        _UpdateCurrentAttrib($vCurrKey, $aVoices, $aRepeat[$iInstance][$iEntryKey], $i)
                        _UpdateCurrentAttrib($vCurrInstrument, $aVoices, $aRepeat[$iInstance][$iEntryInstrument], $i)
                        _UpdateCurrentAttrib($iCurrOctave, $aVoices, $aRepeat[$iInstance][$iEntryOctave], $i, "{", "} ")
                        _UpdateCurrentAttrib($sCurrNote, $aVoices, $aRepeat[$iInstance][$iEntryNote], $i, "{", "} ")
                    EndIf

                Case _IsCoda($aTimeLine[$j])
                    If ($sLookFor = "DS" And $j < $iDalSegno) Or ($sLookFor = "DC" And $j < $iDaCapo) Then
                        If $iDalSegno > $iDaCapo Then
                            $j = $iDalSegno
                        Else
                            $j = $iDaCapo
                        EndIf
                        _UpdateCurrentAttrib($vCurrKey, $aVoices, $aTimeLine[$iLatestKey], $i)
                        _UpdateCurrentAttrib($vCurrInstrument, $aVoices, $aTimeLine[$iLatestInstrument], $i)
                    EndIf

                Case _IsFin($aTimeLine[$j])
                    If ($sLookFor = "DS" And $j < $iDalSegno) Or ($sLookFor = "DC" And $j < $iDaCapo) Then ExitLoop

                Case Else
                    If _IsTimeSig($aTimeLine[$j]) Or _IsTechnique($aTimeLine[$j]) Or _IsBarRepeat($aTimeLine[$j]) Or _IsAccel($aTimeLine[$j]) Or _IsDynamicMark($aTimeLine[$j]) Then
                        ContinueLoop ; Currently unsupported performance instructions or features
                    Else
                        $sErrors &= "Voice " & $i +1 & " Syntax Error => " & $aTimeLine[$j] & @CRLF
                        $sSkipIndex &= $j & "|"
                        ConsoleWrite("Voice " & $i +1 & " Syntax Error => " & $aTimeLine[$j] & @LF)
                    EndIf
            EndSelect
            If $j = $iHangCheck Then $j += 1 ; Recursion correction
        Next

        $aTimeLine = StringRegExp($aVoices[$i], "[^\h]+", 3)
        $iInstance = UBound($aTimeLine)*2 ; upper limit... variable re-usage
        If $iInstance > UBound($aMessage, 2) Then ReDim $aMessage [$iParts][$iInstance][2]

        $vCurrInstrument = 0
        $iLatestInstrument = 0
        $vCurrKey = 0 ; C major / A minor
        $iLatestKey = 0 ; C major / A minor
        $vCurrTempo = 100
        $iCurrOctave = 4
        $sCurrNote = ";"
        $sLookFor = -1 ; variable re-usage
        $bTie = False ; variable re-usage
        $bRest = True
        $iInstance = 0 ; message count
        $iCurrTime = 0
        $iTuplet = 1
        Local $iDuration

        For $j = 0 To UBound($aTimeLine) -1
            Select
                Case _IsInstrument($aTimeLine[$j])
                    $aTimeLine[$j] = StringRegExpReplace($aTimeLine[$j], "(_)(pno|box|org|acc|gtr|bass|tpt|sax|hn|drum|bl)", " " & "$2")
                    $iLatestInstrument = _GetInstrument($aTimeLine[$j])
                    If @error And Not StringInStr($sErrors, $aTimeLine[$j]) Then
                        $sErrors &= "Voice " & $i +1 & " Instrument not recognized => " & $aTimeLine[$j] & @CRLF
                        ConsoleWrite("Voice " & $i +1 & " Instrument not recognized => " & $aTimeLine[$j] & @LF)
                    ElseIf $vCurrInstrument <> $iLatestInstrument Then
                        $vCurrInstrument = $iLatestInstrument
                        $aMessage[$i][$iInstance][0] = $iCurrTime
                        $aMessage[$i][$iInstance][1] = $vCurrInstrument*256 + 0xC0
                        $iInstance += 1
                    EndIf
                    $aInstrument[$i] = $vCurrInstrument*256 + 0xC0

                Case _IsKeySig($aTimeLine[$j])
                    $vCurrKey = _GetKey($aTimeLine[$j])

                Case _IsTempoMark($aTimeLine[$j])
                    $vCurrTempo = _GetQuartNoteBPM($aTimeLine[$j])

                Case _IsTie($aTimeLine[$j])
                    $bTie = True

                Case _IsStartTuplet($aTimeLine[$j])
                    $iTuplet = StringReplace($aTimeLine[$j], "(", "")
                    If $iTuplet = "" Then $iTuplet = 3

                Case _IsOctave($aTimeLine[$j])
                    $iCurrOctave = StringRegExpReplace($aTimeLine[$j], "[\{\}]", "")

                Case _IsCurrentNote($aTimeLine[$j])
                    $sCurrNote = StringRegExpReplace($aTimeLine[$j], "[\{\}]", "")

                Case _IsNote($aTimeLine[$j])
                    $aNotePart = _NoteSplit($aTimeLine[$j])
                    If $aNotePart[0] <> "" Then
                        $sCurrNote = _GetCurrNote($aNotePart[0])
                    Else
                        $aNotePart[0] = $sCurrNote
                    EndIf
                    $iDuration = _GetDuration($aNotePart[0], $vCurrTempo, $iTuplet)

                    If $aNotePart[1] <> "" Then
                        If StringInStr($aNotePart[1], "'") Then
                            $iCurrOctave = _GetOctave($aNotePart[1])
                        EndIf
                        If Not $bTie Then
                            $aMessage[$i][$iInstance][0] = $iCurrTime
                            $iPitch = _GetPitch($aNotePart[1], $vCurrKey, $iCurrOctave)
                            $aMessage[$i][$iInstance][1] = BitOr(($iPitch+0x15)*256, 0x90, 0x400000) ; Midi note on
                            $iInstance += 1
                        Else
                            If Not $bRest And $sLookFor > -1 Then
                                $aMessage[$i][$sLookFor][0] += $iDuration
                            EndIf
                        EndIf
                        $bRest = False
                    Else
                        $bRest = True
                    EndIf

                    $iCurrTime += $iDuration
                    If Not $bRest And Not $bTie Then ; Now turn note off
                        $aMessage[$i][$iInstance][0] = $iCurrTime
                        $aMessage[$i][$iInstance][1] = BitXOR($aMessage[$i][$iInstance -1][1], 0x400000) ; Midi note off
                        $sLookFor = $iInstance
                        $iInstance += 1
                    EndIf
                    $bTie = False

                Case _IsEndTuplet($aTimeLine[$j])
                    $iTuplet = 1
            EndSelect
        Next
        If $iInstance > $iBound Then $iBound = $iInstance
    Next

    ReDim $aMessage[$iParts][$iBound][2]

    ;_WalkThrough3D($aMessage) ; Debugging - Requires arratf.au3

    $sLookFor = ""
    For $i = 0 To $iParts -1
        For $j = 0 To UBound($aMessage, 2) -1
            If $aMessage[$i][$j][0] == "" Then ExitLoop
            If Not StringInStr($sLookFor, "," & $aMessage[$i][$j][0] & ",") Then
                $sLookFor &= $aMessage[$i][$j][0] & ","
            EndIf
        Next
    Next
    $aTimeLine = StringSplit(StringTrimRight($sLookFor, 1), ",", 2)
    _ArraySortByNumber($aTimeLine)

    If $aTimeLine[1] = 0 Then _ArrayDelete($aTimeLine, 0)

    Local $aGrid[UBound($aTimeLine)][$iParts*8 +3]
    For $i = 0 To UBound($aTimeLine) -1
        $aGrid[$i][0] = 1
        $aGrid[$i][1] = $aTimeLine[$i]
    Next

    For $i = $iParts -1 To 0 Step -1
        $iInstance = 0
        For $j = 0 To UBound($aMessage, 2) -1
            If $aMessage[$i][$j][0] == "" Then ExitLoop
            If $aMessage[$i][$j][0] == $aTimeLine[$iInstance] Then

                If BitAND($aMessage[$i][$j][1], 0x400000) = 0x400000 Then
                    If $aGrid[$iInstance][$aGrid[$iInstance][0]] <> $aInstrument[$i] Then
                        $aGrid[$iInstance][0] += 1
                        $aGrid[$iInstance][$aGrid[$iInstance][0]] = $aInstrument[$i]
                    EndIf
                EndIf

                $aGrid[$iInstance][0] += 1
                $aGrid[$iInstance][$aGrid[$iInstance][0]] = $aMessage[$i][$j][1]

            ElseIf $aMessage[$i][$j][0] > $aTimeLine[$iInstance] Then
                $iInstance += 1
                If $iInstance > UBound($aTimeLine) -1 Then ExitLoop
                $j -= 1
            EndIf
        Next

    Next
    ;_ArrayDisplay($aGrid)

    Local $iTimer, $dOpen = _MidiOutOpen()
    $iInstance = 0
    $iTimer = TimerInit()
    While 1
        If TimerDiff($iTimer) >= $aGrid[$iInstance][1] Then
            For $i = 2 To $aGrid[$iInstance][0]
                _MidiOutShortMsg($dOpen, $aGrid[$iInstance][$i])
            Next
            $iInstance += 1
        Else
            Sleep(10)
        EndIf
        If $iInstance > UBound($aTimeLine) -1 Then ExitLoop
    WEnd
    _MidiOutClose($dOpen)
EndFunc ;==> _MusPlusPlus

#region ; conditionals
Func _IsInstrument($sInstruction)
    Return StringRegExp($sInstruction, "(\A<[a-z _0-9]+>\z)")
EndFunc ;==> _IsInstrument

Func _IsKeySig($sInstruction)
    Return StringRegExp($sInstruction, "(\A[0-7][#b]\z)")
EndFunc ;==> _IsKeySig

Func _IsTimeSig($sInstruction) ; Requires accentuation / dynamics
    Return StringRegExp($sInstruction, "(\A\d+/(1|2|4|8|16|32|64)\z)")
EndFunc ;==> _IsTimeSig

Func _IsTempoMark($sInstruction)
    Return StringRegExp($sInstruction, "(\A[o\+;\-~\\\?]\.?=\d*\.?\d+\z)")
EndFunc ;==> _IsTempoMark

Func _IsAtTempo($sInstruction)
    Return $sInstruction = "@Tempo" ; not case sensitive
EndFunc ;==> _IsAtTempo

Func _IsSegno($sInstruction)
    Return $sInstruction = "$"
EndFunc ;==> _IsSegno

Func _IsBarLine($sInstruction)
    Return $sInstruction = "|"
EndFunc ;==> _IsBarLine

Func _IsStartRepeat($sInstruction)
    Return $sInstruction = "|:"
EndFunc ;==> _IsStartRepeat

Func _Is2ndTimeRound($sInstruction)
    Return StringRegExp($sInstruction, "(\A\d+,\z)")
EndFunc ;==> _Is2ndTimeRound

Func _IsTie($sInstruction)
    Return $sInstruction = "_"
EndFunc ;==> _IsTie

Func _IsStartTuplet($sInstruction)
    Return StringRegExp($sInstruction, "(\A\d*\(\z)")
EndFunc ;==> _IsStartTuplet

Func _IsNote($sNote)
    If StringRegExp($sNote, "(\A'*[A-G](#|b|bb|x|z)?'*\z)") Then Return 1
    Return StringRegExp($sNote, "(\A[o\+;\-~\\\?\.]+('*[A-G](#|b|bb|x|z)?'*)?\z)")
EndFunc ;==> _IsNote

Func _IsEndTuplet($sInstruction)
    Return $sInstruction == ")"
EndFunc ;==> _IsEndTuplet

Func _IsEndRepeat($sInstruction)
    Return $sInstruction = ":|"
EndFunc ;==> _IsEndRepeat

Func _IsCoda($sInstruction)
    Return $sInstruction == "Q"
EndFunc ;==> _IsCoda

Func _IsDalSegno($sInstruction)
    Return $sInstruction == "DS"
EndFunc ;==> _IsDalSegno

Func _IsDaCapo($sInstruction)
    Return $sInstruction == "DC"
EndFunc ;==> _IsDaCapo

Func _IsFin($sInstruction)
    Return $sInstruction == "fin"
EndFunc ;==> _IsFin

Func _IsOctave($sInstruction)
    Return StringRegExp($sInstruction, "\A\{[0-8]\}\z")
EndFunc ;==> _IsOctave

Func _IsCurrentNote($sInstruction)
    Return StringRegExp($sInstruction, "\A\{[o+;=~\?]\.*\}\z")
EndFunc ;==> _IsCurrentNote
#endregion ;==> conditionals

#region ; currently unsupported features
Func _IsTechnique($sInstruction) ; Returns an integer - gliss is currently not supported
    Return StringInStr(" gliss pizz ", " " & $sInstruction & " ", 1)
EndFunc ;==> _IsTechnique

Func _IsBarRepeat($sInstruction) ; currently unsupported
    Return StringRegExp($sInstruction, "(\A%\d*\z)")
EndFunc ;==> _IsBarRepeat

Func _IsAccel($sInstruction) ; currently unsupported
    Return  StringInStr(" accel rit ", " " & $sInstruction & " ", 1)
EndFunc ;==> _IsAccel

Func _IsDynamicMark($sInstruction) ; Returns an integer - currently unsupported
    Return StringInStr(" cres dim ppp pp /p mp mf /f ff fff ", " " & $sInstruction & " ", 1)
EndFunc ;==> _IsDynamicMark
#endregion ;==> currently unsupported features

#region ; data requests
Func _GetAccidental($aAccidentals, ByRef $sNote)
    Local $sAlpha = StringReplace($sNote, "'", "")
    $sNote = StringReplace($sNote, $sAlpha, $sAlpha & $aAccidentals[Asc($sAlpha) - 65], 0, 1)
EndFunc ;==> _GetAccidental

Func _GetKey($sKey)
    Local $iSign = 1
    If StringInStr($sKey, "b", 1) Then $iSign = -1
    Return StringRegExpReplace($sKey, "[#b]", "")*$iSign
EndFunc ;==> _GetKey

Func _GetQuartNoteBPM($sTempo)
    Local $aTempo = StringSplit($sTempo, "=", 2)
    Local $iNote = StringInStr("?\~-;+o", $aTempo[0]) -5
    Return $aTempo[1]*2^$iNote
EndFunc ;==> _GetQuartNoteBPM

Func _GetCurrNote($sNote)
    Local $sCurrChr, $sRhythm = ""
    For $i = StringLen($sNote) To 1 Step -1
        $sCurrChr = StringMid($sNote, $i, 1)
        $sRhythm = $sCurrChr & $sRhythm
        If StringInStr("o+;-~\?", $sCurrChr, 1) Then ExitLoop
    Next
    Return $sRhythm
EndFunc ;==> _GetCurrNote

Func _GetOctave($sNote)
    Local $iPos, $iOctave = 4
    For $i = 65 To 71
        $iPos = StringInStr($sNote, Chr($i), 1)
        If $iPos Then
            ExitLoop
        EndIf
    Next
    For $i = 1 To $iPos -1
        If StringMid($sNote, $i, 1) = "'" Then $iOctave -= 1
    Next
    For $i = $iPos +1 To StringLen($sNote)
        If StringMid($sNote, $i, 1) = "'" Then $iOctave += 1
    Next
    Return $iOctave
EndFunc ;==> _GetOctave

Func _GetPitch($sName, $iKey = 0, $iOctave = 4)
    Local $iPitch, $sAlpha
    Select
        Case StringInStr($sName, "C", 1)
            $sAlpha = "C"
            $iPitch = 39
        Case StringInStr($sName, "D", 1)
            $sAlpha = "D"
            $iPitch = 41
        Case StringInStr($sName, "E", 1)
            $sAlpha = "E"
            $iPitch = 43
        Case StringInStr($sName, "F", 1)
            $sAlpha = "F"
            $iPitch = 44
        Case StringInStr($sName, "G", 1)
            $sAlpha = "G"
            $iPitch = 46
        Case StringInStr($sName, "A", 1)
            $sAlpha = "A"
            $iPitch = 48
        Case StringInStr($sName, "B", 1)
            $sAlpha = "B"
            $iPitch = 50
    EndSelect

    Select
        Case StringInStr($sName, "bb", 1)
            $iPitch -= 2
        Case StringInStr($sName, "b", 1)
            $iPitch -= 1
        Case StringInStr($sName, "z", 1)
            $iPitch += 0
        Case StringInStr($sName, "#", 1)
            $iPitch += 1
        Case StringInStr($sName, "x", 1)
            $iPitch += 2
        Case $iKey
            If $iKey > 0 Then
                If StringInStr(StringLeft("FCGDAEB", $iKey), $sAlpha) Then $iPitch += 1
            Else
                If StringInStr(StringRight("FCGDAEB", -$iKey), $sAlpha) Then $iPitch -= 1
            EndIf
    EndSelect

    $iOctave -= 4
    $iPitch += $iOctave*12
    If $iPitch < 0 Or $iPitch > 87 Then Return SetError (2, 0, "") ; Out of range pitch
    Return $iPitch ; values range from 0 to 87
EndFunc ;==> _GetPitch

Func _GetDuration($sNote, $iTempo = 100, $iTuplet = 1)
    Local $sLen = StringLen($sNote)
    If Not $sLen Then Return Default
    If StringLeft($sNote, 1) = "." Then Return SetError(1, 0, 0) ; Syntax error - Dot not preceeded by a note value
    Local $iDuration = 0, $iDots = 0, $sCurrChr = "", $iID, $iNote = 0
    For $i = 1 To $sLen
        $sCurrChr = StringMid($sNote, $i, 1)
        $iID = StringInStr("?\~-;+o.", $sCurrChr) -1
        Switch $iID
            Case 0 To 6
                $iDuration += $iNote
                $iNote = 6930 * 2^$iID
            Case 7
                While $sCurrChr = "."
                    $iDots += 1
                    $i += 1
                    $sCurrChr = StringMid($sNote, $i, 1)
                WEnd
                $iNote *= (2^($iDots +1) -1)/2^$iDots
                $i -= 1
                $iDots = 0
        EndSwitch
    Next
    $iDuration += $iNote
    If $iTuplet > 1 Then
        Switch $iTuplet
            Case 2, 4, 8, 16, 32, 64 ; In mus - only 2 and 4 appear, and then only in compound time
                $iDuration *= 3/2 ; it's the same result in all cases
            Case 3 ; triplets are the most common tuplet division
                $iDuration *= 2/3
            Case 5 To 7
                $iDuration *= 4/$iTuplet
            Case 9 To 15 ; In mus - tuplets greater than 12 almost never appear
                $iDuration *= 8/$iTuplet
            Case 17 To 31
                $iDuration *= 16/$iTuplet
            Case 33 To 63
                $iDuration *= 32/$iTuplet
            Case 65 To 127
                $iDuration *= 64/$iTuplet
            Case Else
                Return SetError (2, 0, 0) ; Unsupported out of range tuplet value
        EndSwitch
    EndIf
    Return $iDuration*125/(231*$iTempo)
EndFunc ;==> _GetDuration

Func _GetInstrument($vInstrument)
    $vInstrument = StringRegExpReplace($vInstrument, "[<>]", "")
    Local $aMIDIInst[72][4] _ ; A selection of available MIDI imstruments
    = _ ; Name    , ##,Mn,Mx
    [["pno"     ,  0, 0,87], _ ; Acoustic Grand Piano ... KEYBOARDS
    ["br pno"   ,  1, 0,87], _ ; Bright Piano
    ["e pno"    ,  2, 0,87], _ ; Electric Grand Piano
    ["h-t pno"  ,  3, 0,87], _ ; Honky-tonk piano
    ["hpsd"     ,  6, 0,87], _ ; Harpsichord
    ["clav"     ,  7, 0,87], _ ; Clavichord
    ["cel"      ,  8, 0,87], _ ; Celesta
    ["glock"    ,  9, 0,87], _ ; Glockenspiel ... PITCHED PERCUSSION
    ["mus box"  , 10, 0,87], _ ; Music Box
    ["vib"      , 11, 0,87], _ ; Vibraphone
    ["marim"    , 12, 0,87], _ ; Marimba
    ["xyl"      , 13, 0,87], _ ; Xylophone
    ["chimes"   , 14, 0,87], _ ; Tubular Bells
    ["dulc"     , 15, 0,87], _ ; Dulcimer
    ["ham org"  , 16, 0,87], _ ; Drawbar Organ ... ORGAN
    ["perc org" , 17, 0,87], _ ; Percussive Organ
    ["org"      , 19, 0,87], _ ; Church Organ
    ["harm"     , 20, 0,87], _ ; Harmonium Reed Organ
    ["accord"   , 21, 0,87], _ ; Accordion
    ["mouth org", 22, 0,87], _ ; Harmonica
    ["tango acc", 23, 0,87], _ ; Bandoneon
    ["gtr"      , 24, 0,87], _ ; Classical Guitar ... GUITAR
    ["a gtr"    , 25, 0,87], _ ; Accoustic Guitar
    ["jazz gtr" , 26, 0,87], _ ; Jazz Guitar
    ["e gtr"    , 27, 0,87], _ ; Electric Guitar
    ["mut gtr"  , 28, 0,87], _ ; Muted Electric Guitar
    ["fuzz gtr" , 30, 0,87], _ ; Distortion Guitar
    ["a bass"   , 32, 0,87], _ ; Acoustic Bass ... BASS
    ["e bass"   , 33, 0,87], _ ; Electric Bass
    ["bass"     , 34, 0,87], _ ; Upright Bass
    ["f bass"   , 35, 0,87], _ ; Fretless Bass
    ["sl bass"  , 36, 0,87], _ ; Slap Bass
    ["vln"      , 40, 0,87], _ ; Violin ... STRINGS
    ["vla"      , 41, 0,87], _ ; Viola
    ["vc"       , 42, 0,87], _ ; Cello
    ["db"       , 43, 0,87], _ ; Double Bass
    ["hp"       , 46, 0,87], _ ; Harp
    ["timp"     , 47, 0,87], _ ; Timpani (perc)
    ["tpt"      , 56, 0,87], _ ; Trumpet ... BRASS
    ["tbn"      , 57, 0,87], _ ; Trombone
    ["tba"      , 58, 0,87], _ ; Tuba
    ["mut tpt"  , 59, 0,87], _ ; Muted Trumpet
    ["hn"       , 60, 0,87], _ ; French Horn
    ["s sax"    , 64, 0,87], _ ; Soprano Sax ... REED
    ["a sax"    , 65, 0,87], _ ; Alto Sax
    ["sax"      , 66, 0,87], _ ; Tenor Sax
    ["b sax"    , 67, 0,87], _ ; Baritone Sax
    ["ob"       , 68, 0,87], _ ; Oboe
    ["eng hn"   , 69, 0,87], _ ; English Horn
    ["bsn"      , 70, 0,87], _ ; Bassoon
    ["cl"       , 71, 0,87], _ ; Clarinet
    ["picc"     , 72, 0,87], _ ; Piccolo ... PIPE
    ["fl"       , 73, 0,87], _ ; Flute
    ["rec"      , 74, 0,87], _ ; Recorder
    ["pan"      , 75, 0,87], _ ; Panpipes
    ["bottle"   , 76, 0,87], _ ; Bottle
    ["shaku"    , 77, 0,87], _ ; Shakuhachi
    ["whistle"  , 78, 0,87], _ ; Whistle
    ["oc"       , 79, 0,87], _ ; Ocarina
    ["sitar"    ,104, 0,87], _ ; Sitar ... OTHER
    ["banjo"    ,105, 0,87], _ ; Banjo
    ["shamisen" ,106, 0,87], _ ; Shamisen
    ["koto"     ,107, 0,87], _ ; Koto
    ["Kalimba"  ,108, 0,87], _ ; Kalimba (perc)
    ["bagp"     ,109, 0,87], _ ; Bagpipe
    ["fiddle"   ,110, 0,87], _ ; Fiddle
    ["shanai"   ,111, 0,87], _ ; Shanai (woodwind)
    ["bell"     ,112, 0,87], _ ; Tinkle Bell
    ["st drum"  ,114, 0,87], _ ; Steel Drums
    ["w bl"     ,115, 0,87], _ ; Woodblock
    ["taiko"    ,116, 0,87], _ ; Taiko Drum
    ["tom-t"    ,117, 0,87]]   ; Tom-tom

    For $i = 0 To 71
        If $aMIDIInst[$i][0] = $vInstrument Then
            $vInstrument = $aMIDIInst[$i][1]
            ExitLoop
        EndIf
    Next

    $vInstrument = StringRegExpReplace($vInstrument, "[<>]", "")
    If StringRegExp($vInstrument, "[^\d]") Or $vInstrument < 0 Or $vInstrument > 117 Then Return SetError(1, 0, 0) ; returns Grand Piano
    Return $vInstrument ; values range from 0 to 117
EndFunc ;==> _GetInstrument
#endregion ;==> data requests

#region ; miscellaneous functions
Func _InitialTidySource($sSource)
    If _IllegalDotCheck($sSource) Then Return SetError(1, 0, 0)
    $sSource = StringReplace($sSource, '"', "''") ; Helmholtz-Wilkinson octaves
    $sSource = StringReplace($sSource, '(', "( ") ; Add spaces after (
    $sSource = StringReplace($sSource, ')', " ) ") ; Add spaces before and after )
    $sSource = StringRegExpReplace($sSource, "(<\h+)", " <") ; Remove spaces after <
    $sSource = StringRegExpReplace($sSource, "(\h+>)", "> ") ; Remove spaces before >
    $sSource = StringReplace($sSource, '_', " _ ") ; Add spaces before and after underscore
    $sSource = StringReplace($sSource, '|:', "|: ") ; Add spaces after start repeats
    $sSource = StringReplace($sSource, ':|', " :|") ; Add spaces before end repeats
    $sSource = StringReplace($sSource, ':|:', ":||:") ; Convert double repeat marks _
    $sSource = StringReplace($sSource, '|', " | ") ; Add spaces before and after bar lines
    $sSource = StringReplace($sSource, '| :', "|:") ; Restore start repeat marks
    $sSource = StringReplace($sSource, ': |', ":|") ; Restore end repeat marks
    $sSource = StringReplace($sSource, ' |  | ', " || ") ; Restore double bar lines
    $sSource = StringRegExpReplace($sSource, "(<\w+)(\h+)(pno|box|org|acc|gtr|bass|tpt|sax|hn|drum|bl)", "$1" & "_" & "$3")
    $sSource = StringReplace(StringReplace($sSource, @CRLF, @LF), @CR, @LF) ; Replace all breaks with @LF
    $sSource = StringRegExpReplace($sSource, "(\n\h*)", @LF) ; Remove spaces after breaks
    $sSource = StringRegExpReplace($sSource, "[\n]{2,}", @LF & @LF) ; Remove duplicate empty lines
    $sSource = StringRegExpReplace($sSource, "(\A\n*)", "") ; Remove Preceeding breaks
    $sSource = StringRegExpReplace($sSource, "(\n*\z)", "") ; Remove Trailing breaks
    Return $sSource
EndFunc ;==> _InitialTidySource

Func _UpdateCurrentAttrib(ByRef $vCurrAttrib, ByRef $aVoices, $vNewAttrib, $iIndex, $sPadLeft = "", $sPadRight = " ")
    If $vCurrAttrib <> $vNewAttrib Then
        $vCurrAttrib = $vNewAttrib
        $aVoices[$iIndex] &= $sPadLeft & $vCurrAttrib & $sPadRight
    EndIf
EndFunc ;==> _UpdateCurrentAttrib

Func _ClearAccidentals(ByRef $aAccidentals)
    For $i = 0 To 6
        $aAccidentals[$i] = ""
    Next
EndFunc ;==> _ClearAccidentals

Func _UpdateAccidentals(ByRef $aAccidentals, $sNote)
    $sNote = StringReplace($sNote, "'", "")
    Local $sAlpha = StringLeft($sNote, 1)
    $aAccidentals[Asc($sAlpha) - 65] = StringTrimLeft($sNote, 1)
EndFunc ;==> _UpdateAccidentals

Func _NoteSplit($sNote)
    Local $aNotePart[2] = ["", ""]
    $aNotePart[1] = StringRegExpReplace($sNote, "[o\+;\-~\\\?\.]+", "") ; Remove rhthmic values
    $aNotePart[0] = StringLeft($sNote, StringLen($sNote) - StringLen($aNotePart[1]))
    Return $aNotePart
EndFunc ;==> _NoteSplit

Func _IllegalDotCheck($sVoo)
    Return StringRegExp($sVoo, "(o\.{7}|\+\.{6}|;\.{5}|\-\.{4}|~\.{3}|\\\.\.|\?\.)")
        ; Warning - detected an unsupported number of dots after a note
EndFunc ;==> _IllegalDotCheck
#endregion ;==>  miscellaneous functions

#region ; MIDI functions
;=======================================================
;Retrieves a MIDI handle and Opens the Device
;Parameters(Optional) - Device ID, Window Callback,
; instance, flags
;Author : Eynstyne
;Library : Microsoft winmm.dll
;=======================================================
Func _MidiOutOpen($devid = 0, $callback = 0, $instance = 0, $flags = 0)
   Local $ret = DllCall("winmm.dll", "long", "midiOutOpen", "handle*", 0, "int", $devid, "dword_ptr", $callback, "dword_ptr", $instance, "long", $flags)
   If @error Then Return SetError(@error,0,0)
   If $ret[0] Then Return SetError(-1,$ret[0],0)
   Return $ret[1]
EndFunc   ;==>_MidiOutOpen

;=======================================================
;Closes Midi Output/Input devices
;Parameters - MidiHandle
;Author : Eynstyne
;Library : Microsoft winmm.dll
;=======================================================
Func _MidiOutClose ($hmidiout)
   Local $ret = DllCall("winmm.dll", "long", "midiOutClose", "handle", $hmidiout)
   If @error Then Return SetError(@error,0,0)
   If $ret[0] Then Return SetError(-1,$ret[0],0)
   Return $ret[0]
EndFunc   ;==> _MidiOutClose

;=======================================================
;Gets the Mixer Volume for MIDI
;Parameters - None
;Author : Eynstyne
;Library : Microsoft winmm.dll
;=======================================================
Func _MidiOutGetVolume ($devid = 0)
   Local $ret = DllCall("winmm.dll", "long", "midiOutGetVolume", "handle", $devid, "dword*",0)
   If @error Then Return SetError(@error,0,0)
   If $ret[0] Then Return SetError(-1,$ret[0],0)
   Return $ret[2]
EndFunc   ;==> _MidiOutGetVolume

;=======================================================
;Sets the Mixer Volume for MIDI
;Parameters - Volume (0 - 65535)
;Author : Eynstyne
;Library : Microsoft winmm.dll
;=======================================================
Func _MidiOutSetVolume($iVolume = 65535, $devid = 0)
    Local $iMixVolume=BitAND($iVolume,0xFFFF)+BitShift(BitAND($iVolume,0xFFFF),-16) ; From Ascend4nt
    Local $ret = DllCall("winmm.dll", "long", "midiOutSetVolume", "handle", $devid, "int", $iMixVolume)
    If @error Then Return SetError(@error,0,0)
    If $ret[0] Then Return SetError(-1,$ret[0],0)
    Return $ret[0]
EndFunc ;==> _MidiOutSetVolume

;=======================================================
;MIDI Message Send Function
;Parameters - Message as Hexcode or Constant
;Author : Eynstyne
;Library : Microsoft winmm.dll
;=======================================================
Func _MidiOutShortMsg($hmidiout, $msg)
   Local $ret = DllCall("winmm.dll", "long", "midiOutShortMsg", "handle", $hmidiout, "long", $msg)
   If @error Then Return SetError(@error,0,0)
   If $ret[0] Then Return SetError(-1,$ret[0],0)
   Return $ret[0]
EndFunc ;==> _MidiOutShortMsg
#endregion ;==> MIDI functions

#region ; functions ripped from arrayf.au3 and stringf.au3
; #FUNCTION# ====================================================================================================================
; Name...........: _ArraySortByNumber
; Description ...: Sorts a 1D array numerically ascending.
; Syntax.........: _ArraySortByNumber(ByRef $avArray [, $bVulgarFrac = False])
; Parameters ....: $avArray     - [ByRef] The array to sort
;                  $bVulgarFrac - [Optional] If set to True, vulgar fractions will be also be sorted numerically
; Return values .: Success   - Returns 1
;                  Failure   - Returns zero and sets @error to the following values:
;                  |@error = 1 : $avArray is not a one dimensional array
; Author ........: czardas
; Modified.......:
; Remarks .......: The array is sorted first by numbers and then by strings.
; Related .......: _ArraySort, _ArraySortByLen
; Link ..........:
; Example .......:
; ===============================================================================================================================

Func _ArraySortByNumber(ByRef $avArray, $bVulgarFrac = False)
    If Not IsArray($avArray) Or UBound($avArray, 0) > 1 Then Return SetError(1, 0, 0)

    Local $iBound = UBound($avArray) -1
    Local $aTemp[$iBound +1][2]
    For $i = 0 To $iBound
        $aTemp[$i][0] = $avArray[$i]
        If _StringIsNumber($avArray[$i], $bVulgarFrac) Then
            $aTemp[$i][1] = Execute($avArray[$i])
        Else
            $aTemp[$i][1] = "z" & $avArray[$i]
        EndIf
    Next
    _ArraySort($aTemp, 0, 0, 0, 1)
    For $i = 0 To $iBound
        $avArray[$i] = $aTemp[$i][0]
    Next
    Return 1
EndFunc ;==> _ArraySortByNumber

; #FUNCTION# ====================================================================================================================
; Name...........: _StringIsNumber
; Description ...: Checks whether a string is a number as recognised by the AutoIt interpreter
; Syntax.........: _StringIsNumber($sString [, $bVulgarFrac])
; Parameters ....: $sString     - The string to test
;                  $bVulgarFrac - [Optional] if set to True, vulgar fractions will also return True
; Return values .: True or False
; Author ........: czardas
; Remarks .......: Returns True for integers, floats, hexadecimal and scientific notation.
; Related .......: StringIsDigit, StringIsFloat, StringIsInt, StringIsXDigit
; Link ..........:
; Example .......: MsgBox(0, "1.2e-300 is a number", _StringIsNumber("1.2e-300"))
; ===============================================================================================================================

Func _StringIsNumber($sString, $bVulgarFrac = False)
    Local $bReturn = False
    If StringIsInt($sString) Or StringIsFloat($sString) Then
        $bReturn = True ; string is integer or float
    ElseIf StringRegExp($sString, "(?i)(\A[\+\-]?0x[A-F\d]+\z)") Then
        $bReturn = True ; string is hexadecimal integer
    ElseIf StringRegExp($sString, "(?i)(\A[\+\-]?\d*\.?\d+e[\+\-]?\d+\z)") Then
        $bReturn = True ; exponential (or scientific notation)
    ElseIf $bVulgarFrac And StringRegExp($sString, "(\A[\+\-]?\d+/\d+\z)") Then
        $bReturn = True ; string is a vulgar fraction
    EndIf
    Return $bReturn
EndFunc ; _StringIsNumber
#endregion ;==> functions ripped from arrayf.au3 and stringf.au3

#cs ; incomplete and unorganized comments
  note attributes ==> all new notes inherit attributes from the previous note played with the exception of repeats
  staff attributes ==> affecting all subsequent new notes (mus) ... key, instrument, time signature
  performance attributes ==> affecting all subsequent notes played including repeats (mus) tempo settings
  short lived attributes ==> affecting remaining notes within the bar ... accidentals
  section repeats ==> DC and DS
  multiple bar repeats ==> |: and :|

  o  ==> Lower case o ..... Whole note ......... open note
  +  ==> Plus symbol ...... Half note .......... open note with a stem
  ;  ==> Apostrophe ....... Quarter note ....... closed note with a stem
  -  ==> Minus sign ....... Eighth note ........ single flag
  ~  ==> Tilde ............ Sixteenth note ····· double flag
  \  ==> Back slash ....... Thirty-second note . tripple flag
  ?  ==> Question mark .... Sixty-fourth note .. quadruple flag (very rare)

  '   ==> 1 octave (above or below)
  "   ==> 2 octaves (above or below)
  "'  ==> 3 octaves (above or below)
  ""  ==> 4 octaves (above or below)

  Accidentals
  # ==> sharp
  b ==> flat
  x ==> double sharp
  bb ==> double flat
  z ==> natural

  Other symbols
  _   ==> tie
  .   ==> dot
  (   ==> start triplet
  5(  ==> start quintuplet
  )   ==> end tuplet
  |   ==> bar line
  |:  ==> start repeat
  :|  ==> end repeat
  1,  ==> first time round
  2,  ==> second time round
  DC ==> da capo
  $ ==> segno
  DS ==> del segno
  fin ==> fine
  Q ==> coda
  @Tempo ==> a tempo
  <instrument name> ==> instrument

  time signatutes n/2^n
  2/4, 3/4, 6/8 etc...

  tempo markings
  ;=100  ==> 100 quarter note beats ber minute

  Key Signatures with sharps
  0# ==> C major ==> C  D  E  F  G  A  B  C
  1# ==> G major ==> G  A  B  C  D  E  F# G
  2# ==> D major ==> D  E  F# G  A  B  C# D
  3# ==> A major ==> A  B  C# D  E  F# G# A
  4# ==> E major ==> E  F# G# A  B  C# D# E
  5# ==> B major ==> B  C# D# E  F# G# A# B
  6# ==> F# major ==> F# G# A# B  C# D# E# F#
  7# ==> C# major ==> C# D# E# F# G# A# B# C#

  Key Signatures with flats
  0b ··· C major ···· C  D  E  F  G  A  B  C
  1b ··· F major ···· F  G  A  Bb C  D  E  F
  2b ··· Bb major ··· Bb C  D  Eb F  G  A  Bb
  3b ··· Eb major ··· Eb F  G  Ab Bb C  D  Eb
  4b ··· Ab major ··· Ab Bb C  Db Eb F  G  Ab
  5b ··· Db major ··· Db Eb F  Gb Ab Bb C  Db
  6b ··· Gb major ··· Gb Ab Bb C  Db Eb Fb G
  7b ··· Cb major ··· Cb Db Eb Fb Gb Ab Bb Cb

  Supported tuplet divisions
  Note    Divisions ·····································
          3       5to7    9to15  17to31   33to63  65to127
  \       ?
  ~       \       ?
  -       ~       \       ?
  ;       -       ~       \       ?
  +       ;       -       ~       \       ?
  o       +       ;       -       ~       \       ?

  Supported tuplets for compound time
  Note    Divisions ································
          2       4       8       16      32      64
  \.      ?
  ~.      \       ?
  -.      ~       \       ?
  ;.      -       ~       \       ?
  +.      ;       -       ~       \       ?
  o.      +       ;       -       ~       \       ?

  Dotted notes
  o. == o+ , o.. == o+;
  +. == +; , +.. == +;-
  ;. == ;- , ;.. == ;-~
  -. == -~ , -.. == -~\
  ~. == ~\ , ~.. == ~\?
  \. == \?
  o...... == o+;-~\?

  Illegal sequences
  o.......
  +......
  ;.....
  -....
  ~...
  \..
  ?.

  ""C  ==>  4th 8va below = sub-contra octave
  "'C  ==>  3rd 8va below
  "C   ==>  2nd 8va below
  'C   ==>  1st 8va below
  'C'  ==>  Middle C
  C'   ==>  1st 8va above
  C"   ==>  2nd 8va above
  C"'  ==>  3rd 8va above
  C""  ==>  4th 8va above

  Full Range = ""A to C""

  After DC and DS all repeat marks are ignored on second run.
  With separate endings the final section is entered immediately.
  Q or $ do not belong in a separate ending section.
  Coda occurs in a section which is skipped
  |: 1, Q :|2, [incorrect] => will miss the coda altogether
  The continuation from segno is unclear
  |: 1, $ :|2, [incorrect] => allow rhythmic corruption
  The following is fine
  |: $ 1, :|2, Q :| DS/Q |Q
  Coda should not be placed before segno
  | Q | $ | DS/Q | Q [incorrect]
  When entering the coda section repeat marks are reinstated

  Before DC or DS ignore $, Q and fin
  After DC go to the start and continue from there
  After DS look behind for $ and continue from there
  After DC or DS stop when you see fin or go to final section when you see Q
  Search for final section Q after DC or DS (whichever is greater)
  In the final section Q ignore DC DS Q $ - they do not belong in the coda
  After DC also look for DS and after DS also look for DC
  After DC or DS repeat marks are ignored within the repeated sequence
  With repeats that have separate endings, the final ending is entered immediately
  All other endings are skipped
  Repeat marks are reinstated after DC (or DS depending which was last encountered)
  DC DS $ fin may only be used once
  Q if used must appear twice

  Illegal characters
  {}[]&¬`
#ce ;==> incomplete and unorganized comments
Link to comment
Share on other sites

Unfortunately I've no talent in creating music - what a pity.

Thanks for sharing.

 

Br,

UEZ

You certainly have talent with graphics. Much of your work amazes me. Try the tutorials and you may suddenly discover another hidden talent. This message goes to everyone. The idea is that anyone can use this without a background in music. Some basic maths is all you need.

Thanks everyone for the birthday wishes.

Edited by czardas
Link to comment
Share on other sites

mus++ for non-musicians

It is important to listen to all the examples in this tutorial to understand what is happening.

The first thing you need to know is that there are seven letters used to name musical notes A, B, C, D, E, F and G. All note names must be typed using upper case. Let's start with the simplest case. The following note is called A.

A

This note has a default pitch of 440 Hz and will sound for exactly 600 ms. There are several ways to prolong the duration of our note. Prefixing a plus sign produces a note which lasts twice as long (1200 ms).

+A

Alternatively a minus sign will shorten the note by half (300 ms).

-A

All notes inherit the duration of the previous note, so the following sequence will produce four notes lasting 600 ms followed by four faster notes at 300 ms:

A A A A -A A A A

To return to the default duration you need to use an apostrophe.

A A A A -A A A A ;A A A A

The symbols used to alter note durations are as follows:
o = 2400 ms
+ = 1200 ms
; = 600 ms default ... quarter note
- = 300 ms
~ = 150 ms
= 75 ms
? = 37.5 ms

In the above list, each note is half the duration of the previous. The values for duration are true when the music is played at the default speed of 100 bpm (100 quarter notes occuring in 1 minute). More about this later.

Now lets look at pitch. The following sequence represents a scale (all notes must be separated by at least one space):

A B C D E F G A

When listening to the scale above, you will notice that the note sequence does not always rise in pitch. To make the notes continue ascending, it is necessary to go up to the next octave. To do this you simply place a single quote after the note name. Each new octave starts with the note C.

A B C' D E F G A

When there are no quotes attached to a note, it will inherit the octave of the previously encountered note. A quote placed before a note sets the octave range below the default range.

G F E D C 'B A

To return to the default octave range, use a single quote on both sides of the note name: 'B' as shown below.

C D E F G A B +C' ;'B' A G F E D oC

In music a note can be raised by a semitone using a sharp (hash sign #):

A B C' D E F# G# +A

Or lowered by a semitone using the flat symbol (lower case b ).

E D 'B Bb G oE

Sharps and flats are also attributes inherited from a previous note with the same letter name. In the following sequence all notes containing F will be sharpened.

D E F# +G ;F E D C 'B A oG

To cancel a sharp or flat you can use a natural sign (lower case z)

D E F# +G ;Fz E D C 'B A oG

When attached to a note these three symbols (# b z) are called accidentals. Accidentals are cancelled after a bar line - vertical bar |. More about bar lines in the next tutorial.

Do not place a single quote between a note and an accidental. 'E'b is incorrect - it should be written 'Eb'

Try adding and changing the symbols in the examples and create your own examples using these basic features and you'll quickly be writing mus++.
 

Examples from the above tutorial:

_MusPlusPlus("A")
Sleep(2000)

_MusPlusPlus("+A")
Sleep(2000)

_MusPlusPlus("-A")
Sleep(2000)

_MusPlusPlus("A A A A -A A A A")
Sleep(2000)

_MusPlusPlus("A A A A -A A A A ;A A A A")
Sleep(2000)

_MusPlusPlus("A B C D E F G A")
Sleep(2000)

_MusPlusPlus("A B C' D E F G A")
Sleep(2000)

_MusPlusPlus("G F E D C 'B A")
Sleep(2000)

_MusPlusPlus("C D E F G A B +C' ;'B' A G F E D oC")
Sleep(2000)

_MusPlusPlus("A B C' D E F# G# +A")
Sleep(2000)

_MusPlusPlus("E D 'B Bb G oE")
Sleep(2000)

_MusPlusPlus("D E F# +G ;F E D C 'B A oG")
Sleep(2000)

_MusPlusPlus("D E F# +G ;Fz E D C 'B A oG")
Sleep(2000)
Edited by czardas
Link to comment
Share on other sites

Why not  automaic change the instrument

I wanted to try all the instruments

happy birthday

thank you now

You can use any midi instrument by using the number of the instrument if you know it. Look in the midiUDF, you can find it in this forum - example scripts. The numbers range from 0 to 127. Some of the instruments are not really instruments - like helicopter and telephone.

For $i = 0 To 127
    _MusPlusPlus( "<" & $i & "> ;=125 (G -G) Q | ;A G 1, C' | +'B' :| 2, D' | +C DC | Q ;G' E C | 'B' A (F' -F) | ;E C D | +C ")
Next
Edited by czardas
Link to comment
Share on other sites

I will try to follow your instruction to create music! ;) Let's see whether it sounds suitable.

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

mus++ for non-musicians (Part 2)

If you have not read and understood the examples in the previous mus++ tutorial, it is advised that you do so before reading further.

In written music it is normal to group notes into bars of equal note duration using a separator called a bar line. In mus++ bar lines are represented by a vertical bar | and can be placed anywhere - there are no restrictions.

G C' 'B' C' | D 'A' +D' | ;C 'B' A B | oC'

As mentioned in the previous tutorial, accidentals are overridden after a bar line. The following sequence plays F# twice in the first bar and F (natural) twice in the second bar etc...

+F# F | F F | E E | D# D | oD

It is possible to repeat a sequence of notes by enclosing the sequence in repeat marks : (colon). Opening repeats must be placed immediately after a bar line with no spaces between, and closing repeats are placed immediately before a bar line. |: sequence :|

|: C D E F | G F E D :| oC

Notes may be prolonged by placing a dot . after the rhythmic duration. The result is one and a half times the original duration. At default bpm, the following sequence plays notes lasting 1800, 600, 1200, 1800, 600, 1200 and 3600 ms.

+.D ;'B +G | +.G ;'D' +'F' | o.E

In the following example each bar lasts for the duration of 3 quarter notes.

G G G | +.F | +E ;D | +.'C'

In mus++ there is another way to extend the duratution of a note which is not available in written music. This involves combining any of the rhthymic note symbols, in any order. The following five notes all have the same duration.

+A ;;A ----A ;.-A ~-+~A

If you use the above method, only the last rhythmic value is inherited by the next note. In the next example all the notes will inherit the duration of an eighth note - (300 ms at default speed) until the last bar.

+;-C' |: C 'B' | G B Bb | A G# Gz | F :| G F | +.E

A silence in music is called a rest. Rests do not have special symbols in mus++ . To indicate a rest you simply write the rhythmic duration of the note without attaching a pitch value.

-F E ;C + | ;. ~F E ;C ; | - ~F E C ~ F E C ~ F E C ~ F E | +.C ;

You can alter the speed of the music using a tempo marking. ;=100 means there are 100 quarter note beats in one minute. Any note value can be used and the tempo can be changed at any point in the music.

C C C C +=83 D D D D ;=70 C C C C

If you change tempo within a repeat section, the speed remains altered on the repeat.

|: C C C C | +=83 D D D D :| oC

If you want to repeat the notes at exactly the same speed as when you entered the loop, then you must also set the tempo at the start of the repeat sequence.

|: ;=100 C C C C | +=83 D D D D :| oC

It is beyond the scope of these tutorials to explain everything about music theory and you may need to do some personal research to further your understanding.

When using sharps or flats it is important to realise that:
B# == C'

Cb == 'B

E# == F

Fb == E

You can see why this is true if you examine the layout of a standard piano keyboard.

500px-Klaviatur-3-en.svg.png

Examples from the tutorial

_MusPlusPlus("G C' 'B' C' | D 'A' +D' | ;C 'B' A B | oC'")
Sleep(2000)

_MusPlusPlus("+F# F | F F | E E | D# D | oD ")
Sleep(2000)

_MusPlusPlus("|: C D E F | G F E D :| oC")
Sleep(2000)

_MusPlusPlus("+.D ;'B +G | +.G ;'D' +'F' | o.E")
Sleep(2000)

_MusPlusPlus("G G G | +.F | +E ;D | +.'C'")
Sleep(2000)

_MusPlusPlus("+A ;;A ----A ;.-A ~-+~A")
Sleep(2000)

_MusPlusPlus("+;-C' |: C 'B' | G B Bb | A G# Gz | F :| G F | +.E")
Sleep(2000)

_MusPlusPlus("-F E ;C + | ;. ~F E ;C ; | - ~F E C ~ F E C ~ F E C ~ F E | +.C ;")
Sleep(2000)

_MusPlusPlus("C C C C +=83 D D D D ;=70 C C C C")
Sleep(2000)

_MusPlusPlus("|: C C C C | +=83 D D D D :| oC")
Sleep(2000)

_MusPlusPlus("|: ;=100 C C C C | +=83 D D D D :| oC")
Sleep(2000)
Edited by czardas
Link to comment
Share on other sites

A patch has been added to fix a bug - the interpreter is still work in progress I'm afraid. The new version (updated in the first post) will be required for the following two examples in order to hear the correct instruments. The examples are real tunes which use the features covered in the previous tutorial. I'll add some more soon.

; The Oysterwives Rant
_MusPlusPlus("<fiddle> ;=125 |: -A | ;B -B A B E E F# | A B A F# D E F A | ;B -B A B C#' D 'B' | A F# D' 'F' ;E -E ;=128 :|" & _
";=131 |: A | B A B C#' D E D 'B' | -.A ~B -A F# -.A ~B -\A ~ -F | B A B C#' D E D 'B' |  A F# D' 'F' ;E -E ;=134 :|"  & _
"-A | ;=137 ;B -B A B E E F# | A B A F# D E F A | ;B -B A B C#' D 'B' | A F# D' 'F' ;=125 ;E -;.E")
Sleep(1200)

; O'er Muir Amang The Heather
_MusPlusPlus("<bagp> ;=90 -E' |: ;'G' -.G ~B ;G -.G ~B | ;A -.A ~B -D' 'G' B G | -.D' ~E -.D ~'B'  -.D' ~E -.G ~A| G F -E -.G ~'B' -.A ~B -.A ~G :|" & _
"|: -.G ~B -.G' ~A G F -E | -.G ~D E -.A A ~G ;A | -.A ~E -.G ~A G F -E -.D ~E -.G ~A | G F -E -.G ~'B' -.A ~B -.A ~G :|" & _
";'G' -.G ~B ;G -.G ~B | ;A -.A ~B -D' 'G' B G | -.D' ~E -.D ~'B'  -.D' ~E -.G ~A| G F -E -.G ~'B' -.A ~B -.A ~G |" & _ ; There is a much shorter way to notate this - all will be revealed.
"-.G ~B -.G' ~A G F -E | -.G ~D E -.A A ~G ;A | -.A ~E -.G ~A G F -E -.D ~E -.G ~A | G F -E -.G ~'B' ;.~A")
 
 
 
 
 
 
 
 
 
 
 
 
;

I admit that some of the music in the tutorials could be more interesting. I need to find interesting examples which demonstrate each feature. I'll add them as I find them. The first two tutorials cover a lot of ground. What is important is practice at writing and listening to develop a feel for how it all works. Learning about music is a gradual process - start with simple arrangements. Trying to sing the notes helps.

You have a bit of time before the next installment because I have some professional commitments to attend to in the next few days. :)

Edited by czardas
Link to comment
Share on other sites

czardas,

This is beautiful. You will make all of us musicians. I always wanted to be a rock star, but I only became a good gardener...

Happy birthday retroactively :sorcerer:

GreenCan

Edited by GreenCan

Contributions

CheckUpdate - SelfUpdating script ------- Self updating script

Dynamic input validation ------------------- Use a Input masks can make your life easier and Validation can be as simple

MsgBox with CountDown ------------------- MsgBox with visual countdown

Display Multiline text cells in ListView ---- Example of pop-up or ToolTip for multiline text items in ListView

Presentation Manager ---------------------- Program to display and refresh different Border-less GUI's on a Display (large screen TV)

USB Drive Tools ------------------------------ Tool to help you with your USB drive management

Input Period udf ------------------------------ GUI for a period input

Excel ColorPicker ---------------------------- Color pickup tool will allow you to select a color from the standard Excel color palette

Excel Chart UDF ----------------------------- Collaboration project with water 

GetDateInString ------------------------------ Find date/time in a string using a date format notation like DD Mon YYYY hh:mm

TaskListAllDetailed --------------------------- List All Scheduled Tasks

Computer Info --------------------------------- A collection of information for helpdesk

Shared memory Demo ----------------------- Demo: Two applications communicate with each other through means of a memory share (using Nomad function, 32bit only)

Universal Date Format Conversion -------- Universal date converter from your PC local date format to any format

Disable Windows DetailsPane -------------- Disable Windows Explorer Details Pane

Oracle SQL Report Generator -------------  Oracle Report generator using SQL

SQLite Report Generator -------------------  SQLite Report generator using SQL

SQLite ListView and BLOB demo ---------- Demo: shows how binary (image) objects can be recognized natively in a database BLOB field

DSN-Less Database connection demo --- Demo: ActiveX Data Objects DSN-Less Database access

Animated animals ----------------------------- Fun: Moving animated objects

Perforated image in GUI --------------------- Fun: Perforate your image with image objects

UEZ's Perforator major update ------------- Fun: Pro version of Perforator by UEZ

Visual Crop Tool (GUI) ----------------------- Easy to use Visual Image Crop tool

Visual Image effect (GUI) -------------------- Visually apply effects on an image

 

 

 

Link to comment
Share on other sites

Thanks GreenCan and Andreik. I've certainly been having fun experimenting with this today - making melodies by randomly selecting notes from known scales (note sets). The beauty is that I can read and modify the output if I think it sounds any good. When I designed the language I wanted the note names to stand out and not be cluttered with too many other symbols.

At first I allowed instruments to be changed within a single voice, but encountered problems when I introduced multiple voices. Consequently I need to clean up some of that particular code. In written music you don't change instruments in a single voice anyway, so it's no big deal. I wanted to allow some methods which are easy from a programming perspective and not be limited to that which exists in written music. One example is the note concatenation idea I mentioned previously. This is done in music using a separate symbol called a tie. I'll cover the syntax for ties next.

It's possible to use mus++ in a number of ways. Designing an interface depends on the purpose. My purpose is to use the language internally, but I'll probably include it in a kind of IDE at some point. When I come to think of it, there are many possibilities. :)

Edited by czardas
Link to comment
Share on other sites

Yet another small change made to the first post - there will be more changes in the future. :whistle: Anyway here's the next installment:

mus++ for non-musicians (Part 3)

Note: Please read the previous two tutorials again if there's anything you didn't quite understand the first time. I have tried to make things a little clearer since I first posted them.

In music a time signature is normally placed at the start of a piece of music. A common way to write a time signature is to write it as a fraction. 3/4 means there are 3 quarter notes contained in each bar.

3/4  ;  ;  ;  |  ;  ;  ;  |

The lower  number (denominator) should always be a power of 2. The current interpreter ignores time signatures but it is good practice to include them in your script. The following time signatures are the most commonly used: 2/4, 3/4, 4/4 and 6/8. In case you were wondering: 3/4 and 6/8 have the same duration but 6/8 is divided into two lots of three.

6/8 ;.   ;. | - - -    - - - |

Double Dots are sometimes used in music to extend a note by 3/4 of the original duration. Each time a dot is added, the duration increases by half as much as value of the previous dot.

;.   == ;-
;..  == ;-~
;... == ;-~


I have never seen more than two dots added to a note.

Another way to extend the duration of a note is to use a tie (underscore). In mus++ the tie should be attached to the second note as shown.

;C _+.C

Ties are very flexible and allow you to join notes of any duration anywhere in the music. In the following example a tie crosses a bar line and the music changes speed whilst the note is still sounding.

;=100 ;C | ;=87 _+.C

To divide a single note into 3 equal parts we use triplets. In mus++ triplets are placed inside brackets.

4/4  ;  ( - - - )  ;  ( - - - ) |

Three eighth note triplets have the same duration as a single quarter note.

( ; ; ; ) == +
( - - - ) == ;
( ~ ~ ~ )
== -


With repeated bar sections it is possible to have separate endings indicated by a number followed by a comma: 1, means 1st time round and 2, means second time round etc...

4/4 |: +A 1, B :|2, C'

The above sequence plays the notes +A B A C'. It is possible to repeat separate endings any number of times. The following example plays the note sequence +A B A B A C'.

4/4 |: +A 2, B :|3, C'

You can use as many separate endings as you wish. The following plays the sequence +A B A C' A D'

4/4 |: +A 1, B :|2, C' :|3, D'

Caution is advised when entering and leaving a repeat sections: mus++ will allow some very complicated syntax - for example:

2/4 A |: _;A ( 1, -B C' 'A' ) :|2, _-A B C' ) | +'A'

The syntax below is a little easier to understand.

2/4 A |: _;A 1, ( -B C' 'A' ) :|2, _( -A B C' ) | +'A'

Instruments are placed between angle brackets and should be positioned at the very start of the music. This was not always the case, but now you must do this. The default instrument is the piano.
 

Examples including features from the 3rd tutorial (copy the latest source from the first post):

_MusPlusPlus( _ ; Fred Wilson's Hornpipe
"<hp> 4/4 ;=114 |: -.G ~E | -.C ~E  -.G ~E  -.D ~F  -.A ~F | -.E ~G  -.C' ~D  -.E ~C  -.'G' ~E |" & _
"-.F ~A  -.D' ~F  -.'E' ~G  -.C' ~E | ( -D E D C 'B' A G A G F E D ) |" & _
"-.C ~E -.G ~E -.D ~F -.A ~F | -.E ~G -.C' ~D -.E ~C -.'G' ~E |" & _
"-.F ~A -.D' ~C -.'B' ~G -.A ~B | ;C' E C :|: -'B' C' |" & _
"-.D ~'G' (-G G G) -.E' ~'G' (-G G G) | -.F' ~'G' -.E' ~'G' -.D' ~'G' (-G G G) |" & _
"-.F' ~'G' -.E' ~'G' -.D' ~C -.'B' ~C' | (-D E D C 'B' A G A G F E D) |" & _
"-.C ~E  -.G ~E  -.D ~F  -.A ~F | -.E ~G  -.C' ~D  -.E ~C  -.'G' ~E |" & _
"-.F ~A -.D' ~C -.'B' ~G -.A ~B | ;C' E C :|")
Sleep(2000)

_MusPlusPlus( _ ; Folk Dance from Alsace-Lorraine
"<kalimba> 4/8 -G |: C' C F E | 3/8 D C D | 4/8 ;E ~E F E D | -C C F E |" & _
"3/8 D C D | -.E ~D C 'B' | 4/8 -A A D' D | 3/8 'B' A B | 4/8 ;C' ~C D C 'B' |" & _
"-A A D' C | 3/8 'B' A B | 1, ;C' -'G' :|2, ;C'")
Sleep(2000)

_MusPlusPlus( _ ; O Sole Mio
"<jazz gtr> 4/4 ;=140 ; C' C 'B' | +G G | _;G B B A | oF | _;F B B A | +F F | _F ;D E F | oG |" & _
"_+.G ;G | +Ab A | _;Ab F C' 'A' | oG | ; E D C | +G G | _;G G ;.D' -C | oC ")
Sleep(2000)

_MusPlusPlus( _ ; Fandango de Salamanca
"<picc> 3/4 ;=160 ;.A' -G# ;E | A A B | -C'' D C B' ;A | _+A ; | ;.B -A ;G# | A G# F# |" & _
"-G# A G F# E | _+A ; | ;.A -G# ;E | A A B | -C'' D C B' A | _+A ; | ;.B -C'' ;D |" & _
"E D E | C -D C ;B' | _B -G# G G A |: ;B B C'' | D C B' | -C'' D C B' ;A | C'' B' A |" & _
"-B C'' B' A ;G# | A G# F# |1, ;.G# -F#  ;E | ; -G# G G A :|2, -G# A G F# ;E | _+.E |" & _
";=152 ;.A' -G# ;E | A A B | -C'' D C B' ;A | _+A ; | ;.B -A ;G# | A G# F# | ;.G# -F# ;E |" & _
"_+E ; | ;.A -G# ;E | A A B | -C'' D C B' A | _+A ; | ;.B -C'' ;D | E D E | C -C B' ;A | _+.A")
Edited by czardas
Link to comment
Share on other sites

Now I have explained most of the features included in mus++. The next installment should just about cover the remaining features. If you have understood everything so far, then you were probably already a musician to begin with. The material covered in the tutorials would probably take a music student several months to absorb, so there's no reason to feel out of your depth. Take it one step at a time and keep trying out new ideas. It is not necessary to use all the features and there are many ways to write a piece of music. Creating a masterpiece just takes practice. :)

A good friend showed me a similar music project you might want to look at. http://benjaminsoule.fr/tools/vmml/

I would say that both our systems have strengths and weaknesses, although they are in many ways similar. There are missing features in both. Muhaha! :tv_horror:

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...