Ascend4nt Posted July 27, 2013 Posted July 27, 2013 (edited) czardas, nice to know we're helping you out! I'm just glad that I stumbled across that website, which lays out MIDI encoding really well. Might even be able to decode a MIDI file if that's the format of all messages.. I've also updated the script now to add Panning, Modulation, and per-Channel Volume adjustments. There's sustain pedal and aftertouch stuff added too, but I haven't been able to get them to work with my soundcard. I think it's just a limit of the drivers though. Here's the script now, with more example stuff. I will need to separate the example stuff out for an 'official' release. expandcollapse popup; ==================================================================================================== ; <MidiExTest.au3> ; ; Extra Tests of the MIDI UDF (see below for best version) ; This uses fixed versions of the functions in the original 'MidiTest' script, ; especially MidiSetInstrument, NoteOn, and NoteOff. It also adds a few functions ; ; Functions: ; NoteOn() ; Turns on a given note on a given channel at a given velocity ; NoteAfterTouch(); Applies Aftertouch to a given note on a given channel at given pressure ; NoteOff() ; Turns off a given note on a given channel ; PercussionOn() ; Turns on a Percussion instrument at a given velocity ; PercussionOff() ; Turns off a Percussion instrument ; NotesAllOff() ; Turns off all notes on a given channel (unless sustain is on) ; MidiAllSoundOff() ; Turns off all sound on a given channel (even if sustain is on) ; MidiResetControllers() ; Resets Controllers (Pedals, PitchBend, Modulation, etc) ; MidiPitchBend() ; Pitch-bends all the notes on a given channel ; MidiChannelAftertouch() ; Sets Channel Pressure (AfterTouch) - different from NoteAfterTouch() ; MidiSetInstrument() ; Sets the instrument on a given channel (channel 10 is special though) ; MidiControlChange() ; Sends certain Control messages (such as Pan, Modulate, Volume) ; ; Requirements: ; MIDI UDF - Modified version (Ascend4nt) ; @ http://www.autoitscript.com/forum/topic/37072-midi-udf/?p=810725 ; ; Reference: ; MIDI Message Table 1 (Status = low byte, data 1 = upper byte LowWord, 2 = low byte HiWord) ; @ http://www.midi.org/techspecs/midimessages.php ; ; Author: Ascend4nt ; ==================================================================================================== ; Note Values Global Const $NOTE_A0 = 0x15 Global Const $NOTE_A0SHARP = 0x16 Global Const $NOTE_B0 = 0x17 Global Const $NOTE_C1 = 0x18 Global Const $NOTE_C1SHARP = 0x19 Global Const $NOTE_D1 = 0x1A Global Const $NOTE_D1SHARP = 0x1B Global Const $NOTE_E1 = 0x1C Global Const $NOTE_F1 = 0x1D Global Const $NOTE_F1SHARP = 0x1E Global Const $NOTE_G1 = 0x1F Global Const $NOTE_G1SHARP = 0x20 Global Const $NOTE_A1 = 0x21 Global Const $NOTE_A1SHARP = 0x22 Global Const $NOTE_B1 = 0x23 Global Const $NOTE_C2 = 0x24 Global Const $NOTE_C2SHARP = 0x25 Global Const $NOTE_D2 = 0x26 Global Const $NOTE_D2SHARP = 0x27 Global Const $NOTE_E2 = 0x28 Global Const $NOTE_F2 = 0x29 Global Const $NOTE_F2SHARP = 0x2A Global Const $NOTE_G2 = 0x2B Global Const $NOTE_G2SHARP = 0x2C Global Const $NOTE_A2 = 0x2D Global Const $NOTE_A2SHARP = 0x2E Global Const $NOTE_B2 = 0x2F Global Const $NOTE_C3 = 0x30 Global Const $NOTE_C3SHARP = 0x31 Global Const $NOTE_D3 = 0x32 Global Const $NOTE_D3SHARP = 0x33 Global Const $NOTE_E3 = 0x34 Global Const $NOTE_F3 = 0x35 Global Const $NOTE_F3SHARP = 0x36 Global Const $NOTE_G3 = 0x37 Global Const $NOTE_G3SHARP = 0x38 Global Const $NOTE_A3 = 0x39 Global Const $NOTE_A3SHARP = 0x3A Global Const $NOTE_B3 = 0x3B Global Const $NOTE_C4 = 0x3C Global Const $NOTE_C4SHARP = 0x3D Global Const $NOTE_D4 = 0x3E Global Const $NOTE_D4SHARP = 0x3F Global Const $NOTE_E4 = 0x40 Global Const $NOTE_F4 = 0x41 Global Const $NOTE_F4SHARP = 0x42 Global Const $NOTE_G4 = 0x43 Global Const $NOTE_G4SHARP = 0x44 Global Const $NOTE_A4 = 0x45 Global Const $NOTE_A4SHARP = 0x46 Global Const $NOTE_B4 = 0x47 Global Const $NOTE_C5 = 0x48 Global Const $NOTE_C5SHARP = 0x49 Global Const $NOTE_D5 = 0x4A Global Const $NOTE_D5SHARP = 0x4B Global Const $NOTE_E5 = 0x4C Global Const $NOTE_F5 = 0x4D Global Const $NOTE_F5SHARP = 0x4E Global Const $NOTE_G5 = 0x4F Global Const $NOTE_G5SHARP = 0x50 Global Const $NOTE_A5 = 0x51 Global Const $NOTE_A5SHARP = 0x52 Global Const $NOTE_B5 = 0x53 Global Const $NOTE_C6 = 0x54 Global Const $NOTE_C6SHARP = 0x55 Global Const $NOTE_D6 = 0x56 Global Const $NOTE_D6SHARP = 0x57 Global Const $NOTE_E6 = 0x58 Global Const $NOTE_F6 = 0x59 Global Const $NOTE_F6SHARP = 0x5A Global Const $NOTE_G6 = 0x5B Global Const $NOTE_G6SHARP = 0x5C Global Const $NOTE_A6 = 0x5D Global Const $NOTE_A6SHARP = 0x5E Global Const $NOTE_B6 = 0x5F Global Const $NOTE_C7 = 0x60 Global Const $NOTE_C7SHARP = 0x61 Global Const $NOTE_D7 = 0x62 Global Const $NOTE_D7SHARP = 0x63 Global Const $NOTE_E7 = 0x64 Global Const $NOTE_F7 = 0x65 Global Const $NOTE_F7SHARP = 0x66 Global Const $NOTE_G7 = 0x67 Global Const $NOTE_G7SHARP = 0x68 Global Const $NOTE_A7 = 0x69 Global Const $NOTE_A7SHARP = 0x6A Global Const $NOTE_B7 = 0x6B Global Const $NOTE_C8 = 0x6C ; Percussion Instruments Global Const $DRUMS_AcousticBassDrum = 0x23 Global Const $DRUMS_BassDrum1 = 0x24 Global Const $DRUMS_SideStick = 0x25 Global Const $DRUMS_AcousticSnare = 0x26 Global Const $DRUMS_HandClap = 0x27 Global Const $DRUMS_ElectricSnare = 0x28 Global Const $DRUMS_LowFloorTom = 0x29 Global Const $DRUMS_ClosedHiHat = 0x2A Global Const $DRUMS_HighFloorTom = 0x2B Global Const $DRUMS_PedalHiHat = 0x2C Global Const $DRUMS_LowTom = 0x2D Global Const $DRUMS_OpenHiHat = 0x2E Global Const $DRUMS_LowMidTom = 0x2F Global Const $DRUMS_HiMidTom = 0x30 Global Const $DRUMS_CrashCymbal1 = 0x31 Global Const $DRUMS_HighTom = 0x32 Global Const $DRUMS_RideCymbal1 = 0x33 Global Const $DRUMS_ChineseCymbal = 0x34 Global Const $DRUMS_RideBell = 0x35 Global Const $DRUMS_Tambourine = 0x36 Global Const $DRUMS_SplashCymbal = 0x37 Global Const $DRUMS_Cowbell = 0x38 Global Const $DRUMS_CrashSymbol2 = 0x39 Global Const $DRUMS_Vibraslap = 0x3A Global Const $DRUMS_RideCymbal2 = 0x3B Global Const $DRUMS_HiBongo = 0x3C Global Const $DRUMS_LowBongo = 0x3D Global Const $DRUMS_MuteHiConga = 0x3E Global Const $DRUMS_OpenHiConga = 0x3F Global Const $DRUMS_LowConga = 0x40 Global Const $DRUMS_HighTimbale = 0x41 Global Const $DRUMS_LowTimbale = 0x42 Global Const $DRUMS_HighAgogo = 0x43 Global Const $DRUMS_LowAgogo = 0x44 Global Const $DRUMS_Cabasa = 0x45 Global Const $DRUMS_Maracas = 0x46 Global Const $DRUMS_ShortWhistle = 0x47 Global Const $DRUMS_LongWhistle = 0x48 Global Const $DRUMS_ShortGuiro = 0x49 Global Const $DRUMS_LongGuiro = 0x4A Global Const $DRUMS_Claves = 0x4B Global Const $DRUMS_HiWoodBlock = 0x4C Global Const $DRUMS_LowWoodBlock = 0x4D Global Const $DRUMS_MuteCuica = 0x4E Global Const $DRUMS_OpenCuica = 0x4F Global Const $DRUMS_MuteTriangle = 0x50 Global Const $DRUMS_OpenTriangle = 0x51 Global Const $DRUMS_Shaker = 0x52 ; Channels ;~ Global Const $MIDI_CHANNEL_1 = 1 ; ... Global Const $MIDI_PERCUSSION_CHANNEL = 10 ; Drums etc ; ... ;~ Global Const $MIDI_CHANNEL_16 = 16 ; Min/Max Values Global Const $MIDI_MIN_VALUE = 0, $MIDI_MAX_VALUE = 0x7F, $MIDI_CENTER_VALUE = 64 Global Const $MIDI_PITCH_BEND_CENTER = 0x2000 Global Const $MIDI_PITCH_BEND_MAX = 0x3FFF ; CONTROL Messages Global Const $MIDI_CONTROL_BANK_SELECT = 0 Global Const $MIDI_CONTROL_MODULATE = 0x01 Global Const $MIDI_CONTROL_BREATH_CONTROLLER = 0x02 ; 0x03 = Undefined Global Const $MIDI_CONTROL_FOOT_CONTROLLER = 0x04 Global Const $MIDI_CONTROL_PORTAMENTO_TIME = 0x05 Global Const $MIDI_CONTROL_DATA_ENTRY_MSB = 0x06 Global Const $MIDI_CONTROL_CHANNEL_VOLUME = 0x07 Global Const $MIDI_CONTROL_BALANCE = 0x08 ; 0x09 = Undefined Global Const $MIDI_CONTROL_PAN = 0x0A Global Const $MIDI_CONTROL_EXPRESSION_CONTROLLER = 0x0B Global Const $MIDI_CONTROL_EFFECT_CONTROL_1 = 0x0C Global Const $MIDI_CONTROL_EFFECT_CONTROL_2 = 0x0D ; 0x0E, 0x0F = Undefined ; ----- GENERAL PURPOSE CONTROLLERS ------ Global Const $MIDI_CONTROL_GENERAL_PURPOSE_1 = 0x10 Global Const $MIDI_CONTROL_GENERAL_PURPOSE_2 = 0x11 Global Const $MIDI_CONTROL_GENERAL_PURPOSE_3 = 0x12 Global Const $MIDI_CONTROL_GENERAL_PURPOSE_4 = 0x13 ; 0x14 -> 0x1F = Undefined ; ----- PEDALS (4 variants): Values >= 64 are 'on', <= 63 are 'off' ------- Global Const $MIDI_CONTROL_DAMPER_PEDAL = 0x40 Global Const $MIDI_CONTROL_SUSTAIN_PEDAL = 0x40 Global Const $MIDI_CONTROL_PORTAMENTO_PEDAL = 0x41 Global Const $MIDI_CONTROL_SOSTENUTO_PEDAL = 0x42 Global Const $MIDI_CONTROL_SOFT_PEDAL = 0x43 Global Const $MIDI_CONTROL_LEGATO_FOOTSWITCH = 0x44 ; <= 63 is 'Normal', >= 64 is Legato Global Const $MIDI_CONTROL_HOLD_2 = 0x45 ; <= 63 is OFF, >= 64 is ON ; ----- SOUND CONTROLLERS ------ Global Const $MIDI_CONTROL_SOUND_CONTROLLER_1 = 0x46 ; Default: Sound Variation Global Const $MIDI_CONTROL_SOUND_CONTROLLER_2 = 0x47 ; Default: Timbre/Harmonic Intensity Global Const $MIDI_CONTROL_SOUND_CONTROLLER_3 = 0x48 ; Default: Release Time Global Const $MIDI_CONTROL_SOUND_CONTROLLER_4 = 0x49 ; Default: Attack Time Global Const $MIDI_CONTROL_SOUND_CONTROLLER_5 = 0x4A ; Default: Brightness Global Const $MIDI_CONTROL_SOUND_CONTROLLER_6 = 0x4B ; Default: Decay Time Global Const $MIDI_CONTROL_SOUND_CONTROLLER_7 = 0x4C ; Default: Vibrato Rate Global Const $MIDI_CONTROL_SOUND_CONTROLLER_8 = 0x4D ; Default: Vibrato Depth Global Const $MIDI_CONTROL_SOUND_CONTROLLER_9 = 0x4E ; Default: Vibrato Delay Global Const $MIDI_CONTROL_SOUND_CONTROLLER_10 = 0x4F ; No Default defined ; ----- GENERAL PURPOSE CONTROLLERS ------ Global Const $MIDI_CONTROL_GENERAL_PURPOSE_5 = 0x50 Global Const $MIDI_CONTROL_GENERAL_PURPOSE_6 = 0x51 Global Const $MIDI_CONTROL_GENERAL_PURPOSE_7 = 0x52 Global Const $MIDI_CONTROL_GENERAL_PURPOSE_8 = 0x53 Global Const $MIDI_CONTROL_PORTAMENTO_CONTROL = 0x54 ; 0x55 - 0x57 = Undefined Global Const $MIDI_CONTROL_HIGHRES_VELOCITY_PREFIX = 0x58 ; 0x59 - 0x5A = Undefined Global Const $MIDI_CONTROL_EFFECTS_1_DEPTH = 0x5B ; Default: Reverb Send Level (formerly External Effects Depth) Global Const $MIDI_CONTROL_EFFECTS_2_DEPTH = 0x5C ; (formerly Tremolo Depth) Global Const $MIDI_CONTROL_EFFECTS_3_DEPTH = 0x5D ; Default: Chorus Send Level (formerly Chorus Depth) Global Const $MIDI_CONTROL_EFFECTS_4_DEPTH = 0x5E ; (formerly Celeste [Detune] Depth) Global Const $MIDI_CONTROL_EFFECTS_5_DEPTH = 0x5F ; (formerly Phaser Depth) ; These are used in conjunction with other messages: Global Const $MIDI_CONTROL_DATA_INCREMENT = 0x60 ; Data Entry + 1 **Control Value: 0 Global Const $MIDI_CONTROL_DATA_DECREMENT = 0x61 ; Data Entry - 1 **Control Value: 0 ; ------ REGISTERED PARAMETER SEQUENCES ------ ; These are combined with other messages Global Const $MIDI_CONTROL_NONREGISTERED_PARAM_NUM = 0x62 ; 0x63 = Non-Registered Parameter Number using MSB Global Const $MIDI_CONTROL_REGISTERED_PARAM_NUM = 0x64 ; 0x65 = Registered Parameter Number using MSB ; 0x66 - 0x77 = Undefined ; ------ CHANNEL MODE MESSAGES ------ Global Const $MIDI_CONTROL_ALL_SOUND_OFF = 0x78 ; Control Value: 0 Global Const $MIDI_CONTROL_RESET_ALL_CONTROLLERS = 0x79 ; Control Value: 0 Global Const $MIDI_CONTROL_LOCAL_CONTROL = 0x7A ; 0 = Off, 127 = On Global Const $MIDI_CONTROL_ALL_NOTES_OFF = 0x7B ; Control Value: 0 Global Const $MIDI_CONTROL_OMNI_MODE_OFF = 0x7C ; Additionally sets All Notes OFF **Control Value: 0 Global Const $MIDI_CONTROL_OMNI_MODE_ON = 0x7D ; Additionally sets All Notes OFF **Control Value: 0 Global Const $MIDI_CONTROL_MONO_MODE_ON = 0x7E ; Additionally: All Notes OFF, Poly OFF **Control Value: 0?? (see Midi Table) Global Const $MIDI_CONTROL_POOLY_MODE_ON = 0x7F ; Additionally: All Notes OFF, Mono OFF **Control Value: 0 #include "midiudf.au3" ; Open MIDI Out $hMidiOut = _midiOutOpen(0) If @error Then ConsoleWrite("_MidiOutOpen error:"& @error & ", @extended = " & @extended & @CRLF) Exit EndIf $nMidiDevices = _MidiOutGetNumDevs() ConsoleWrite(" # Devices: " & $nMidiDevices & @CRLF) ; MIDI Devices are indexed 0 through #devices minus 1 For $i = 0 To $nMidiDevices - 1 $aCaps = _MidiOutGetDevCaps($i) ConsoleWrite("Caps Dev #"&$i&": [0] = " & $aCaps[0] & _ ; Manufacturer ID ", [1] = " & $aCaps[1] & _ ; Product ID ", [2] = " & $aCaps[2] & _ ; Driver Version ", [3] = " & $aCaps[3] & _ ; Name ", [4] = " & $aCaps[4] & _ ; If 1, then 'MOD_MIDIPORT' or MIDI Hardware Port ", [5] = " & $aCaps[5] & _ ; # of Voices (0 for Hardware Ports) ", [6] = " & $aCaps[6] & _ ; # Simultaneous Notes (0 for Hardware Ports) ", [7] = " & $aCaps[7] & _ ; Channel mask (0xFFFF = all 16 ports) ", [8] = " & $aCaps[8] &@CRLF) ; Optional Functionality Next #cs MidiSetInstrument($hMidiOut,1, 1) NoteOn($hMidiOut, 0x3C, 1, 127) Sleep(1500) ;~ NoteAfterTouch($hMidiOut, 0x3C, 1, 88) NoteOn($hMidiOut, 0x3C, 1, 127) MsgBox(0, "Aftertouched?", "AfterTouched") NotesAllOff($hMidiOut,1) #ce ; Set 3 Different Instruments to 3 different Channels: MidiSetInstrument($hMidiOut,48, 1) ; String Ensemble 1 MidiSetInstrument($hMidiOut, 52, 2) ;Choir Aah MidiSetInstrument($hMidiOut, 102, 3) ; FX Echo Drops ; String Ensemble, Channel 1 NoteOn($hMidiOut, $NOTE_C4, 1, 127) ; C4 (Middle C) ; Set Pan - extreme Left MidiControlChange($hMidiOut, $MIDI_CONTROL_PAN, 0) MsgBox(0,"String (Left)","String on Left") ; Pan Left to Right For $i = 0 To 127 MidiControlChange($hMidiOut, $MIDI_CONTROL_PAN, $i) Sleep(10) Next MsgBox(0,"Panned Left To Right", "Panned Left to Right") ; Pan Center MidiControlChange($hMidiOut, $MIDI_CONTROL_PAN, $MIDI_CENTER_VALUE) ; Modulation none - max For $i=0 To 127 MidiControlChange($hMidiOut, $MIDI_CONTROL_MODULATE, $i) Sleep(10) Next MsgBox(0,"Modulated", "Modulated 0 to 127") MidiControlChange($hMidiOut, $MIDI_CONTROL_MODULATE, 0) ; Channel Volume max - min For $i= 127 To 0 Step -1 MidiControlChange($hMidiOut, $MIDI_CONTROL_CHANNEL_VOLUME, $i) Sleep(20) Next MsgBox(0,"Volume Adjusted", "Volume Adjusted high-to-low") MidiControlChange($hMidiOut, $MIDI_CONTROL_CHANNEL_VOLUME, $MIDI_MAX_VALUE) ; Sustain - This will continue keeping notes pressed even after 'release' ; (meaning after turning off the notes) MidiControlChange($hMidiOut, $MIDI_CONTROL_SUSTAIN_PEDAL, $MIDI_MAX_VALUE - 27) ;~ NoteOff($hMidiOut, $NOTE_C4, 1) NotesAllOff($hMidiOut, 1) MsgBox(0,"Sustained","Sustained After NoteOff") MidiControlChange($hMidiOut, $MIDI_CONTROL_SUSTAIN_PEDAL, $MIDI_MIN_VALUE) MsgBox(0,"Sustain Off","Sustain OFF") NoteOn($hMidiOut, $NOTE_C4, 1, 127) #cs For $i=0 To 127 MidiControlChange($hMidiOut, 0x08, $i) Sleep(10) Next MsgBox(0,"Balanced?", "Balance 0 to 127") #ce ; Choir Aah, Channel 2 NoteOn($hMidiOut, $NOTE_C3, 2, 127) ; FX Echo Drops, Channel 3 NoteOn($hMidiOut, $NOTE_C5, 3, $MIDI_CENTER_VALUE) ; Percussion Instrument (Channel 10) ;~ NoteOn($hMidiOut, $DRUMS_AcousticBassDrum, 10, 127) PercussionOn($hMidiOut, $DRUMS_AcousticBassDrum, 127) MsgBox(0,"ALL", "ALL") ; Percussion Instrument OFf ;~ NoteOff($hMidiOut, 35, 10) PercussionOff($hMidiOut, 35) ;~ NoteOn($hMidiOut, $DRUMS_AcousticSnare, 10) PercussionOn($hMidiOut, $DRUMS_AcousticSnare) ; String Ensemble - C4 Off ;~ NoteOff($hMidiOut, 0x3C) NotesAllOff($hMidiOut) MsgBox(0,"NoString", "NoString") ; Percussion Instrument Off ;~ NoteOff($hMidiOut, 38, 10) PercussionOff($hMidiOut, 38) ; Choir Aah, ch. 2, C3 Off ;~ NoteOff($hMidiOut, 0x30, 2) NotesAllOff($hMidiOut, 2) MsgBox(0,"NoChoirAhh", "NoChoirAhh") ; FX Echo Drops, ch. 3, C5 Off ;~ NoteOff($hMidiOut, 0x48, 3) NotesAllOff($hMidiOut, 3) MsgBox(0,"NONE", "SILENCE!") ; Pitch-Bend Tests NoteOn($hMidiOut, 0x3C - 12) MsgBox(0,"Pitch-Default", "Pitch-Default") #cs For $i = 1 To 8192*2-1 Step 4 MidiPitchBend($hMidiOut, $i, 1) Next #ce MidiPitchBend($hMidiOut, $MIDI_PITCH_BEND_MAX, 1) MsgBox(0,"Pitch-bended", "Pitch-bended") ;~ MidiPitchBend($hMidiOut, $MIDI_PITCH_BEND_CENTER, 1) MidiResetControllers($hMidiOut) MsgBox(0,"Pitch-Reverted","Reverted Pitch") NotesAllOff($hMidiOut, 1) ; --- UDF Helper Functions --- ; ============================================================================================== ; Func NoteOn($hMidiOut, $nNote, $nChannel = 1, $nVelocity = 127) ; ; Turns on, or restarts, $nNote on the given Channel at the given Velocity ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nNote = Note to Turn On. Valid values are 0-127, with 60 representing Middle C (C4) ; There are 12 gradations of notes pitches (60 + 12 = C5) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; $nVelocity = Velocity to play note at. 127 is maximum volume, 64 is medium, and 0 is silent ; ; Author: Ascend4nt, based on code by Eynstyne [but more flexibility] ; ============================================================================================== Func NoteOn($hMidiOut, $nNote, $nChannel = 1, $nVelocity = 127) ;~ Local Const $NOTE_ON = 0x90 ; Adjust cut-offs for Note and Velocity (0 - 127 for each) $nVelocity = BitAND($nVelocity, 0x7F) ; Adjust cut-off for Note (0 - 127 for each) $nNote = BitAND($nNote, 0x7F) ; 0x90 = Note ON _midiOutShortMsg($hMidiOut, ($nVelocity * 65536) + ($nNote * 256) + 0x90 + BitAND($nChannel - 1, 0xF)) EndFunc ; ============================================================================================== ; Func NoteAfterTouch($hMidiOut, $nNote, $nChannel = 1, $nPressure = 64) ; ; Applies Aftertouch to a given $nNote on the given Channel at the given Velocity ; "This message is most often sent by pressing down on the key after it 'bottoms out' " ; ; Your MIDI card/controller must support this. Mine doesn't so this needs further testing.. ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nNote = Note to apply Aftertouch to. Valid values are 0-127, with 60 representing Middle C (C4) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; $nPressure = Afteroutch 'Pressure' to apply to note. 127 is max, 64 is medium, and 0 is none ; ; Author: Ascend4nt ; ============================================================================================== Func NoteAfterTouch($hMidiOut, $nNote, $nChannel = 1, $nPressure = 64) ; Adjust cut-offs for Note and Velocity (0 - 127 for each) $nPressure = BitAND($nPressure, 0x7F) ; Adjust cut-off for Note (0 - 127 for each) $nNote = BitAND($nNote, 0x7F) ; 0xA0 = Aftertouch _midiOutShortMsg($hMidiOut, ($nPressure * 65536) + ($nNote * 256) + 0xA0 + BitAND($nChannel - 1, 0xF)) EndFunc ; ============================================================================================== ; Func NoteOff($hMidiOut, $nNote, $nChannel = 1, $nVelocity = 127) ; ; Turns off $nNote on the given Channel ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nNote = Note to Turn On. Valid values are 0-127, with 60 representing Middle C (C4) ; There are 12 gradations of notes pitches (60 + 12 = C5) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; $nVelocity = Velocity to use at release. 127 is maximum volume, 64 is medium, and 0 is silent ; Not sure how this is applied at Note-Off, but it is nonetheless part of the mesage ; ; Author: Ascend4nt, based on code by Eynstyne [but corrected, and w/added ability] ; ============================================================================================== Func NoteOff($hMidiOut, $nNote, $nChannel = 1, $nVelocity = 127) ;~ Local Const $NOTE_OFF = 0x80 ; Adjust cut-off for Velocity (0 - 127) $nVelocity = BitAND($nVelocity, 0x7F) ; Adjust cut-off for Note (0 - 127 for each) $nNote = BitAND($nNote, 0x7F) ; 0x80 = Note OFF _midiOutShortMsg($hMidiOut, ($nVelocity * 65536) + ($nNote * 256) + 0x80 + BitAND($nChannel - 1, 0xF)) Endfunc ; ============================================================================================== ; Func PercussionOn($hMidiOut, $nNote, $nVelocity = 127) ; ; A 'shortcut' to playing percussion instruments on channel 10 ; This is just a wrapper for a call to NoteOn for channel 10 ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nNote = Instrument to Turn On. Valid values are 0-127 ; $nVelocity = Velocity to play instrument at. 127 is maximum volume, 64 is medium, and 0 is silent ; ; Author: Ascend4nt ; ============================================================================================== Func PercussionOn($hMidiOut, $nNote, $nVelocity = 127) Return NoteOn($hMidiOut, $nNote, 10, $nVelocity) EndFunc ; ============================================================================================== ; Func PercussionOff($hMidiOut, $nNote, $nVelocity = 127) ; ; A 'shortcut' to playing percussion instruments on channel 10 ; This is just a wrapper for a call to NoteOff for channel 10 ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nNote = Instrument to Turn On. Valid values are 0-127 ; $nVelocity = Velocity to use at release. 127 is maximum volume, 64 is medium, and 0 is silent ; Not sure how this is applied at Note-Off, but it is nonetheless part of the mesage ; ; Author: Ascend4nt ; ============================================================================================== Func PercussionOff($hMidiOut, $nNote, $nVelocity = 127) Return NoteOff($hMidiOut, $nNote, 10, $nVelocity) EndFunc ; ============================================================================================== ; Func NotesAllOff($hMidiOut, $nChannel = 1) ; ; This turns off all 'On' notes for a given channel. ; NOTE however that a 'Sustain' message will continue emitting sound for any notes ; until either sustain is turned off, or MidiAllSoundOff() is called ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; ; Author: Ascend4nt ; ============================================================================================== Func NotesAllOff($hMidiOut, $nChannel = 1) ; 0xB0 = Channel Mode Message, 7B = All Notes Off _midiOutShortMsg($hMidiOut, 0x7BB0 + BitAND($nChannel - 1, 0xF)) EndFunc ; ============================================================================================== ; Func MidiAllSoundOff($hMidiOut, $nChannel = 1) ; ; This turns off all sound for a given channel. ; This differs from NotesAllOff() in that this will additionally turn of sustained notes ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; ; Author: Ascend4nt ; ============================================================================================== Func MidiAllSoundOff($hMidiOut, $nChannel = 1) ; 0xB0 = Channel Mode Message, 78 = All Sound Off _midiOutShortMsg($hMidiOut, 0x78B0 + BitAND($nChannel - 1, 0xF)) EndFunc ; ============================================================================================== ; Func MidiResetControllers($hMidiOut, $nChannel = 1) ; ; Resets Controllers: ; Modulation, Channel & Polyphonic Pressure are set to 0 ; Pedals (Sustain (Damper), Portamento, Sostenuto, Soft Pedal) set to 0 ; PitchBend set to center ; ; See 'RP-15: Response to Reset All Controllers' ; @ http://www.midi.org/techspecs/rp15.php ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; ; Author: Ascend4nt ; ============================================================================================== Func MidiResetControllers($hMidiOut, $nChannel = 1) ; 0xB0 = Channel Mode Message, 79 = Reset All Controllers _midiOutShortMsg($hMidiOut, 0x79B0 + BitAND($nChannel - 1, 0xF)) EndFunc ; ============================================================================================== ; Func MidiPitchBend($hMidiOut, $nBendValue = 8192, $nChannel = 1) ; ; Pitch-Bends all Notes on specified channel ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nBendValue = Value from 0 - 16383. Default (no bend) is 8192 (0x2000) ; Lower than 8192 lowers pitch, Higher #'s increase pitch ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; ; The mapping of bytes appears correctly though: ; [31-24] = 0, [23] = 0, [22 - 16] = Upper 7 Bits, [15] = 0, [14 - 8] = Lower 7 Bits ; ; Author: Ascend4nt ; ============================================================================================== Func MidiPitchBend($hMidiOut, $nBendValue = 8192, $nChannel = 1) ; Min-Max Range is 14 bits If $nBendValue > 0x3FFF Or $nBendValue < 0 Then Return SetError(1,0,0) ; Low 7 Bits - Upper Byte of Lower Word Local $nLowBend = BitAND($nBendValue, 0x7F) * 256 ; Upper 7 Bits -> Move to Lower Byte of Upper Word Local $nHighBend = BitShift($nBendValue, 7) * 65536 ;~ ConsoleWrite("MidiPitchBend value = 0x" & Hex($nHighBend + $nLowBend + 0xE0 + $nChannel) & @CRLF) ; 0xE0 = Pitch Bend _midiOutShortMsg($hMidiOut, $nHighBend + $nLowBend + 0xE0 + BitAND($nChannel - 1, 0xF)) EndFunc ; ============================================================================================== ; Func MidiChannelAftertouch($hMidiOut, $nChannel = 1, $nVelocity = 127) ; ; Adjusts Channel Aftertouch. Different from Note Aftertouch ; ; See: 'MIDI Specification: Channel Pressure' ; @ http://www.blitter.com/~russtopia/MIDI/~jglatt/tech/midispec/pressure.htm ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; $nVelocity = Velocity, or pressure, value. 127 is maximum volume, 64 is medium, and 0 is none ; ; Author: Ascend4nt ; ============================================================================================== Func MidiChannelAftertouch($hMidiOut, $nChannel = 1, $nVelocity = 127) ; Adjust cut-off for Velocity (0 - 127) $nVelocity = BitAND($nVelocity, 0x7F) ; 0xD0 = Channel Pressure (AfterTouch) _midiOutShortMsg($hMidiOut, ($nVelocity * 256) + 0xD0 + BitAND($nChannel - 1, 0xF)) EndFunc ; ============================================================================================== ; Func MidiSetInstrument($hMidiOut, $nInstrument, $nChannel = 1) ; ; This sets a given instrument to a particular channel ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nInstrument = Instrument to use for the given Channel. Valid values are 0-127 ; Note that this should have no effect on Channel 10, which is percussive instruments. ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; ; Author: Eynstyne, Ascend4nt (added Channel capability, and filtering) ; ============================================================================================== Func MidiSetInstrument($hMidiOut, $nInstrument, $nChannel = 1) ; Channels are 1-16 (represented as 0-15). Channel 10 is special- percussion instruments only $nChannel = BitAND($nChannel - 1, 0xF) ; Instruments are 0 - 127 $nInstrument = BitAND($nInstrument, 0x7F) ; 0xC0 = Program Change _midiOutShortMsg($hMidiOut, ($nInstrument * 256) + 0xC0 + $nChannel) EndFunc ; ============================================================================================== ; Func MidiControlChange($hMidiOut, $nControlID, $nControlVal, $nChannel = 1) ; ; Performs various control/mode changes on the specified channel ; ; $hMidiOut = Handle to a Midi-Out device (retrieved via _MidiOutOpen() ) ; $nControlID = # of the Control Function to use (e.g. 0x0A = Pan) ; $nControlVal = Value to be used with Control Change (0 - 127) ; $nChannel = Channel to apply this to. Channels are 1-15, with 10 being percussion-only ; ; Author: Ascend4nt ; ============================================================================================== Func MidiControlChange($hMidiOut, $nControlID, $nControlVal, $nChannel = 1) ; 7-bit cut off for values $nControlID = BitAND($nControlID, 0x7F) $nControlVal = BitAND($nControlVal, 0x7F) ; 0xB0 = Control Change _midiOutShortMsg($hMidiOut, ($nControlVal * 65536) + ($nControlID * 256) + 0xB0 + BitAND($nChannel - 1, 0xF)) EndFunc *edit: Added more constants, functions, a few misc. extra tests (yes, more annoying msgbox's). Should now expose most of the capabilities of MIDI messaging. Will eventually separate the UDF from the example.. *edit: Once again, update - now its a complete package - see the >MIDIEx UDF Edited August 6, 2013 by Ascend4nt czardas 1 My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs | Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) | Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code)
czardas Posted July 27, 2013 Posted July 27, 2013 (edited) Yeah, I struggled with this. As I say: the code I wrote recently was written with a view to doing things properly - using channels, even though I wasn't sure exactly how. I've had no time recently, but will resume development of my music projects when I find the opportunity. Here's a very cool link - it's definately worth a look. As far as I know there's a newer version of midi which includes features which may not be working for you; and it's also likely that they will not be supported by many other sound cards (it's a while since I read this, so the details are a bit vague). Edited July 27, 2013 by czardas operator64 ArrayWorkshop
czardas Posted July 28, 2013 Posted July 28, 2013 (edited) You know, I never could understand the terminology used in midi. How on Earth did the term velocity get into the mix? No matter how hard I try, I can't find a reason to use this word in the context in which it's given. In air, the speed of sound is 340.29 m/s according to Google. Edit Now I understand how this turned out. The designers of midi decided that volume is a consequence of the speed your finger moves when it hits a piano key. I'm sorry: this is not only confusing, but also hilarious. Very well done to Ascend4nt for deciphering this. It has been a complete mystery to me until now. Edited July 28, 2013 by czardas operator64 ArrayWorkshop
Ascend4nt Posted July 28, 2013 Posted July 28, 2013 czardas.. I never thought about the velocity term, as I've heard it used before in regards to sound. However, looking now I don't see any dictionaries that list it! Well, good investigative work, my friend. Oh, I figured out that 'sustain' does in fact work, but it just so happened I wasn't realizing that it had to be applied, followed by note-off events, before its effect is noticed. i.e.: ; Sustain - This will continue keeping notes pressed even after 'release' ; (meaning after turning off the notes) MidiControlChange($hMidiOut, $MIDI_CONTROL_SUSTAIN_PEDAL, $MIDI_MAX_VALUE) ; This normally turns all notes off, however with sustain 'pressed', they will continue playing NotesAllOff($hMidiOut, 1) ; Disables sustain, and any notes turned off above will stop playing MidiControlChange($hMidiOut, $MIDI_CONTROL_SUSTAIN_PEDAL, $MIDI_MIN_VALUE) I think we need to revamp sandin's >Midi keyboard to allow for the use of all these extra controls, as well as percussion instruments, channels, velocity.. hrm, looks like a bit of GUI work which I loathe.. My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs | Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) | Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code)
jaberwacky Posted July 28, 2013 Posted July 28, 2013 From what I gether on the wiki volume and velocity are slightly different beasts. Wiki says this about velocity: "... a velocity value that indicates how forcefully the note was played ...". So it seems to me that I can have an instrument with a fixed low volume such as a synth that has been turned down to a low volume, then I could strike the keys forcefully all day and yet still achieve a low volume. Discuss. Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum?
AZJIO Posted July 28, 2013 Posted July 28, 2013 Might even be able to decode a MIDI file if that's the format of all messages. I too looked for this opportunity. My other projects or all
Ascend4nt Posted July 29, 2013 Posted July 29, 2013 jaberwocky, Velocity as a concept does make sense when you keep in mind that the midi Out volume and channel volume work independently of the 'velocity', or how 'hard' a key is stricken. With touch-sensitive digital keyboards, the force you use to press a key is translated into velocity over the MIDI interface. This makes sense especially with weighted keys where you don't actually have to depress the key fully.. My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs | Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) | Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code)
czardas Posted July 29, 2013 Posted July 29, 2013 (edited) From what I gether on the wiki volume and velocity are slightly different beasts. Wiki says this about velocity: "... a velocity value that indicates how forcefully the note was played ...". So it seems to me that I can have an instrument with a fixed low volume such as a synth that has been turned down to a low volume, then I could strike the keys forcefully all day and yet still achieve a low volume. Discuss. The official term is attack. Every note has an attack, a decay, a sustain and a release. The link also mentions the term (midi) velocity, but this is not standard music terminology. Edited July 29, 2013 by czardas operator64 ArrayWorkshop
Ascend4nt Posted July 29, 2013 Posted July 29, 2013 I've updated the script again. I've now incorporated all the constants to use for controller messages, as well as the notes. I've also added more functions - one for channel aftertouch, one for all-sounds-off (overrides sustain etc), and a reset-controllers function. There's additionally a 'velocity' value for NoteOff messages that I didn't have as part of the functions before. I'm not clear how this affects a 'release-key' event, but it is part of the MIDI message being sent! These additions should expose most functionality of the MIDI interface, at least individual-message-wise.. I'll get around to splitting up the script from the example eventually. I should probably split the constants out too? Hmm.. I could also include an updated midiudf, which gets rid of the incorrect note-on/off values, and has faster DLLCall's (using a DLL handle), jaberwacky 1 My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs | Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) | Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code)
czardas Posted July 29, 2013 Posted July 29, 2013 (edited) Thanks again. This represents a great breakthrough for us all, I'm pretty sure. Edited July 29, 2013 by czardas operator64 ArrayWorkshop
Edano Posted July 29, 2013 Posted July 29, 2013 is >UEZ SysInfo Clock related to this thread ? it is quite impressing i must say. [color=rgb(255,0,0);][font="'comic sans ms', cursive;"]FukuLeaks[/color][/font]
czardas Posted July 29, 2013 Posted July 29, 2013 (edited) is >UEZ SysInfo Clock related to this thread ? it is quite impressing i must say. In short - yes. See >mus++ This script still needs lots of work. Edited July 29, 2013 by czardas operator64 ArrayWorkshop
Edano Posted July 29, 2013 Posted July 29, 2013 (edited) a by-product so to say ..... amazing Edited July 29, 2013 by Edano czardas 1 [color=rgb(255,0,0);][font="'comic sans ms', cursive;"]FukuLeaks[/color][/font]
Ascend4nt Posted August 6, 2013 Posted August 6, 2013 (edited) MIDIEx UDF Okay, enough time sitting on this. Here's the new MIDIEx UDF package, consisting of three modules: MIDIFunctions.au3: This was the midiudf that Eynstyne created, except with all the fixes and adjustments made to it over time, plus the new functions that are still listed in a >prior post for MidiExTest. MIDIConstants.au3: This has all the Constants that were originally part of the midiudf, but without the incorrect NoteOn/Off message constants. It additionally has these new constants: MIDI Instruments constants MIDI Note Constants (not NoteOn/Off, but note value)DRUM (Percussion) Instrument ConstantsChannel ConstantsController Message Constants MidiExTest - the same basic UDF in the >previous post, but stripped of Constants and functions that are now part of the other two modules Here's MidiExTest as it is now, with proper includes and all. It's a lame example, but from this much can be done. There's plenty of examples of the midiudf that can easily be ported to this by adjusting the way Note messages are sent. expandcollapse popup; ==================================================================================================== ; <MidiExTest.au3> ; ; Tests of the 'Extra' functionality of the new improved (and fixed) MIDI UDF ; ; Author: Ascend4nt ; ==================================================================================================== #include "MIDIFunctions.au3" #include "MIDIConstants.au3" ; Open MIDI Out $hMidiOut = _midiOutOpen(0) If @error Then ConsoleWrite("_MidiOutOpen error:"& @error & ", @extended = " & @extended & @CRLF) Exit EndIf $nMidiDevices = _MidiOutGetNumDevs() ConsoleWrite(" # Devices: " & $nMidiDevices & @CRLF) ; MIDI Devices are indexed 0 through #devices minus 1 For $i = 0 To $nMidiDevices - 1 $aCaps = _MidiOutGetDevCaps($i) ConsoleWrite("Caps Dev #"&$i&": [0] = " & $aCaps[0] & _ ; Manufacturer ID ", [1] = " & $aCaps[1] & _ ; Product ID ", [2] = " & $aCaps[2] & _ ; Driver Version ", [3] = " & $aCaps[3] & _ ; Name ", [4] = " & $aCaps[4] & _ ; If 1, then 'MOD_MIDIPORT' or MIDI Hardware Port ", [5] = " & $aCaps[5] & _ ; # of Voices (0 for Hardware Ports) ", [6] = " & $aCaps[6] & _ ; # Simultaneous Notes (0 for Hardware Ports) ", [7] = " & $aCaps[7] & _ ; Channel mask (0xFFFF = all 16 ports) ", [8] = " & $aCaps[8] &@CRLF) ; Optional Functionality Next #cs MidiSetInstrument($hMidiOut,1, 1) NoteOn($hMidiOut, 0x3C, 1, 127) Sleep(1500) ;~ NoteAfterTouch($hMidiOut, 0x3C, 1, 88) NoteOn($hMidiOut, 0x3C, 1, 127) MsgBox(0, "Aftertouched?", "AfterTouched") NotesAllOff($hMidiOut,1) #ce ; Set 3 Different Instruments to 3 different Channels: MidiSetInstrument($hMidiOut, $INSTR_StringEnsemble1, $MIDI_CHANNEL_1) MidiSetInstrument($hMidiOut, $INSTR_ChoirAhh, $MIDI_CHANNEL_2) MidiSetInstrument($hMidiOut, $INSTR_FXEchoDrops, $MIDI_CHANNEL_3) ; String Ensemble, Channel 1 NoteOn($hMidiOut, $NOTE_C4, 1, $MIDI_MAX_VALUE) ; C4 (Middle C) ; Set Pan - extreme Left MidiControlChange($hMidiOut, $MIDI_CONTROL_PAN, 0) MsgBox(0,"String (Left)","String on Left") ; Pan Left to Right For $i = 0 To 127 MidiControlChange($hMidiOut, $MIDI_CONTROL_PAN, $i) Sleep(10) Next MsgBox(0,"Panned Left To Right", "Panned Left to Right") ; Pan Center MidiControlChange($hMidiOut, $MIDI_CONTROL_PAN, $MIDI_CENTER_VALUE) ; Modulation none - max For $i=0 To 127 MidiControlChange($hMidiOut, $MIDI_CONTROL_MODULATE, $i) Sleep(10) Next MsgBox(0,"Modulated", "Modulated 0 to 127") MidiControlChange($hMidiOut, $MIDI_CONTROL_MODULATE, 0) ; Channel Volume max - min For $i= 127 To 0 Step -1 MidiControlChange($hMidiOut, $MIDI_CONTROL_CHANNEL_VOLUME, $i) Sleep(20) Next MsgBox(0,"Volume Adjusted", "Volume Adjusted high-to-low") MidiControlChange($hMidiOut, $MIDI_CONTROL_CHANNEL_VOLUME, $MIDI_MAX_VALUE) ; Sustain - This will continue keeping notes pressed even after 'release' ; (meaning after turning off the notes) MidiControlChange($hMidiOut, $MIDI_CONTROL_SUSTAIN_PEDAL, $MIDI_MAX_VALUE - 27) ;~ NoteOff($hMidiOut, $NOTE_C4, 1) NotesAllOff($hMidiOut, 1) MsgBox(0,"Sustained","Sustained After NoteOff") MidiControlChange($hMidiOut, $MIDI_CONTROL_SUSTAIN_PEDAL, $MIDI_MIN_VALUE) MsgBox(0,"Sustain Off","Sustain OFF") NoteOn($hMidiOut, $NOTE_C4, 1, $MIDI_MAX_VALUE) #cs For $i=0 To 127 MidiControlChange($hMidiOut, 0x08, $i) Sleep(10) Next MsgBox(0,"Balanced?", "Balance 0 to 127") #ce ; Choir Aah, Channel 2 NoteOn($hMidiOut, $NOTE_C3, 2, $MIDI_MAX_VALUE) ; FX Echo Drops, Channel 3 NoteOn($hMidiOut, $NOTE_C5, 3, $MIDI_CENTER_VALUE) ; Percussion Instrument (Channel 10) ;~ NoteOn($hMidiOut, $DRUMS_AcousticBassDrum, 10, 127) PercussionOn($hMidiOut, $DRUMS_AcousticBassDrum, $MIDI_MAX_VALUE) MsgBox(0,"ALL", "ALL") ; Percussion Instrument OFf ;~ NoteOff($hMidiOut, 35, 10) PercussionOff($hMidiOut, 35) ;~ NoteOn($hMidiOut, $DRUMS_AcousticSnare, 10) PercussionOn($hMidiOut, $DRUMS_AcousticSnare) ; String Ensemble - C4 Off ;~ NoteOff($hMidiOut, 0x3C) NotesAllOff($hMidiOut) MsgBox(0,"NoString", "NoString") ; Percussion Instrument Off ;~ NoteOff($hMidiOut, 38, 10) PercussionOff($hMidiOut, 38) ; Choir Aah, ch. 2, C3 Off ;~ NoteOff($hMidiOut, 0x30, 2) NotesAllOff($hMidiOut, 2) MsgBox(0,"NoChoirAhh", "NoChoirAhh") ; FX Echo Drops, ch. 3, C5 Off ;~ NoteOff($hMidiOut, 0x48, 3) NotesAllOff($hMidiOut, 3) MsgBox(0,"NONE", "SILENCE!") ; Pitch-Bend Tests NoteOn($hMidiOut, 0x3C - 12) MsgBox(0,"Pitch-Default", "Pitch-Default") #cs For $i = 1 To 8192*2-1 Step 4 MidiPitchBend($hMidiOut, $i, 1) Next #ce MidiPitchBend($hMidiOut, $MIDI_PITCH_BEND_MAX, 1) MsgBox(0,"Pitch-bended", "Pitch-bended") ;~ MidiPitchBend($hMidiOut, $MIDI_PITCH_BEND_CENTER, 1) MidiResetControllers($hMidiOut) MsgBox(0,"Pitch-Reverted","Reverted Pitch") NotesAllOff($hMidiOut, 1) MIDIExUDF.zip Edited August 6, 2013 by Ascend4nt czardas 1 My contributions: Performance Counters in Windows - Measure CPU, Disk, Network etc Performance | Network Interface Info, Statistics, and Traffic | CPU Multi-Processor Usage w/o Performance Counters | Disk and Device Read/Write Statistics | Atom Table Functions | Process, Thread, & DLL Functions UDFs | Process CPU Usage Trackers | PE File Overlay Extraction | A3X Script Extract | File + Process Imports/Exports Information | Windows Desktop Dimmer Shade | Spotlight + Focus GUI - Highlight and Dim for Eyestrain Relief | CrossHairs (FullScreen) | Rubber-Band Boxes using GUI's (_GUIBox) | GUI Fun! | IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) | Magnifier (Vista+) Functions UDF | _DLLStructDisplay (Debug!) | _EnumChildWindows (controls etc) | _FileFindEx | _ClipGetHTML | _ClipPutHTML + ClipPutHyperlink | _FileGetShortcutEx | _FilePropertiesDialog | I/O Port Functions | File(s) Drag & Drop | _RunWithReducedPrivileges | _ShellExecuteWithReducedPrivileges | _WinAPI_GetSystemInfo | dotNETGetVersions | Drive(s) Power Status | _WinGetDesktopHandle | _StringParseParameters | Screensaver, Sleep, Desktop Lock Disable | Full-Screen Crash Recovery Wrappers/Modifications of others' contributions: _DOSWildcardsToPCRegEx (original code: RobSaunder's) | WinGetAltTabWinList (original: Authenticity) UDF's added support/programming to: _ExplorerWinGetSelectedItems | MIDIEx UDF (original code: eynstyne) (All personal code/wrappers centrally located at Ascend4nt's AutoIT Code)
loutch21 Posted July 21, 2014 Posted July 21, 2014 Hello, I used midiexeUdf function to send command Canal change to my device and it work very nice, however I do not know how to use the function to receive data with this UDF function , have you an example file to use the functions of reception data please? Thank you in advance.
kisstom Posted May 30, 2015 Posted May 30, 2015 Is there a way to create a MIDI device wich is show in the device list in windows? I would like to emulate a MIDI foot controller.Thx
JJC2 Posted August 19, 2016 Posted August 19, 2016 (edited) I know this thread is old, but I'm working with MIDI right now and am successful at reading normal MIDI in messages. But, the SYSEX part is not working. For sysex to work, one has to use use MidiInAddBuffer (with a MidiInPrepareHeader created structure) actual, according to MS you need 2. I did all that, found an example script on the German AutoItScript.de site. But no good. Does anyone have a working example for SYSEX receiving? Any help is appreciated. I have re-written all buffer and prepare functions to be up to snuff with MS latest specs (both 32-bit & 64-bit) and provided ample buffers. When I call MidiInReset(), I get MM_MIM_LONGDATA for every buffer, proofing that they ARE INDEED attached to the MidiInPort. But there is no data in them, even though I know for a fact (MIDIOX shows it) that SYSEX is coming in. I'm at a loss. Something is not adding up and I cannot figure it out. James ps. Code is attached. I must be doing something wrong with MidiInPrepareHeader (although it returns success) Sorry for it being long Marshall_Code.au3 Edited August 20, 2016 by JJC2 More info
JoeP8 Posted November 7, 2017 Posted November 7, 2017 Just wanted to say, 'thank you.' This was a tremendous amount of work. The Autoit programmer Jonathan Bennet, you, and so many here are so capable. have a blessed day.
wysocki Posted January 20, 2018 Posted January 20, 2018 Ditto that this is an old thread - but what are the alternatives?! Best to keep it all in one place. Unfortunately it looks like Ascend4nt has not been around the forum since 2014 and eynstyne hasn't checked in since 2013 (so I guess this great project is in the able hands of czardas? Anyway, I've just started a project and I need a midi controller on my touchscreen laptop. I bought a DrumBuddy drum machine (amazing!) but the UI is not optimal for me (playing keyboards) so since it supports midi, I thought I'd whip up an app with buttons on it to control the device! I got the basic app to work but as I get deeper I need some help. For openers, it seems like I need to send a GM2-ON message which I believe is a Sysex. JJC2 says above that he has had problems with getting sysex to work. Anyone know the status on this? Also, how do I send a string of parameters for GM2-ON or GM1-ON (example: f0 7e 7f 09 01 f7 )?
la_saucisse Posted June 8, 2019 Posted June 8, 2019 Hi, (excuse my poor english, I'm french) I tried this udf and create a small app that allow : step 1 : display midi devices, choose one, choose midi out chanel : ok step 2 : send a note : ok, it works, whatever on local (windows GS) or with an hardware expander. step 3 : send a sysex... and this is where it gets complicated ! I guess I have to use the _MidiOutLongMsg() func, but 2nd parameter refers to _MidiOutPrepareHeader() func's return, and I can't find any documentation to explain it. I tried the sysex message "as it" as parameter, but it failed. any idea, anybody ?
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now