Well done sandin,thats fantastic work. Thankyou!
I too have been interested in midi for a while, alas i dabble in a few scripting languages but am not a master of autoit.
I've put this together to play midi notes directly from the keyboard. It has the abilty to play multiple notes at once but i've found it difficult to make it s responsive as it should be to user input.
Instrument can be set from the menu.
There are some things about the WindowEvents and dll calls i don't really understand fully to know where i've gone wrong. Its eating up CPU, and perhaps those who are more familiar with autoit can help make it better and offer some input on where i've gone wrong.
#include <SendMessage.au3>
;#include <misc.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <Midiudf.au3>
Opt("GUIOnEventMode", 1) ; OnEvent mode
Global $Q = 2890 ;20
Global $W = 2990 ;20
Global $E = "2A90" ;20
Global $R = "2B90" ;20
Global $T = "2C90" ;20
Global $Y = "2D90" ;20
Global $U = "2E90" ;20
Global $I = "2F90" ;20
Global $O = "3090" ;20
Global $P = "3190" ;20
Global $A = "3290" ;21
Global $S = "3390" ;20
Global $D = "3490" ;20
Global $F = "3590" ;20
Global $G = "3690" ;20
Global $H = "3790" ;20
Global $J = "3890" ;20
Global $K = "3990" ;20
Global $L = "3A90" ;20
Global $Z = "3B90" ;20
Global $X = "3C90" ;20
Global $C = "3D90" ;20
Global $V = "3E90" ;20
Global $B = "3F90" ;20
Global $N = "4090" ;20
Global $M = "4190" ;20
Global $instrument_String="Grand Piano|Bright Piano|Electric Grand Piano|Honky-Tonk Piano|Electric piano|Electric Piano|" & _
"Harpsichord|Clavinet|Celesta|Glockenspiel|Music Box|Vibraphone|Marimba|Xylophone|Tubular bells|Dulcimer|Drawbar Organ|" & _
"Percussive Organ|Rock Organ|Church Organ|Reed Organ|Accordion|Harmonica|Tango Accordion|Nylon String Guitar|Steel String Guitar|" & _
"Jazz Guitar|Clean Electric Guitar|Muted Electric Guitar|Overdrive Guitar|Distortion Guitar|Guitar Harmonics|Accoustic Bass|" & _
"Fingered Bass|Picked Bass|Fretless Bass|Slap Bass 1|Slap Bass 2|Synth Bass 1|Synth Bass 2|Violin|Viola|Cello|Contrabass|" & _
"Tremolo Strings|Pizzicato Strings|Orchestral Harp|Timpani|String Ensemble 1|String Ensemble 2|Synth Strings 1|" & _
"Synth Strings 2|Choir ahh|Choir oohh|Synth Voice|Orchestral Hit|Trumpet|Trombone|Tuba|Muted Trumpet|French Horn|" & _
"Brass Section|Synth Brass 1|Synth Brass 2|Soprano Sax|Alto Sax|Tenor Sax|Baritone Sax|Oboe|English Horn|Bassoon|" & _
"Clarinet|Piccolo|Flute|Recorder|Pan flute|Blown Bottle|Shakuhachi|Whistle|Ocarina|Square Wave|Sawtooth Wave|Caliope|" & _
"Chiff|Charang|Voice|Fifths|Bass & Lead|New Age|Warm|PolySynth|Choir|Bowed|Metallic|Halo|Sweep|FX: Rain|FX: Soundtrack|" & _
"FX: Crystal|FX: Atmosphere|FX: Brightness|FX: Goblins|FX: Echo Drops|FX: Star Theme|Sitar|Banjo|Shamisen|Koto|Kalimba|" & _
"Bagpipe|Fiddle|Shanai|Tinkle bell|Agogo|Steel Drums|Woodblock|Taiko Drum|Melodic Tom|Synth Drum|Reverse Cymbal|" & _
"Guitar Fret Noise|Breath Noise|Seashore|Bird Tweet|Telephone Ring|Helicopter|Applause|Gunshot"
Global $instrument_Array= StringSplit($instrument_String,"|")
;Global Const $WM_KEYDOWN = 0x0100
;Global Const $WM_KEYUP = 0x0101
Dim $iKeyIndex=""
Global $sKeyName,$fileitem
$Gui = GUICreate("Key Name Demo (Esc to exit)", 400, 50)
GUISetOnEvent($GUI_EVENT_CLOSE, "Quit")
$instr_Menu=GUICtrlCreateMenu("&Instrument")
GUICtrlSetOnEvent(-1, "_instChanged")
for $zz = 1 to $instrument_Array[0]
$men1=GUICtrlCreateMenuItem($instrument_Array[$zz],$instr_Menu,-1,1)
GUICtrlSetOnEvent(-1, "_instChanged")
if $zz=1 then GUICtrlSetState(-1, $GUI_CHECKED)
Next
GUISetState(@SW_SHOW, $Gui)
GUIRegisterMsg($WM_NCLBUTTONUP, "WindowEvents")
GUIRegisterMsg($WM_KEYDOWN, "WindowEvents")
GUIRegisterMsg($WM_KEYUP, "WindowEvents")
HotKeySet("{Esc}", "Quit"); Esc to Exit
Dim $Open = _MidiOutOpen()
SetInstrument($Open,0);piano
While 1
_SendMessage($Gui, $WM_SYSCOMMAND, 0xF012, 0)
$sKeyName = ""
;sleep(100)
WEnd
Func _instChanged()
$ind=GUICtrlRead(@GUI_CtrlId,1)
if StringLen($ind>0) Then
for $zz = 1 to $instrument_Array[0]
if $ind=$instrument_Array[$zz] Then
SetInstrument($Open,$zz-1)
;MsgBox(0,"",$ind & ":" & $zz-1)
ExitLoop
EndIf
Next
EndIf
EndFunc
Func NoteOn($Handle, $NoteIdx)
If IsDeclared ( $NoteIdx ) Then
$NoteIdx = Eval($NoteIdx)
_MidiOutShortMsg($Handle, "0x0040" & $NoteIdx)
EndIf
EndFunc
Func NoteOff($Handle, $NoteIdx)
If IsDeclared ( $NoteIdx ) Then
$NoteIdx = Eval($NoteIdx)
_MidiOutShortMsg($Handle, "0x0000" & $NoteIdx)
EndIf
Endfunc
Func Play($Handle, $Notes, $Duration); Can play Single notes or use arrays for chords
If Isarray($Notes) Then
For $i in $Notes
If $i > 87 then Return 0
$i-=1
_MidiOutShortMsg($Handle, $Notes[$i])
Next
Sleep($Duration)
For $i in $Notes
$i-=1
_MidiOutShortMsg($Handle, $Notes[$i])
Next
Else
_MidiOutShortMsg($Handle, $Notes)
Sleep($Duration)
_MidiOutShortMsg($Handle, $Notes)
EndIf
EndFunc
Func SetInstrument($Handle, $Instrument)
_MidiOutShortMsg($Handle,256 * $Instrument + 192)
EndFunc
Func Quit()
Exit
EndFunc ;==>Quit
Func OnAutoItExit()
_MidiOutClose($Open)
GUIDelete($Gui)
EndFunc ;==>OnAutoItExit
Func WindowEvents($hWnd, $Msg, $wParam, $lParam)
Switch $Msg
Case $WM_KEYUP
$aRet = DllCall('user32.dll', 'int', 'GetKeyNameText', 'int', $lParam, 'str', "", 'int', 256)
$sKeyName = $aRet[2]
$iKeyIndex=StringReplace($iKeyIndex,$sKeyName,"")
NoteOff($Open, $sKeyName)
;ConsoleWrite($iKeyIndex & @CRLF)
;ConsoleWrite("keyUp: " & $sKeyName & @CRLF)
Case $WM_KEYDOWN
$aRet = DllCall('user32.dll', 'int', 'GetKeyNameText', 'int', $lParam, 'str', "", 'int', 256)
$sKeyName = $aRet[2]
if Not StringInStr($iKeyIndex,$sKeyName) Then
$iKeyIndex = $iKeyIndex & $sKeyName
NoteOn($Open, $sKeyName)
EndIf
;ConsoleWrite("keyDn: " & $sKeyName & @CRLF)
EndSwitch
EndFunc ;==>WindowEvents