Jump to content

MIDI UDF


eynstyne
 Share

Recommended Posts

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.

; ====================================================================================================
; <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 by Ascend4nt
Link to comment
Share on other sites

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 by czardas
Link to comment
Share on other sites

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 by czardas
Link to comment
Share on other sites

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..

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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..

Link to comment
Share on other sites

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 by czardas
Link to comment
Share on other sites

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),

Link to comment
Share on other sites

  • 2 weeks later...

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 Constants

    Channel Constants

    Controller 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.

; ====================================================================================================
; <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 by Ascend4nt
Link to comment
Share on other sites

  • 11 months later...

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.

Link to comment
Share on other sites

  • 10 months later...
  • 1 year later...

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 by JJC2
More info
Link to comment
Share on other sites

  • 1 year later...
  • 2 months later...

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 )?

Link to comment
Share on other sites

  • 1 year later...

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 ?

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...