Attribute VB_Name = "modMidi"
Public Declare Function midiStreamClose Lib "winmm.dll" (ByVal hms As Long) As Long
Public Declare Function midiStreamOpen Lib "winmm.dll" (phms As Long, puDeviceID As Long, ByVal cMidi As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal fdwOpen As Long) As Long
Public Declare Function midiStreamOut Lib "winmm.dll" (ByVal hms As Long, pmh As MIDIHDR, ByVal cbmh As Long) As Long
Public Declare Function midiStreamPause Lib "winmm.dll" (ByVal hms As Long) As Long
Public Declare Function midiStreamPosition Lib "winmm.dll" (ByVal hms As Long, lpmmt As MMTIME, ByVal cbmmt As Long) As Long
Public Declare Function midiStreamProperty Lib "winmm.dll" (ByVal hms As Long, lppropdata As Any, ByVal dwProperty As Long) As Long
Public Declare Function midiStreamRestart Lib "winmm.dll" (ByVal hms As Long) As Long
Public Declare Function midiStreamStop Lib "winmm.dll" (ByVal hms As Long) As Long
Public Declare Function midiOutPrepareHeader Lib "winmm.dll" (ByVal hMidiOut As Long, lpMidiOutHdr As MIDIHDR, ByVal uSize As Long) As Long
Public Declare Function midiOutUnprepareHeader Lib "winmm.dll" (ByVal hMidiOut As Long, lpMidiOutHdr As MIDIHDR, ByVal uSize As Long) As Long
Public Declare Function midiOutGetVolume Lib "winmm.dll" (ByVal uDeviceID As Long, lpdwVolume As Long) As Long
Public Declare Function midiOutSetVolume Lib "winmm.dll" (ByVal uDeviceID As Long, ByVal dwVolume As Long) As Long
Public Declare Function midiOutGetErrorText Lib "winmm.dll" Alias "midiOutGetErrorTextA" (ByVal err As Long, ByVal lpText As String, ByVal uSize As Long) As Long
Public Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOut As Long, ByVal dwMsg As Long) As Long
Public Declare Function midiOutGetNumDevs Lib "winmm" () As Integer
Public Declare Function midiOutGetDevCaps Lib "winmm.dll" Alias "midiOutGetDevCapsA" (ByVal uDeviceID As Long, lpCaps As MIDIOUTCAPS, ByVal uSize As Long) As Long
Public Declare Function midiOutReset Lib "winmm.dll" (ByVal hMidiOut As Long) As Long
Public Declare Sub EnterCriticalSection Lib "kernel32" (lpCriticalSection As CRITICAL_SECTION)
Public Declare Sub InitializeCriticalSection Lib "kernel32" (lpCriticalSection As CRITICAL_SECTION)
Public Declare Sub LeaveCriticalSection Lib "kernel32" (lpCriticalSection As CRITICAL_SECTION)
Public Declare Sub DeleteCriticalSection Lib "kernel32" (lpCriticalSection As CRITICAL_SECTION)
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Public Type CRITICAL_SECTION
    dummy As Long
End Type
Dim CrS As CRITICAL_SECTION

Public Const MAXPNAMELEN = 32
Public Type MMTIME
    wType As Long
    u As Long
    dummy As Long
End Type
Public mTime As MMTIME

Public Type MIDIEVENT
    dwDeltaTime As Long
    dwStreamID As Long
    dwEvent As Long
End Type

Public Type MIDI_EVENT
    dwDeltaTime As Long
    dwStreamID As Long
    dwEvent As Long
    kIndex As Integer
End Type

Public Type MIDIHDR
    lpData As Long
    dwBufferLength As Long
    dwBytesRecorded As Long
    dwUser As Long
    dwFlags As Long
    lpNext As Long
    Reserved As Long
    dwOffset As Long
    dwReserved(4) As Long
End Type

Public Type MIDIOUTCAPS
    wMid As Integer
    wPid As Integer
    vDriverVersion As Long
    szPname As String * MAXPNAMELEN
    wTechnology As Integer
    wVoices As Integer
    wNotes As Integer
    wChannelMask As Integer
    dwSupport As Long
End Type
Public midiCaps As MIDIOUTCAPS

Public Type MIDIPROPTEMPO
    cbStruct As Long
    dwTempo As Long
End Type

Public Type MidiDescriptions
    Tempo As Long
    Numerator As Integer
    Denominator  As Integer
    MidiClock As Integer
    MidiQuarterNote As Integer
    sfKeySignature As Integer
    miKeySignature As Integer
    TrackName() As String
    Instrument() As String
End Type
Public midiDesc As MidiDescriptions

Public Type MidiHeader
    FileSignature As String * 4
    SizeHeader As Integer
    FileFormat As Integer
    TrackCount As Integer
    DeltaTimeTick As Integer
End Type
Public mHeader As MidiHeader

Public Type MidiChunk
    TrackSignature As String * 4
    TrackLenght As Long
    TrackNumber As Integer
    IniTrack As Long
    EndTrack As Long
End Type
Public mChunk() As MidiChunk

Public Type DefLyric
    TxtString As String
    TxtStringLen As Integer
    TextStart As Long
    FraseIndex As Integer
End Type
Public Lyric() As DefLyric
Public Phrase() As String

Public Const MIDIPROP_SET = &H80000000
Public Const MIDIPROP_TEMPO = &H2&
Public Const CALLBACK_WINDOW = &H10000
Public Const MOM_DONE = &H3C9
Public Const MEVT_NOP = (&H2)
Public Const MEVT_SHORTMSG = (&H0)
Public Const TIME_TICKS = &H20
Public Const GWL_WNDPROC = (-4)
Public Const MIDI_STOPPED = &H0
Public Const MIDI_PLAYING = &H1
Public Const MIDI_PAUSED = &H2
Public Const MIDI_INVALIDFILE = &H3
Public Const MIDI_CLOSED = &H4
Public Const MIDI_FILEOPEN = &H5
Public Const MIDI_FILENOTOPEN = &H6

Public PrevProc As Long
Public hMidi As Long, TimeDiv As Double, bClose As Boolean
Public Ret As Long, MsgErr As String * 255
Public mHDR As MIDIHDR, Ptrs() As Long, mTrk As Long, StartPoint As Long
Public nCt() As Long, Ev1() As MIDI_EVENT, EventRange As Long
Public Ev() As MIDI_EVENT, isMidiKar As Boolean
Public EvPlay() As MIDIEVENT, MidiStartTime As Long
Public cMidi As clsMidi

Public mvarDevice As Integer
Public mvarStatus As Integer
Public mvarTranspose As Integer
Public mvarTimeLength As Long
Public mvarPosition As Long
Public mvarVelocity As Integer
Public mvarMasterVolume As Long
Public mvarLyricText As String
Public mvarMuteChannel(0 To 15) As Boolean
Public mvarVolume(0 To 15) As Integer
Public mvarBalance(0 To 15) As Integer
Public mvarValidChannel(0 To 15) As Boolean
Public mvarInstrument(0 To 15) As Integer
Public mvarPhaser(0 To 15) As Integer
Public mvarCeleste(0 To 15) As Integer
Public mvarChorus(0 To 15) As Integer
Public mvarTremulo(0 To 15) As Integer
Public mvarTitles(0 To 2) As String


Private Function SetTranspose(ByVal dEvent As Long) As Long
    
    If mvarTranspose = 0 Then
        SetTranspose = dEvent
        Exit Function
    End If
    
    Dim NewValue As Byte
    If (dEvent And &HF) <> 9 Then
        Select Case (dEvent And &HF0)
            Case &H80, &H90, &HA0
                NewValue = (((dEvent \ &H100)) And &HFF) + mvarTranspose
                If NewValue < &H0 Then NewValue = NewValue + &HC
                If NewValue > &H7F Then NewValue = NewValue - &HC
                SetTranspose = (dEvent And &HFF0000) Or (NewValue * &H100) Or (dEvent And &HFF)
            Case Else
                SetTranspose = dEvent
        End Select
    Else
        SetTranspose = dEvent
    End If
    
End Function

Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    
    On Error Resume Next
    If bClose Then
        StopEvents
    Else
        If uMsg = MOM_DONE Then
            InitializeCriticalSection CrS
            EnterCriticalSection CrS
            Call FreeBuffer
            LeaveCriticalSection CrS
            DeleteCriticalSection CrS
        End If
    End If
    WindowProc = CallWindowProc(PrevProc, hWnd, uMsg, wParam, lParam)
    
End Function
Public Sub HookForm(F As Form)
    PrevProc = SetWindowLong(F.hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Public Sub UnHookForm(F As Form)
    SetWindowLong F.hWnd, GWL_WNDPROC, PrevProc
End Sub
Private Sub FreeBuffer()

    midiOutUnprepareHeader hMidi, mHDR, Len(mHDR)
    If bClose Then
        StopEvents
        Exit Sub
    End If
    Call GetEvents
    
End Sub
Public Sub StopEvents()
    
    bClose = True
    FormProc.Timer1.Enabled = False
    UnHookForm FormProc
    DoEvents
    If mvarStatus = MIDI_PAUSED Then
        midiStreamPause hMidi
    Else
        midiStreamStop hMidi
    End If
    midiOutReset hMidi
    midiOutUnprepareHeader hMidi, mHDR, Len(mHDR)
    midiStreamClose hMidi
    
End Sub
Public Sub GetEvents()

    StartPoint = StartPoint + EventRange
    If bClose Then Exit Sub
    If StartPoint + 1 > UBound(Ev) Then
        cMidi.StopMidi
        Exit Sub
    End If
    
    ReDim EvPlay(0)
    EventRange = GetNextEventRange(StartPoint)
    lSize = Int(((Len(EvPlay(0)) * EventRange) + 4) / 4) * 4
    mHDR.lpData = VarPtr(EvPlay(0))
    mHDR.dwBufferLength = lSize
    mHDR.dwBytesRecorded = lSize - 4
    mHDR.dwFlags = 0
    If midiOutPrepareHeader(hMidi, mHDR, Len(mHDR)) <> 0 Then
        StopEvents
        Exit Sub
    End If
    If midiStreamOut(hMidi, mHDR, Len(mHDR)) <> 0 Then
        StopEvents
        Exit Sub
    End If

End Sub
Public Function GetNote(ByVal Note As Integer) As String
    
    Select Case Note
        Case 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120: GetNote = "C"
        Case 1, 13, 25, 37, 49, 61, 73, 85, 97, 109, 121: GetNote = "C#"
        Case 2, 14, 26, 38, 50, 62, 74, 86, 98, 110, 122: GetNote = "D"
        Case 3, 15, 27, 39, 51, 63, 75, 87, 99, 111, 123: GetNote = "D#"
        Case 4, 16, 28, 40, 52, 64, 76, 88, 100, 112, 124: GetNote = "E"
        Case 5, 17, 29, 41, 53, 65, 77, 89, 101, 113, 125: GetNote = "F"
        Case 6, 18, 30, 42, 54, 66, 78, 90, 102, 114, 126: GetNote = "F#"
        Case 7, 19, 31, 43, 55, 67, 79, 91, 103, 115, 127: GetNote = "G"
        Case 8, 20, 32, 44, 56, 68, 80, 92, 104, 116: GetNote = "G#"
        Case 9, 21, 33, 45, 57, 69, 81, 93, 105, 117: GetNote = "A"
        Case 10, 22, 34, 46, 58, 70, 82, 94, 106, 118: GetNote = "A#"
        Case 11, 23, 35, 47, 59, 71, 83, 95, 107, 119: GetNote = "B"
        Case Else: GetNote = ""
    End Select
    
End Function
Public Function GetPatches(ByVal p As Integer) As String

    Select Case p + 1
        'PIANO
        Case 1: GetPatches = "Acoustic Grand"
        Case 2: GetPatches = "Bright Acoustic"
        Case 3: GetPatches = "Electric Grand"
        Case 4: GetPatches = "Honky-Tonk"
        Case 5: GetPatches = "Electric Piano 1"
        Case 6: GetPatches = "Electric Piano 2"
        Case 7: GetPatches = "Harpsichord"
        Case 8: GetPatches = "Clavinet"
        'CHROMATIC PERCUSSION
        Case 9: GetPatches = "Celesta"
        Case 10: GetPatches = "Glockenspiel"
        Case 11: GetPatches = "Music Box"
        Case 12: GetPatches = "Vibraphone"
        Case 13: GetPatches = "Marimba"
        Case 14: GetPatches = "Xylophone"
        Case 15: GetPatches = "Tubular Bells"
        Case 16: GetPatches = "Dulcimer"
        'Organ
        Case 17: GetPatches = "Drawbar Organ"
        Case 18: GetPatches = "Percussive Organ"
        Case 19: GetPatches = "Rock Organ"
        Case 20: GetPatches = "Church Organ"
        Case 21: GetPatches = "Reed Organ"
        Case 22: GetPatches = "Accoridan"
        Case 23: GetPatches = "Harmonica"
        Case 24: GetPatches = "Tango Accordian"
        'GUITAR
        Case 25: GetPatches = "Nylon String Guitar"
        Case 26: GetPatches = "Steel String Guitar"
        Case 27: GetPatches = "Electric Jazz Guitar"
        Case 28: GetPatches = "Electric Clean Guitar"
        Case 29: GetPatches = "Electric Muted Guitar"
        Case 30: GetPatches = "Overdriven Guitar"
        Case 31: GetPatches = "Distortion Guitar"
        Case 32: GetPatches = "Guitar Harmonics"
        'BASS
        Case 33: GetPatches = "Acoustic Bass"
        Case 34: GetPatches = "Electric Bass(finger)"
        Case 35: GetPatches = "Electric Bass(pick)"
        Case 36: GetPatches = "Fretless Bass"
        Case 37: GetPatches = "Slap Bass 1"
        Case 38: GetPatches = "Slap Bass 2"
        Case 39: GetPatches = "Synth Bass 1"
        Case 40: GetPatches = "Synth Bass 2"
        'SOLO STRINGS
        Case 41: GetPatches = "Violin"
        Case 42: GetPatches = "Viola"
        Case 43: GetPatches = "Cello"
        Case 44: GetPatches = "Contrabass"
        Case 45: GetPatches = "Tremolo Strings"
        Case 46: GetPatches = "Pizzicato Strings"
        Case 47: GetPatches = "Orchestral Strings"
        Case 48: GetPatches = "Timpani"
        'Ensemble
        Case 49: GetPatches = "String Ensemble 1"
        Case 50: GetPatches = "String Ensemble 2"
        Case 51: GetPatches = "SynthStrings 1"
        Case 52: GetPatches = "SynthStrings 2"
        Case 53: GetPatches = "Choir Aahs"
        Case 54: GetPatches = "Voice Oohs"
        Case 55: GetPatches = "Synth Voice"
        Case 56: GetPatches = "Orchestra Hit"
        'BRASS
        Case 57: GetPatches = "Trumpet"
        Case 58: GetPatches = "Trombone"
        Case 59: GetPatches = "Tuba"
        Case 60: GetPatches = "Muted Trumpet"
        Case 61: GetPatches = "French Horn"
        Case 62: GetPatches = "Brass Section"
        Case 63: GetPatches = "SynthBrass 1"
        Case 64: GetPatches = "SynthBrass 2"
        'REED
        Case 65: GetPatches = "Soprano Sax"
        Case 66: GetPatches = "Alto Sax"
        Case 67: GetPatches = "Tenor Sax"
        Case 68: GetPatches = "Baritone Sax"
        Case 69: GetPatches = "Oboe"
        Case 70: GetPatches = "English Horn"
        Case 71: GetPatches = "Bassoon"
        Case 72: GetPatches = "Clarinet"
        'PIPE
        Case 73: GetPatches = "Piccolo"
        Case 74: GetPatches = "Flute"
        Case 75: GetPatches = "Recorder"
        Case 76: GetPatches = "Pan Flute"
        Case 77: GetPatches = "Blown Bottle"
        Case 78: GetPatches = "Skakuhachi"
        Case 79:  GetPatches = "Whistle"
        Case 80: GetPatches = "Ocarina"
        'SYNTH LEAD
        Case 81: GetPatches = "Lead 1 (square)"
        Case 82: GetPatches = "Lead 2 (sawtooth)"
        Case 83: GetPatches = "Lead 3 (calliope)"
        Case 84: GetPatches = "Lead 4 (chiff)"
        Case 85: GetPatches = "Lead 5 (charang)"
        Case 86: GetPatches = "Lead 6 (voice)"
        Case 87: GetPatches = "Lead 7 (fifths)"
        Case 88: GetPatches = "Lead 8 (bass+lead)"
        'SYNTH PAD
        Case 89: GetPatches = "Pad 1 (new age)"
        Case 90: GetPatches = "Pad 2 (warm)"
        Case 91: GetPatches = "Pad 3 (polysynth)"
        Case 92: GetPatches = "Pad 4 (choir)"
        Case 93: GetPatches = "Pad 5 (bowed)"
        Case 94: GetPatches = "Pad 6 (metallic)"
        Case 95: GetPatches = "Pad 7 (halo)"
        Case 96: GetPatches = "Pad 8 (sweep)"
        'SYNTH EFFECTS
        Case 97:  GetPatches = "FX 1 (rain)"
        Case 98:  GetPatches = "FX 2 (soundtrack)"
        Case 99:  GetPatches = "FX 3 (crystal)"
        Case 100: GetPatches = "FX 4 (atmosphere)"
        Case 101: GetPatches = "FX 5 (brightness)"
        Case 102: GetPatches = "FX 6 (goblins)"
        Case 103: GetPatches = "FX 7 (echoes)"
        Case 104: GetPatches = "FX 8 (sci-fi)"
        'ETHNIC
        Case 105: GetPatches = "Sitar"
        Case 106: GetPatches = "Banjo"
        Case 107: GetPatches = "Shamisen"
        Case 108: GetPatches = "Koto"
        Case 109: GetPatches = "Kalimba"
        Case 110: GetPatches = "Bagpipe"
        Case 111: GetPatches = "Fiddle"
        Case 112: GetPatches = "Shanai"
        'PERCUSSIVE
        Case 113: GetPatches = "Tinkle Bell"
        Case 114: GetPatches = "Agogo"
        Case 115: GetPatches = "Steel Drums"
        Case 116: GetPatches = "Woodblock"
        Case 117: GetPatches = "Taiko Drum"
        Case 118: GetPatches = "Melodic Tom"
        Case 119: GetPatches = "Synth Drum"
        Case 120: GetPatches = "Reverse Cymbal"
        'SOUND EFFECTS
        Case 121: GetPatches = "Guitar Fret Noise"
        Case 122: GetPatches = "Breath Noise"
        Case 123: GetPatches = "Seashore"
        Case 124: GetPatches = "Bird Tweet"
        Case 125: GetPatches = "Telephone Ring"
        Case 126: GetPatches = "Helicopter"
        Case 127: GetPatches = "Applause"
        Case 128: GetPatches = "Gunshot"
    
    End Select

End Function
Private Function GetNextEventRange(ByVal PtrIni As Long) As Long

    Dim OffSet As Long, VarTemp As Long, DrumVle As Long, DrumTxt As String
    Dim FireEvent(0 To 15) As Boolean

    If PtrIni > UBound(Ev) Then
        cMidi.StopMidi
        Exit Function
    End If

    OffSet = 1
    EvPlay(0).dwDeltaTime = Ev(PtrIni).dwDeltaTime
    If Ev(PtrIni).kIndex > 0 Then cMidi.FireEventText Ev(PtrIni).kIndex
    EvPlay(0).dwEvent = SetTranspose(Ev(PtrIni).dwEvent)
    EvPlay(0).dwStreamID = &H0
    VarTemp = EvPlay(0).dwEvent
    If VarTemp > &H7F Then
        Channel = VarTemp And &HF
        If mvarMuteChannel(Channel) Then
            If (VarTemp And &HF0) = &H90 Then
                EvPlay(0).dwStreamID = &H1000
            End If
            midiOutShortMsg hMidi, &H7BB0 + Channel
        Else
            Select Case (VarTemp And &HF0)
                Case &H80
                    cMidi.FireExtEvent Channel, ((VarTemp \ &H100) And &HFF), GetNote(((VarTemp \ &H100) And &HFF)), 0, "", False, 2   'NotesPlaying
                Case &H90
                    DrumVle = IIf(Channel = 9, ((VarTemp \ &H100) And &HFF), 0)
                    DrumTxt = IIf(Channel = 9, GetDrums(((VarTemp \ &H100) And &HFF)), "")
                    If ((VarTemp \ &H10000) And &HFF) = 0 Then
                        cMidi.FireExtEvent Channel, ((VarTemp \ &H100) And &HFF), GetNote(((VarTemp \ &H100) And &HFF)), DrumVle, DrumTxt, False, 2 'Notes Playing
                    Else
                        If Not FireEvent(Channel) Then
                            cMidi.FireExtEvent Channel, ((VarTemp \ &H10000) And &HFFFF), "", 0, "", False, 1  'Level
                            cMidi.FireExtEvent Channel, ((VarTemp \ &H100) And &HFF), GetNote(((VarTemp \ &H100) And &HFF)), 0, "", True, 2
                            FireEvent(Channel) = True
                        End If
                    End If
            End Select
        End If
    End If
    
    
    Do
        If bClose Then Exit Function
        If PtrIni + OffSet + 1 > UBound(Ev) Then Exit Do
        If Ev(PtrIni + OffSet).dwDeltaTime = 0 Then
            ReDim Preserve EvPlay(OffSet)
            EvPlay(OffSet).dwDeltaTime = Ev(PtrIni + OffSet).dwDeltaTime
            If Ev(PtrIni + OffSet).kIndex > 0 Then cMidi.FireEventText Ev(PtrIni + OffSet).kIndex
            EvPlay(OffSet).dwEvent = SetTranspose(Ev(PtrIni + OffSet).dwEvent)
            EvPlay(OffSet).dwStreamID = &H0
            VarTemp = EvPlay(OffSet).dwEvent
            If VarTemp > &H7F Then
                Channel = VarTemp And &HF
                If mvarMuteChannel(Channel) Then
                    If (VarTemp And &HF0) = &H90 Then
                        EvPlay(OffSet).dwStreamID = &H1000
                    End If
                    midiOutShortMsg hMidi, &H7BB0 + Channel
                Else
                    Select Case (VarTemp And &HF0)
                        Case &H80
                            cMidi.FireExtEvent Channel, ((VarTemp \ &H100) And &HFF), GetNote(((VarTemp \ &H100) And &HFF)), 0, "", False, 2   'NotesPlaying
                        Case &H90
                            DrumVle = IIf(Channel = 9, ((VarTemp \ &H100) And &HFF), 0)
                            DrumTxt = IIf(Channel = 9, GetDrums(((VarTemp \ &H100) And &HFF)), "")
                            If ((VarTemp \ &H10000) And &HFF) = 0 Then
                                cMidi.FireExtEvent Channel, ((VarTemp \ &H100) And &HFF), GetNote(((VarTemp \ &H100) And &HFF)), DrumVle, DrumTxt, False, 2 'Notes Playing
                            Else
                                If Not FireEvent(Channel) Then
                                    cMidi.FireExtEvent Channel, ((VarTemp \ &H10000) And &HFFFF), "", 0, "", False, 1  'Level
                                    cMidi.FireExtEvent Channel, ((VarTemp \ &H100) And &HFF), GetNote(((VarTemp \ &H100) And &HFF)), 0, "", True, 2
                                    FireEvent(Channel) = True
                                End If
                                DoEvents
                            End If
                    End Select
                End If
            End If
            OffSet = OffSet + 1
        Else
            Exit Do
        End If
    Loop
    GetNextEventRange = OffSet

End Function
Public Function GetDrums(ByVal nDrum As Integer) As String

    Select Case nDrum
        Case 35: GetDrums = "Acoustic Bass Drum"
        Case 36: GetDrums = "Bass Drum 1"
        Case 37: GetDrums = "Side Stick"
        Case 38: GetDrums = "Acoustic Snare"
        Case 39: GetDrums = "Hand Clap"
        Case 40: GetDrums = "Electric Snare"
        Case 41: GetDrums = "Low Floor Tom"
        Case 42: GetDrums = "Closed Hi-Hat"
        Case 43: GetDrums = "High Floor Tom"
        Case 44: GetDrums = "Pedal Hi-Hat"
        Case 45: GetDrums = "Low Tom"
        Case 46: GetDrums = "Open Hi-Hat"
        Case 47: GetDrums = "Low-Mid Tom"
        Case 48: GetDrums = "Hi-Mid Tom"
        Case 49: GetDrums = "Crash Cymbal 1"
        Case 50: GetDrums = "High Tom"
        Case 51: GetDrums = "Ride Cymbal 1"
        Case 52: GetDrums = "Chinese Cymbal"
        Case 53: GetDrums = "Ride Bell"
        Case 54: GetDrums = "Tambourine"
        Case 55: GetDrums = "Splash Cymbal"
        Case 56: GetDrums = "Cowbell"
        Case 57: GetDrums = "Crash Cymbal 2"
        Case 58: GetDrums = "Vibraslap"
        Case 59: GetDrums = "Ride Cymbal 2"
        Case 60: GetDrums = "Hi Bongo"
        Case 61: GetDrums = "Low Bongo"
        Case 62: GetDrums = "Mute Hi Conga"
        Case 63: GetDrums = "Open Hi Conga"
        Case 64: GetDrums = "Low Conga"
        Case 65: GetDrums = "High Timbale"
        Case 66: GetDrums = "Low Timbale"
        Case 67: GetDrums = "High Agogo"
        Case 68: GetDrums = "Low Agogo"
        Case 69: GetDrums = "Cabasa"
        Case 70: GetDrums = "Maracas"
        Case 71: GetDrums = "Short Whistle"
        Case 72: GetDrums = "Long Whistle"
        Case 73: GetDrums = "Short Guiro"
        Case 74: GetDrums = "Long Guiro"
        Case 75: GetDrums = "Claves"
        Case 76: GetDrums = "Hi Wood Block"
        Case 77: GetDrums = "Low Wood Block"
        Case 78: GetDrums = "Mute Cuica"
        Case 79: GetDrums = "Open Cuica"
        Case 80: GetDrums = "Mute Triangle"
        Case 81: GetDrums = "Open Triangle"
    End Select

End Function
