Receiving MIDI System Exclusive Messages
Re: Receiving MIDI System Exclusive Messages
GM is alway a limitation. If you want to do more or you want to be more flexible use the SC an normal midi dive.
You can address every sound by a bank change command followed by a program change.
If you want to assign a CC to a special parameter you must use a SysEx command, but this is not so complicated.
you can give me your code to get more overview of you idea.
You can address every sound by a bank change command followed by a program change.
If you want to assign a CC to a special parameter you must use a SysEx command, but this is not so complicated.
you can give me your code to get more overview of you idea.
macOS Catalina 10.15.7
Re: Receiving MIDI System Exclusive Messages
Sorry for the delay to answer, but I had problems with the pc.Wolfram wrote:GM is alway a limitation. If you want to do more or you want to be more flexible use the SC an normal midi dive.
You can address every sound by a bank change command followed by a program change.
If you want to assign a CC to a special parameter you must use a SysEx command, but this is not so complicated.
you can give me your code to get more overview of you idea.
My code is very messy.
Here is a summary of what I have. But I don't see. And so, the layout must be crumbling!
Remembering that at any time, "F1" key changes the device, and "enter" plays the phrase.
Code: Select all
; --------------------
Define moc.MIDIOUTCAPS
Global MHI.MIDIHDR
Define hmo.i
Procedure PitchBend(channel, n)
Shared hmo
If n=>16 :n0$="":Else:n0$="0":EndIf
midiOutShortMsg_(hmo, Val("$00"+n0$+Hex(n)+n0$+Hex(n)+"E"+Hex(channel)))
EndProcedure
Procedure ProgramChange(channel, n)
Shared hmo
If n=>16 :n0$="":Else:n0$="0":EndIf
midiOutShortMsg_(hmo, Val("$0000"+n0$+Hex(n)+"C"+Hex(channel)))
EndProcedure
Procedure controlchange(channel, n, v)
Shared hmo
If v=>16 :v0$="":Else:v0$="0":EndIf
If n=>16 :n0$="":Else:n0$="0":EndIf
midiOutShortMsg_(hmo, Val("$00"+ v0$+Hex(v)+n0$+Hex(n)+"B"+Hex(channel)))
EndProcedure
Procedure playnote(channel, n, v)
Shared hmo
If v>9 :v0$="":Else:v0$="0":EndIf
If n>9 :n0$="":Else:n0$="0":EndIf
midiOutShortMsg_(hmo, Val("$00"+ v0$+Hex(v)+n0$+Hex(n)+"9"+Hex(channel)))
EndProcedure
Procedure stopnote(channel, n)
Shared hmo
If n>9 :n0$="":Else:n0$="0":EndIf
midiOutShortMsg_(hmo, Val("$0000"+n0$+Hex(n)+"9"+Hex(channel)))
EndProcedure
Gosub dispositivo
If Result = #MMSYSERR_NOERROR
OpenWindow(0, 0, 0, 300, 300, "Playing a simple frase")
tg2=TextGadget(#PB_Any, 10, 10, 150, 20, "Instrument number:")
sg1=SpinGadget(#PB_Any, 200, 10, 40, 20, 0, 127, #PB_Spin_Numeric)
SetActiveGadget(sg1)
SetGadgetText(sg1, "4")
SetActiveGadget(sg1)
tg3=TextGadget(#PB_Any, 10, 50, 150, 20, "Balance:")
sg2=SpinGadget(#PB_Any, 200, 50, 40, 20, 0, 127, #PB_Spin_Numeric)
SetGadgetText(sg2, "64")
tg4=TextGadget(#PB_Any, 10, 100, 100, 20, "Sysex:")
sg3=StringGadget(#PB_Any, 120, 100, 150, 20, "")
tg5=CheckBoxGadget(#PB_Any, 10, 150, 100, 20, "Pitch Bend:")
Gosub atalho
Repeat
Select WaitWindowEvent()
Case 13116
Break
Case #PB_Event_Gadget
Select EventGadget()
Case sg1
SetGadgetText(sg1, Str(GetGadgetState(sg1)))
Case sg2
SetGadgetText(sg2, Str(GetGadgetState(sg2)))
EndSelect
Case #PB_Event_Timer
Select EventTimer()
Case 1
Gosub stop
Case 2
p=p+1
If p>127
p=127
RemoveWindowTimer(0, 2)
EndIf
PitchBend(channel, p)
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case 1
Gosub play
Case 2
Gosub dispositivo
EndSelect
EndSelect
ForEver
EndIf
End
stop:
For r=50 To 73
stopnote(channel, r)
Next
RemoveWindowTimer(0, 1)
Return
play:
controlchange(channel, 10, Val(GetGadgetText(sg2)))
programchange(0, Val(GetGadgetText(sg1)))
Gosub stop
AddWindowTimer(0, 1, 2000)
If GetGadgetState(tg5)=1
AddWindowTimer(0, 2, 10)
p =64
pitchbend(channel, 64)
EndIf
For r= 50 To 71 Step 3
playnote(0, r, 70)
Delay(30)
Next
Return
atalho:
AddKeyboardShortcut(0, #PB_Shortcut_Return, 1)
AddKeyboardShortcut(0, #PB_Shortcut_F1, 2)
Return
dispositivo:
midiOutClose_(hmo)
OpenWindow(1, 0, 0, 300, 400, "Select a Midi Port")
iNumDev = midiOutGetNumDevs_()
tg1=TextGadget(#PB_Any, 10, 10, 280, 20, Str(iNumDev) + " MIDI out devices.")
lg1=ListViewGadget(#PB_Any, 10, 40, 280, 330)
For around = 0 To iNumDev - 1
midiOutGetDevCaps_(around, moc, SizeOf(MIDIOUTCAPS))
;Debug " " + Str(around) + " " + PeekS(@moc\szPname[0], #MAXPNAMELEN)
aa$=Str(around) + " " + PeekS(@moc\szPname[0], #MAXPNAMELEN)
AddGadgetItem(lg1, around, aa$)
Next
SetActiveGadget(lg1)
SetGadgetState(lg1, 0)
AddKeyboardShortcut(1, #PB_Shortcut_Return, 1)
Repeat
w=WaitWindowEvent()
Select w
Case 13116
End
Case #PB_Event_Menu
k=GetGadgetState(lg1)
If EventMenu()=1 And k>-1
Break
EndIf
EndSelect
ForEver
CloseWindow(1)
result = midiOutOpen_(@hmo, k, #Null, #Null, #CALLBACK_NULL)
Return
; --------------------
Re: Receiving MIDI System Exclusive Messages
Hi,
I allowed me to restructure your code.
I eliminate the global and shared variables.
There should only one eventloop inside the code, else you miss events.
Also Gosub is a bit outdated and makes it a bit more difficult to follow the code.
I hope you can follow my code lines:
I allowed me to restructure your code.
I eliminate the global and shared variables.
There should only one eventloop inside the code, else you miss events.
Also Gosub is a bit outdated and makes it a bit more difficult to follow the code.
I hope you can follow my code lines:
Code: Select all
EnableExplicit
;-Enumerations
Enumeration Windows
#MainWindow
#DeviceWindow
EndEnumeration
Enumeration Gadgets
#tg1
#tg2
#tg3
#tg4
#tg5
#sg1
#sg2
#sg3
#lg1
EndEnumeration
Enumeration Shortcuts
#ReturnShotcut
#F1Shortcut
EndEnumeration
Enumeration Timers
#Timer1
#Timer2
EndEnumeration
;-Procedures
Procedure PitchBend(hmo.i, channel.i, n.i)
Protected n0$
If n => 16
n0$= ""
Else
n0$="0"
EndIf
midiOutShortMsg_(hmo, Val("$00" + n0$ + Hex(n) + n0$ + Hex(n) + "E" + Hex(channel)))
EndProcedure
Procedure ProgramChange(hmo.i, channel.i, n.i)
Protected n0$
If n=>16
n0$ = ""
Else
n0$="0"
EndIf
midiOutShortMsg_(hmo, Val("$0000" + n0$ + Hex(n) + "C" + Hex(channel)))
EndProcedure
Procedure controlchange(hmo.i, channel.i, n.i, v.i)
Protected v0$, n0$
If v => 16
v0$ = ""
Else
v0$ = "0"
EndIf
If n => 16
n0$ = ""
Else
n0$ = "0"
EndIf
midiOutShortMsg_(hmo, Val("$00" + v0$ + Hex(v) + n0$ + Hex(n) + "B" + Hex(channel)))
EndProcedure
Procedure playnote(hmo.i, channel.i, n.i, v.i)
Protected v0$, n0$
If v > 9
v0$ = ""
Else
v0$ = "0"
EndIf
If n > 9
n0$ = ""
Else
n0$ = "0"
EndIf
midiOutShortMsg_(hmo, Val("$00" + v0$ + Hex(v) + n0$ + Hex(n) + "9" + Hex(channel)))
EndProcedure
Procedure stopnote(hmo.i, channel.i, n.i)
Protected n0$
If n > 9
n0$ = ""
Else
n0$ = "0"
EndIf
midiOutShortMsg_(hmo, Val("$0000" + n0$ + Hex(n) + "9" + Hex(channel)))
EndProcedure
Procedure stop(hmo.i, channel.i)
Protected r.i
For r = 50 To 73
stopnote(hmo, channel, r)
Next
RemoveWindowTimer(#MainWindow, #Timer1)
EndProcedure
Procedure play(hmo.i, channel.i)
Protected.i r, p
controlchange(hmo, channel, 10, Val(GetGadgetText(#sg2)))
programchange(hmo, channel, Val(GetGadgetText(#sg1)))
stop(hmo, channel)
AddWindowTimer(#MainWindow, #Timer1, 2000)
If GetGadgetState(#tg5) = 1
AddWindowTimer(#MainWindow, #Timer2, 10)
p = 64
pitchbend(hmo, channel, 64)
EndIf
For r = 50 To 71 Step 3
playnote(hmo, channel, r, 70)
Delay(30)
Next
EndProcedure
Procedure dispositivo(hmo.i)
Protected.i iNumDev, around, w, k, Result
Protected aa$
Protected moc.MIDIOUTCAPS
midiOutClose_(hmo)
OpenWindow(#DeviceWindow, 0, 0, 300, 400, "Select a Midi Port")
iNumDev = midiOutGetNumDevs_()
TextGadget(#tg1, 10, 10, 280, 20, Str(iNumDev) + " MIDI out devices.")
ListViewGadget(#lg1, 10, 40, 280, 330)
For around = 0 To iNumDev - 1
midiOutGetDevCaps_(around, moc, SizeOf(MIDIOUTCAPS))
;Debug " " + Str(around) + " " + PeekS(@moc\szPname[0], #MAXPNAMELEN)
aa$ = Str(around) + " " + PeekS(@moc\szPname[0], #MAXPNAMELEN)
AddGadgetItem(#lg1, around, aa$)
Next
SetActiveGadget(#lg1)
SetGadgetState(#lg1, 0)
AddKeyboardShortcut(#DeviceWindow, #PB_Shortcut_Return, #ReturnShotcut)
EndProcedure
;-Main
Define.i Result, p, Event, DeviceId, hmo, channel
OpenWindow(#MainWindow, 0, 0, 300, 300, "Playing a simple frase")
TextGadget(#tg2, 10, 10, 150, 20, "Instrument number:")
SpinGadget(#sg1, 200, 10, 40, 20, 0, 127, #PB_Spin_Numeric)
SetActiveGadget(#sg1)
SetGadgetText(#sg1, "4")
SetActiveGadget(#sg1)
TextGadget(#tg3, 10, 50, 150, 20, "Balance:")
SpinGadget(#sg2, 200, 50, 40, 20, 0, 127, #PB_Spin_Numeric)
SetGadgetText(#sg2, "64")
TextGadget(#tg4, 10, 100, 100, 20, "Sysex:")
StringGadget(#sg3, 120, 100, 150, 20, "")
CheckBoxGadget(#tg5, 10, 150, 100, 20, "Pitch Bend:")
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_Return, #ReturnShotcut)
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_F1, #F1Shortcut)
PostEvent(#PB_Event_Menu, #MainWindow, #F1Shortcut)
;-EventLoop
Repeat
Event = WaitWindowEvent()
Select EventWindow()
;-MainWindowEvents
Case #MainWindow
Select Event
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case #sg1
SetGadgetText(#sg1, Str(GetGadgetState(#sg1)))
Case #sg2
SetGadgetText(#sg2, Str(GetGadgetState(#sg2)))
EndSelect
Case #PB_Event_Timer
Select EventTimer()
Case 1
stop(hmo, channel)
Case 2
p = p + 1
If p > 127
p = 127
RemoveWindowTimer(#MainWindow, #Timer2)
EndIf
PitchBend(hmo, channel, p)
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case #ReturnShotcut
play(hmo, channel)
Case #F1Shortcut
DisableWindow(#MainWindow, #True)
dispositivo(hmo)
EndSelect
EndSelect
;-DeviceWindowEvents
Case #DeviceWindow
Select Event
Case #PB_Event_CloseWindow
CloseWindow(#DeviceWindow)
DisableWindow(#MainWindow, #False)
SetActiveWindow(#MainWindow)
Case #PB_Event_Menu
DeviceId = GetGadgetState(#lg1)
If EventMenu() = #ReturnShotcut And DeviceId > -1
result = midiOutOpen_(@hmo, DeviceId, #Null, #Null, #CALLBACK_NULL)
If Result <> #MMSYSERR_NOERROR
EndIf
PostEvent(#PB_Event_CloseWindow, #DeviceWindow, 0)
EndIf
EndSelect
EndSelect
ForEver
Re: Receiving MIDI System Exclusive Messages
Although the code was better fixed as above, it was not working properly.infratec wrote:Hi,
I allowed me to restructure your code.
I eliminate the global and shared variables.
There should only one eventloop inside the code, else you miss events.
Also Gosub is a bit outdated and makes it a bit more difficult to follow the code.
I hope you can follow my code lines:
The sound was without pause after 2 seconds.
The pitch was not working.
With the "pitch" option checked, the sound only lasted a few seconds.
I tried not to change much of the current structure, but I made some corrections.
Now it works just like the old code, but not confusing like I did the first time.
Additions and changes are commented.
Code: Select all
EnableExplicit
Global p ;I added this line
;-Enumerations
Enumeration Windows
#MainWindow
#DeviceWindow
EndEnumeration
Enumeration Gadgets
#tg1
#tg2
#tg3
#tg4
#tg5
#sg1
#sg2
#sg3
#lg1
EndEnumeration
Enumeration Shortcuts
#ReturnShotcut
#F1Shortcut
EndEnumeration
Enumeration Timers
#Timer1
#Timer2
EndEnumeration
;-Procedures
Procedure PitchBend(hmo.i, channel.i, n.i)
Protected n0$
If n => 16
n0$= ""
Else
n0$="0"
EndIf
midiOutShortMsg_(hmo, Val("$00" + n0$ + Hex(n) + n0$ + Hex(n) + "E" + Hex(channel)))
EndProcedure
Procedure ProgramChange(hmo.i, channel.i, n.i)
Protected n0$
If n=>16
n0$ = ""
Else
n0$="0"
EndIf
midiOutShortMsg_(hmo, Val("$0000" + n0$ + Hex(n) + "C" + Hex(channel)))
EndProcedure
Procedure controlchange(hmo.i, channel.i, n.i, v.i)
Protected v0$, n0$
If v => 16
v0$ = ""
Else
v0$ = "0"
EndIf
If n => 16
n0$ = ""
Else
n0$ = "0"
EndIf
midiOutShortMsg_(hmo, Val("$00" + v0$ + Hex(v) + n0$ + Hex(n) + "B" + Hex(channel)))
EndProcedure
Procedure playnote(hmo.i, channel.i, n.i, v.i)
Protected v0$, n0$
If v > 15
v0$ = ""
Else
v0$ = "0"
EndIf
If n > 15
n0$ = ""
Else
n0$ = "0"
EndIf
midiOutShortMsg_(hmo, Val("$00" + v0$ + Hex(v) + n0$ + Hex(n) + "9" + Hex(channel)))
EndProcedure
Procedure stopnote(hmo.i, channel.i, n.i)
Protected n0$
If n > 15
n0$ = ""
Else
n0$ = "0"
EndIf
midiOutShortMsg_(hmo, Val("$0000" + n0$ + Hex(n) + "9" + Hex(channel)))
EndProcedure
Procedure stop(hmo.i, channel.i)
Protected r.i
For r = 50 To 73
stopnote(hmo, channel, r)
Next
RemoveWindowTimer(#MainWindow, #Timer1)
EndProcedure
Procedure play(hmo.i, channel.i)
Protected.i r
controlchange(hmo, channel, 10, Val(GetGadgetText(#sg2)))
programchange(hmo, channel, Val(GetGadgetText(#sg1)))
stop(hmo, channel)
AddWindowTimer(#MainWindow, #Timer1, 2000)
If GetGadgetState(#tg5) = 1
AddWindowTimer(#MainWindow, #Timer2, 10)
EndIf
p=64
pitchbend(hmo, channel, 64)
For r = 50 To 71 Step 3
playnote(hmo, channel, r, 70)
Delay(30)
Next
EndProcedure
Procedure dispositivo(hmo.i)
Protected.i iNumDev, around, w, k, Result
Protected aa$
Protected moc.MIDIOUTCAPS
midiOutClose_(hmo)
OpenWindow(#DeviceWindow, 0, 0, 300, 400, "Select a Midi Port")
iNumDev = midiOutGetNumDevs_()
TextGadget(#tg1, 10, 10, 280, 20, Str(iNumDev) + " MIDI out devices.")
ListViewGadget(#lg1, 10, 40, 280, 330)
For around = 0 To iNumDev - 1
midiOutGetDevCaps_(around, moc, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lg1, around, Str(around) + " " + PeekS(@moc\szPname[0], #MAXPNAMELEN))
Next
SetActiveGadget(#lg1)
SetGadgetState(#lg1, 0)
AddKeyboardShortcut(#DeviceWindow, #PB_Shortcut_Return, #ReturnShotcut)
EndProcedure
;-Main
Define.i Result, Event, DeviceId, hmo, channel ;I removed the "p" variable from here
OpenWindow(#MainWindow, 0, 0, 300, 300, "Playing a simple frase")
TextGadget(#tg2, 10, 10, 150, 20, "Instrument number:")
SpinGadget(#sg1, 200, 10, 40, 20, 0, 127, #PB_Spin_Numeric)
SetActiveGadget(#sg1)
SetGadgetText(#sg1, "4")
SetActiveGadget(#sg1)
TextGadget(#tg3, 10, 50, 150, 20, "Balance:")
SpinGadget(#sg2, 200, 50, 40, 20, 0, 127, #PB_Spin_Numeric)
SetGadgetText(#sg2, "64")
TextGadget(#tg4, 10, 100, 100, 20, "Sysex:")
StringGadget(#sg3, 120, 100, 150, 20, "")
CheckBoxGadget(#tg5, 10, 150, 100, 20, "Pitch Bend:")
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_Return, #ReturnShotcut)
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_F1, #F1Shortcut)
PostEvent(#PB_Event_Menu, #MainWindow, #F1Shortcut)
;-EventLoop
Repeat
Event = WaitWindowEvent()
Select EventWindow()
;-MainWindowEvents
Case #MainWindow
Select Event
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case #sg1
SetGadgetText(#sg1, Str(GetGadgetState(#sg1)))
Case #sg2
SetGadgetText(#sg2, Str(GetGadgetState(#sg2)))
EndSelect
Case #PB_Event_Timer
Select EventTimer()
Case #Timer1 ;I changed here
stop(hmo, channel)
Case #timer2 ;I changed here too!
p = p + 1
If p > 127
p = 127
RemoveWindowTimer(#MainWindow, #Timer2)
EndIf
PitchBend(hmo, channel, p)
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case #ReturnShotcut
play(hmo, channel)
Case #F1Shortcut
DisableWindow(#MainWindow, #True)
dispositivo(hmo)
EndSelect
EndSelect
;-DeviceWindowEvents
Case #DeviceWindow
Select Event
Case #PB_Event_CloseWindow
CloseWindow(#DeviceWindow)
DisableWindow(#MainWindow, #False)
SetActiveWindow(#MainWindow)
Case #PB_Event_Menu
DeviceId = GetGadgetState(#lg1)
If EventMenu() = #ReturnShotcut And DeviceId > -1
result = midiOutOpen_(@hmo, DeviceId, #Null, #Null, #CALLBACK_NULL)
;two old lines removed from here
PostEvent(#PB_Event_CloseWindow, #DeviceWindow, 0)
EndIf
EndSelect
EndSelect
ForEver
Re: Receiving MIDI System Exclusive Messages
If you were able to understand the code, and you do, I would like to know how it is possible to make sysex work in this code, such as controlchange, pitchbender, programchange, etc.
If this is really possible !!!
Grateful for what you've done so far.
If this is really possible !!!
Grateful for what you've done so far.
Re: Receiving MIDI System Exclusive Messages
For sysex you need midiOutLongMsgMarcosPC wrote:If you were able to understand the code, and you do, I would like to know how it is possible to make sysex work in this code, such as controlchange, pitchbender, programchange, etc.
If this is really possible !!!
Grateful for what you've done so far.
so it should look like this.
Code: Select all
sizeOfSysExMessage.a = 8
Dim sysexMessage.a(sizeOfSysExMessage -1)
sysexMessage(0) = $F0
sysexMessage(1) = xx
sysexMessage(2) = xx
sysexMessage(3) = xx
sysexMessage(4) = xx
sysexMessage(5) = xx
sysexMessage(6) = xx
sysexMessage(7) = $F7
midiOutLongMsg_(hmo, @sysexMessage(), sizeOfSysExMessage)
macOS Catalina 10.15.7
Re: Receiving MIDI System Exclusive Messages
SysEx for the Mastervolume (max 16383)
Set it to 10000 to get a quick difference.
Set it to 10000 to get a quick difference.
Code: Select all
EnableExplicit
;-Enumerations
Enumeration Windows
#MainWindow
#DeviceWindow
EndEnumeration
Enumeration Gadgets
#tg1
#tg2
#tg3
#tg4
#tg5
#sg1
#sg2
#sg3
#lg1
EndEnumeration
Enumeration Shortcuts
#ReturnShotcut
#F1Shortcut
EndEnumeration
Enumeration Timers
#Timer1
#Timer2
EndEnumeration
;-Procedures
Procedure PitchBend(hmo.i, channel.i, n.i)
midiOutShortMsg_(hmo, Val("$00" + RSet(Hex(n & $7F), 2, "0") + RSet(Hex(n >> 7), 2, "0") + "E" + Hex(channel))) ; E = 1110 PITCH BEND
EndProcedure
Procedure ProgramChange(hmo.i, channel.i, n.i)
midiOutShortMsg_(hmo, Val("$0000" + RSet(Hex(n), 2, "0") + "C" + Hex(channel))) ; C = 1100 PROGRAMM CHANGE
EndProcedure
Procedure controlchange(hmo.i, channel.i, n.i, v.i)
midiOutShortMsg_(hmo, Val("$00" + RSet(Hex(v), 2, "0") + RSet(Hex(n), 2, "0") + "B" + Hex(channel))) ; B = 1011 CONTROLLER
EndProcedure
Procedure playnote(hmo.i, channel.i, n.i, v.i)
midiOutShortMsg_(hmo, Val("$00" + RSet(Hex(v), 2, "0") + RSet(Hex(n), 2, "0") + "9" + Hex(channel))) ; 9 = 1001 NOTE ON
EndProcedure
Procedure stopnote(hmo.i, channel.i, n.i)
midiOutShortMsg_(hmo, Val("$0000" + RSet(Hex(n), 2, "0") + "8" + Hex(channel))) ; 8 = 1000 NOTE OFF
EndProcedure
Procedure SysEXVolume(hmo.i, Volume.i)
Protected *SysExBuffer
Protected MIDIHeader.MIDIHDR
If Volume > $3FFF
Volume = $3FFF
EndIf
*SysExBuffer = AllocateMemory(8)
If *SysExBuffer
PokeA(*SysExBuffer + 0, $F0) ; SysEx
PokeA(*SysExBuffer + 1, $7F) ; Realtime
PokeA(*SysExBuffer + 2, $7F) ; Channel (disregard)
PokeA(*SysExBuffer + 3, $04) ; SubID (Device Control)
PokeA(*SysExBuffer + 4, $01) ; SubID2 (Master Volume)
PokeA(*SysExBuffer + 5, Volume & $7F) ; Volume lower 7 bits
PokeA(*SysExBuffer + 6, Volume >> 7) ; Volume upper 7 bits
PokeA(*SysExBuffer + 7, $F7) ; SysEx End
;ShowMemoryViewer(*SysExBuffer, MemorySize(*SysExBuffer))
MIDIHeader\lpData = *SysExBuffer
MIDIHeader\dwBufferLength = MemorySize(*SysExBuffer)
MIDIHeader\dwFlags = 0
midiOutPrepareHeader_(hmo, @MIDIHeader, SizeOf(MIDIHDR))
;CopyMemory(*SysExBuffer, MIDIHeader\lpData, MemorySize(*SysExBuffer))
midiOutLongMsg_(hmo, @MIDIheader, SizeOf(MIDIHDR))
FreeMemory(*SysExBuffer)
EndIf
EndProcedure
Procedure stop(hmo.i, channel.i)
Protected r.i
For r = 50 To 73
stopnote(hmo, channel, r)
Next
RemoveWindowTimer(#MainWindow, #Timer1)
EndProcedure
Procedure play(hmo.i, channel.i)
Protected.i r
controlchange(hmo, channel, 10, GetGadgetState(#sg2)) ; 10 = pan
programchange(hmo, channel, Val(GetGadgetText(#sg1)))
stop(hmo, channel)
AddWindowTimer(#MainWindow, #Timer1, 2000)
If GetGadgetState(#tg5) = 1
AddWindowTimer(#MainWindow, #Timer2, 5)
EndIf
pitchbend(hmo, channel, $2000)
For r = 50 To 71 Step 3
playnote(hmo, channel, r, 70)
Delay(30)
Next
EndProcedure
Procedure dispositivo(hmo.i)
Protected.i iNumDev, around, w, k, Result
Protected aa$
Protected moc.MIDIOUTCAPS
midiOutClose_(hmo)
OpenWindow(#DeviceWindow, 0, 0, 300, 400, "Select a Midi Port")
iNumDev = midiOutGetNumDevs_()
TextGadget(#tg1, 10, 10, 280, 20, Str(iNumDev) + " MIDI out devices.")
ListViewGadget(#lg1, 10, 40, 280, 330)
For around = 0 To iNumDev - 1
midiOutGetDevCaps_(around, moc, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lg1, around, Str(around) + " " + PeekS(@moc\szPname[0], #MAXPNAMELEN))
Next
SetActiveGadget(#lg1)
SetGadgetState(#lg1, 0)
AddKeyboardShortcut(#DeviceWindow, #PB_Shortcut_Return, #ReturnShotcut)
EndProcedure
;-Main
Define.i Result, Event, DeviceId, hmo, channel, p
OpenWindow(#MainWindow, 0, 0, 300, 300, "Playing a simple frase")
TextGadget(#tg2, 10, 10, 150, 20, "Instrument number:")
SpinGadget(#sg1, 200, 10, 40, 20, 0, 127, #PB_Spin_Numeric)
SetActiveGadget(#sg1)
SetGadgetText(#sg1, "4")
SetActiveGadget(#sg1)
TextGadget(#tg3, 10, 50, 150, 20, "Balance:")
TrackBarGadget(#sg2, 120, 50, 150, 20, 0, 128)
SetGadgetState(#sg2, 64)
TextGadget(#tg4, 10, 100, 100, 20, "SysexVolume:")
SpinGadget(#sg3, 120, 100, 150, 20, 0, 16383, #PB_Spin_Numeric)
SetGadgetText(#sg3, "16383")
CheckBoxGadget(#tg5, 10, 150, 100, 20, "Pitch Bend:")
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_Return, #ReturnShotcut)
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_F1, #F1Shortcut)
PostEvent(#PB_Event_Menu, #MainWindow, #F1Shortcut)
;-EventLoop
Repeat
Event = WaitWindowEvent()
Select EventWindow()
;-MainWindowEvents
Case #MainWindow
Select Event
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case #sg1
SetGadgetText(#sg1, Str(GetGadgetState(#sg1)))
Case #sg2
SetGadgetText(#sg2, Str(GetGadgetState(#sg2)))
EndSelect
Case #PB_Event_Timer
Select EventTimer()
Case #Timer1
stop(hmo, channel)
RemoveWindowTimer(#MainWindow, #Timer2)
Case #Timer2
p = p + 1
PitchBend(hmo, channel, $2000 + p)
If p = $1FFF Or p = -$1FFF
RemoveWindowTimer(#MainWindow, #Timer2)
EndIf
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case #ReturnShotcut
If GetGadgetText(#sg3) <> ""
SysEXVolume(hmo, Val(GetGadgetText(#sg3)))
EndIf
play(hmo, channel)
p = 0
Case #F1Shortcut
DisableWindow(#MainWindow, #True)
dispositivo(hmo)
EndSelect
EndSelect
;-DeviceWindowEvents
Case #DeviceWindow
Select Event
Case #PB_Event_CloseWindow
CloseWindow(#DeviceWindow)
DisableWindow(#MainWindow, #False)
SetActiveWindow(#MainWindow)
Case #PB_Event_Menu
DeviceId = GetGadgetState(#lg1)
If EventMenu() = #ReturnShotcut And DeviceId > -1
result = midiOutOpen_(@hmo, DeviceId, #Null, #Null, #CALLBACK_NULL)
;two old lines removed from here
PostEvent(#PB_Event_CloseWindow, #DeviceWindow, 0)
EndIf
EndSelect
EndSelect
ForEver
Last edited by infratec on Wed Feb 19, 2020 8:18 am, edited 1 time in total.
Re: Receiving MIDI System Exclusive Messages
I am very grateful for everyone's effort to help me.
Unfortunately my computer stopped playing soundcanvas exclusive messages.
I am trying to correct this problem.
Even so, I am already quite optimistic about the codes provided, and I believe that my little mind opens up to this feature unknown to me.
As soon as I put everything to work, I'll post my complete code.
I look forward to everything being resolved.
Unfortunately my computer stopped playing soundcanvas exclusive messages.
I am trying to correct this problem.
Even so, I am already quite optimistic about the codes provided, and I believe that my little mind opens up to this feature unknown to me.
As soon as I put everything to work, I'll post my complete code.
I look forward to everything being resolved.
Re: Receiving MIDI System Exclusive Messages
The pc problem has been solved, and the Roland demo songs using Sysex messages are already working perfectly on the windows media player.
I tested the complete posted code of Infratec.
The code works well with the yamaha vst: (syxg50). Although I did not enter any value. Just what was already. Both Yamaha and Roland vst.
However, Roland's SoundCanvas executes the phrase only once, and stops the program.
Debug does not indicate an error line or the like. Simply stop, and the fields (gadgets) are empty.
Taking a step by step, I realized that the program stops when executing the following line inside the procedure "SysEXVolume":
midiOutLongMsg_ (hmo, @MIDIheader, SizeOf (MIDIHDR))
But if I press "Enter" before the sentence ends, it repeats. If the sound ends and I press "Enter", literally nothing happens.
Going deeper, I saw that when I choose soundcanvas, the program vsthost64.exe is run in the background. However, if you use yamaha sxg50, vsthost32.exe is run.
When the sentence is executed for the first time, windows displays the error message, saying "foo_midi VST host bridge" has stopped working and needs to be closed. Even so, the program continues to respond to events. It only stops when I try to execute the sentence a second time.
Just remembering! It is only a problem when I use SoundCanvas. I'm looking for another 64bit vst even though it's a demo version just for testing.
As this is a part of the code that I don't quite understand, I don't know how to understand what is causing this shutdown.
If anyone can help me I would appreciate it, as this is a part of the code that I am trying to research, but I think it would take too long to find a solution alone.
I tested the complete posted code of Infratec.
The code works well with the yamaha vst: (syxg50). Although I did not enter any value. Just what was already. Both Yamaha and Roland vst.
However, Roland's SoundCanvas executes the phrase only once, and stops the program.
Debug does not indicate an error line or the like. Simply stop, and the fields (gadgets) are empty.
Taking a step by step, I realized that the program stops when executing the following line inside the procedure "SysEXVolume":
midiOutLongMsg_ (hmo, @MIDIheader, SizeOf (MIDIHDR))
But if I press "Enter" before the sentence ends, it repeats. If the sound ends and I press "Enter", literally nothing happens.
Going deeper, I saw that when I choose soundcanvas, the program vsthost64.exe is run in the background. However, if you use yamaha sxg50, vsthost32.exe is run.
When the sentence is executed for the first time, windows displays the error message, saying "foo_midi VST host bridge" has stopped working and needs to be closed. Even so, the program continues to respond to events. It only stops when I try to execute the sentence a second time.
Just remembering! It is only a problem when I use SoundCanvas. I'm looking for another 64bit vst even though it's a demo version just for testing.
As this is a part of the code that I don't quite understand, I don't know how to understand what is causing this shutdown.
If anyone can help me I would appreciate it, as this is a part of the code that I am trying to research, but I think it would take too long to find a solution alone.
Re: Receiving MIDI System Exclusive Messages
I modified the sysex part a bit.
try it
try it
Code: Select all
EnableExplicit
;-Enumerations
Enumeration Windows
#MainWindow
#DeviceWindow
EndEnumeration
Enumeration Gadgets
#tg1
#tg2
#tg3
#tg4
#tg5
#sg1
#sg2
#sg3
#lg1
EndEnumeration
Enumeration Shortcuts
#ReturnShotcut
#F1Shortcut
EndEnumeration
Enumeration Timers
#Timer1
#Timer2
EndEnumeration
;-Procedures
Procedure PitchBend(hmo.i, channel.i, n.i)
midiOutShortMsg_(hmo, Val("$00" + RSet(Hex(n & $7F), 2, "0") + RSet(Hex(n >> 7), 2, "0") + "E" + Hex(channel))) ; E = 1110 PITCH BEND
EndProcedure
Procedure ProgramChange(hmo.i, channel.i, n.i)
midiOutShortMsg_(hmo, Val("$0000" + RSet(Hex(n), 2, "0") + "C" + Hex(channel))) ; C = 1100 PROGRAMM CHANGE
EndProcedure
Procedure controlchange(hmo.i, channel.i, n.i, v.i)
midiOutShortMsg_(hmo, Val("$00" + RSet(Hex(v), 2, "0") + RSet(Hex(n), 2, "0") + "B" + Hex(channel))) ; B = 1011 CONTROLLER
EndProcedure
Procedure playnote(hmo.i, channel.i, n.i, v.i)
midiOutShortMsg_(hmo, Val("$00" + RSet(Hex(v), 2, "0") + RSet(Hex(n), 2, "0") + "9" + Hex(channel))) ; 9 = 1001 NOTE ON
EndProcedure
Procedure stopnote(hmo.i, channel.i, n.i)
midiOutShortMsg_(hmo, Val("$0000" + RSet(Hex(n), 2, "0") + "8" + Hex(channel))) ; 8 = 1000 NOTE OFF
EndProcedure
Procedure SysEXVolume(hmo.i, Volume.i)
Protected MIDIHeader.MIDIHDR
If Volume > $3FFF
Volume = $3FFF
EndIf
MIDIHeader\lpData = AllocateMemory(8)
If MIDIHeader\lpData
PokeA(MIDIHeader\lpData + 0, $F0) ; SysEx
PokeA(MIDIHeader\lpData + 1, $7F) ; Realtime
PokeA(MIDIHeader\lpData + 2, $7F) ; Channel (disregard)
PokeA(MIDIHeader\lpData + 3, $04) ; SubID (Device Control)
PokeA(MIDIHeader\lpData + 4, $01) ; SubID2 (Master Volume)
PokeA(MIDIHeader\lpData + 5, Volume & $7F) ; Volume lower 7 bits
PokeA(MIDIHeader\lpData + 6, Volume >> 7) ; Volume upper 7 bits
PokeA(MIDIHeader\lpData + 7, $F7) ; SysEx End
MIDIHeader\dwBufferLength = MemorySize(MIDIHeader\lpData)
MIDIHeader\dwFlags = 0
midiOutPrepareHeader_(hmo, @MIDIHeader, SizeOf(MIDIHDR))
midiOutLongMsg_(hmo, @MIDIheader, SizeOf(MIDIHDR))
;Unprepare the buffer And MIDIHDR
While midiOutUnprepareHeader_(hmo, @MIDIHeader, SizeOf(MIDIHDR)) = #MIDIERR_STILLPLAYING
Delay(3)
Debug "Unprepeare"
Wend
FreeMemory(MIDIHeader\lpData)
EndIf
EndProcedure
Procedure stop(hmo.i, channel.i)
Protected r.i
For r = 50 To 73
stopnote(hmo, channel, r)
Next
RemoveWindowTimer(#MainWindow, #Timer1)
EndProcedure
Procedure play(hmo.i, channel.i)
Protected.i r
controlchange(hmo, channel, 10, GetGadgetState(#sg2)) ; 10 = pan
programchange(hmo, channel, Val(GetGadgetText(#sg1)))
stop(hmo, channel)
AddWindowTimer(#MainWindow, #Timer1, 2000)
If GetGadgetState(#tg5) = 1
AddWindowTimer(#MainWindow, #Timer2, 5)
EndIf
pitchbend(hmo, channel, $2000)
For r = 50 To 71 Step 3
playnote(hmo, channel, r, 70)
Delay(30)
Next
EndProcedure
Procedure dispositivo(hmo.i)
Protected.i iNumDev, around, w, k, Result
Protected aa$
Protected moc.MIDIOUTCAPS
midiOutClose_(hmo)
OpenWindow(#DeviceWindow, 0, 0, 300, 400, "Select a Midi Port")
iNumDev = midiOutGetNumDevs_()
TextGadget(#tg1, 10, 10, 280, 20, Str(iNumDev) + " MIDI out devices.")
ListViewGadget(#lg1, 10, 40, 280, 330)
For around = 0 To iNumDev - 1
midiOutGetDevCaps_(around, moc, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lg1, around, Str(around) + " " + PeekS(@moc\szPname[0], #MAXPNAMELEN))
Next
SetActiveGadget(#lg1)
SetGadgetState(#lg1, 0)
AddKeyboardShortcut(#DeviceWindow, #PB_Shortcut_Return, #ReturnShotcut)
EndProcedure
;-Main
Define.i Result, Event, DeviceId, hmo, channel, p
OpenWindow(#MainWindow, 0, 0, 300, 300, "Playing a simple frase")
TextGadget(#tg2, 10, 10, 150, 20, "Instrument number:")
SpinGadget(#sg1, 200, 10, 40, 20, 0, 127, #PB_Spin_Numeric)
SetActiveGadget(#sg1)
SetGadgetText(#sg1, "4")
SetActiveGadget(#sg1)
TextGadget(#tg3, 10, 50, 150, 20, "Balance:")
TrackBarGadget(#sg2, 120, 50, 150, 20, 0, 128)
SetGadgetState(#sg2, 64)
TextGadget(#tg4, 10, 100, 100, 20, "SysexVolume:")
SpinGadget(#sg3, 120, 100, 150, 20, 0, 16383, #PB_Spin_Numeric)
SetGadgetText(#sg3, "16383")
CheckBoxGadget(#tg5, 10, 150, 100, 20, "Pitch Bend:")
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_Return, #ReturnShotcut)
AddKeyboardShortcut(#MainWindow, #PB_Shortcut_F1, #F1Shortcut)
PostEvent(#PB_Event_Menu, #MainWindow, #F1Shortcut)
;-EventLoop
Repeat
Event = WaitWindowEvent()
Select EventWindow()
;-MainWindowEvents
Case #MainWindow
Select Event
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
Select EventGadget()
Case #sg1
SetGadgetText(#sg1, Str(GetGadgetState(#sg1)))
Case #sg2
SetGadgetText(#sg2, Str(GetGadgetState(#sg2)))
EndSelect
Case #PB_Event_Timer
Select EventTimer()
Case #Timer1
stop(hmo, channel)
RemoveWindowTimer(#MainWindow, #Timer2)
Case #Timer2
p = p + 1
PitchBend(hmo, channel, $2000 + p)
If p = $1FFF Or p = -$1FFF
RemoveWindowTimer(#MainWindow, #Timer2)
EndIf
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case #ReturnShotcut
If GetGadgetText(#sg3) <> ""
SysEXVolume(hmo, Val(GetGadgetText(#sg3)))
EndIf
play(hmo, channel)
p = 0
Case #F1Shortcut
DisableWindow(#MainWindow, #True)
dispositivo(hmo)
EndSelect
EndSelect
;-DeviceWindowEvents
Case #DeviceWindow
Select Event
Case #PB_Event_CloseWindow
CloseWindow(#DeviceWindow)
DisableWindow(#MainWindow, #False)
SetActiveWindow(#MainWindow)
Case #PB_Event_Menu
DeviceId = GetGadgetState(#lg1)
If EventMenu() = #ReturnShotcut And DeviceId > -1
result = midiOutOpen_(@hmo, DeviceId, #Null, #Null, #CALLBACK_NULL)
;two old lines removed from here
PostEvent(#PB_Event_CloseWindow, #DeviceWindow, 0)
EndIf
EndSelect
EndSelect
ForEver
Re: Receiving MIDI System Exclusive Messages
OK! My mistake!
In another program that I did in another language, it gave a similar error in windows.
I used the 32bit version of soundcanvas, and it doesn't crash.
That is, my operating system has a problem with the 64-bit host version.
I have a laptop with windows 7 64bit installed, and I'll see if there is a problem there too.
Regardless, what I wanted was to make soundcanvas work with sysex, and this is already happening in the 32bit version.
In another program that I did in another language, it gave a similar error in windows.
I used the 32bit version of soundcanvas, and it doesn't crash.
That is, my operating system has a problem with the 64-bit host version.
I have a laptop with windows 7 64bit installed, and I'll see if there is a problem there too.
Regardless, what I wanted was to make soundcanvas work with sysex, and this is already happening in the 32bit version.
-
- User
- Posts: 40
- Joined: Wed Oct 06, 2010 9:37 pm
Re: Receiving MIDI System Exclusive Messages
Hi Khorus! After a long break I started coding again. Managed to send short MIDI messages to control my synth but I am failing to receive SYSEX DUMP. Tried you code by putting it amongst code that is working (receiving MIDI notes). Would you be kind to see what I did wrong?
Code: Select all
;Incoming SYSEX Tryout.
#WinMIDIrequester=1
Enumeration GADGETS
#txtOutputDevices=1
#txtInputDevices
#lgtOutputDevices
#lgtInputDevices
#btnOK
#btnCancel
#frgFrame
#txtVersion
#txttech
#txtMaxVoice
#txtPoly
EndEnumeration
Structure MIDI
MIDIIn.A
MIDIOut.A
Stat.A
Dat1.A
Dat2.A
EndStructure
Global MidiHeader.MIDIHDR
Global hMiP0.l = 0
Global *SysexBuffer = AllocateMemory(4096)
Global _MIDI.MIDI
Global Dim arrSysexMessage.a(9)
Procedure MIDIRequester(*OutDevice, *InDevice)
Define MaxOutDev, MaxInDev, InfoOut.MIDIOUTCAPS,InfoIn.MIDIINCAPS, a, OutDev, InDev, Quit, OK, TmpS.s, EventID
#MOD_WAVETABLE = 6
#MOD_SWSYNTH = 7
#MIDIRequ_InSet = 2
#MIDIRequ_OutSet = 1
#Width = 400
If OpenWindow(#WinMIDIrequester, 0, 0, #Width, 270, "MIDI-Requester Sel MIDI-modem etc slot that you want to use.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
#Column = (#Width - 20) / 2
#Offset = (#Width / 2) + 5
TextGadget(#txtOutputDevices, 5, 5, #Column, 18, "Output-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtOutputDevices, 5, 23, #Column, 100)
MaxOutDev = midiOutGetNumDevs_()
InfoOut.MIDIOUTCAPS
If MaxOutDev
For a = -1 To MaxOutDev - 1
midiOutGetDevCaps_(a, InfoOut, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lgtOutputDevices, -1, PeekS(@InfoOut\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtOutputDevices, -1, "(no output device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","1")
TextGadget(#txtInputDevices, #Offset, 5, #Column, 18, "Input-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtInputDevices, #Offset, 23, #Column, 100)
MaxInDev = midiInGetNumDevs_()
InfoIn.MIDIINCAPS
If MaxInDev
For a = 0 To MaxInDev - 1
midiInGetDevCaps_(a, InfoIn, SizeOf(MIDIINCAPS))
AddGadgetItem(#lgtInputDevices, -1, PeekS(@InfoIn\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtInputDevices, -1, "(no input device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","2")
ButtonGadget(#btnOK, 5, 240, #Column, 24, "&OK")
ButtonGadget(#btnCancel, #Offset, 240, #Column, 24, "&Cancel")
FrameGadget(#frgFrame, 5, 130, #Width - 10, 100, "Info of Output-Device", 0)
TextGadget(#txtVersion, 10, 145, #Width - 20, 18, "Version:")
TextGadget(#txtTech, 10, 165, #Width - 20, 18, "Technology:")
TextGadget(#txtMaxVoice, 10, 185, #Width - 20, 18, "Max. Voices:")
TextGadget(#txtPoly, 10, 205, #Width - 20, 18, "Polyphonie:")
OutDev = 0
InDev = 0
Quit = #False
OK = #False
; MessageRequester("","TEST")
; ======================================================================
Repeat
If GetGadgetState(#lgtOutputDevices) > -1 Or GetGadgetState(#lgtInputDevices) > -1
DisableGadget(#btnOK, 0)
Else
DisableGadget(#btnOK, 1)
EndIf
If InDev <> GetGadgetState(#lgtInputDevices)
InDev = GetGadgetState(#lgtInputDevices)
EndIf
If GetGadgetState(#lgtOutputDevices) <> OutDev
OutDev = GetGadgetState(#lgtOutputDevices)
midiOutGetDevCaps_(OutDev - 1, InfoOut, SizeOf(MIDIOUTCAPS))
SetGadgetText(#txtVersion, "Version: " + Str(InfoOut\vDriverVersion >> 8) + "." + Str(InfoOut\vDriverVersion & $FF))
Select InfoOut\wTechnology
Case #MOD_MIDIPORT : TmpS.s = "Hardware Port"
Case #MOD_SYNTH : TmpS.s = "Synthesizer"
Case #MOD_SQSYNTH : TmpS.s = "Square Wave Synthesizer"
Case #MOD_FMSYNTH : TmpS.s = "FM Synthesizer"
Case #MOD_MAPPER : TmpS.s = "Microsoft MIDI Mapper"
Case #MOD_WAVETABLE : TmpS.s = "Hardware Wavetable Synthesizer"
Case #MOD_SWSYNTH : TmpS.s = "Software Synthesizer"
Default: TmpS.s = "(Error Code " + Str(InfoOut\wTechnology) + ")"
EndSelect
SetGadgetText(#txtTech, "Technology: " + TmpS)
If InfoOut\wVoices = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wVoices) : EndIf
SetGadgetText(#txtMaxVoice, "Max. Voices: " + TmpS)
If InfoOut\wNotes = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wNotes) : EndIf
SetGadgetText(#txtPoly, "Polyphonie: " + TmpS)
EndIf
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Quit = #True
OK = #False
Case #PB_Event_Gadget
Select EventGadget()
Case #btnOK
PokeL(*OutDevice, OutDev - 1) ; Trick to return two results (OutDev & InDev)
PokeL(*InDevice, InDev)
Quit = #True
OK = 3
If (OutDev = -1 Or CountGadgetItems(#lgtOutputDevices) = 0) And OK & #MIDIRequ_OutSet
OK ! #MIDIRequ_OutSet : EndIf
If (InDev = -1 Or CountGadgetItems(#lgtInputDevices) = 0) And OK & #MIDIRequ_InSet
OK ! #MIDIRequ_InSet : EndIf
Case #btnCancel
Quit = #True
OK = #False
EndSelect
EndSelect
Until Quit
;==================================================================================
; CloseWindow(#WinMIDIrequester)
ProcedureReturn OK
Else
End
EndIf
EndProcedure
Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ;ONLY CALLED ON STARTUP BY ME BUT THE SYNTH CALLS IT ALL THE TIME! It is the callback function for handling incoming MIDI messages.
Define i
If FetchFlag
Debug Hex(D2);Str(D1)
EndIf
With _MIDI
Select WMsg ; process some MIDI in events.
Case #MM_MIM_DATA;The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device.
If D1 & $FF =144
\Stat=(D1 >> 8) & $FF ;Note pitch value.
\Dat1=(D1 >> 16) & $FF ;Velocity value.
If \Dat1
SetWindowTitle(0,"Note On")
Debug "MIDIInProc NOTE ON " + Str(D1) + "; " + Str(\Stat) + "; Velocity: " + Str(\Dat1)
Else
SetWindowTitle(0,"Note Off")
EndIf
ElseIf D1 & $FF = $F0 ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "Start of SYSEX!"
If (D1 >> 8) & $FF = $42
Debug "KORG-ID"
EndIf
EndIf
Case #MIM_LONGDATA ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "---------- NEW INCOMING SYSEX -----------"
For i = 0 To MidiHeader\dwBytesRecorded - 1 ; Read Buffer Sent from LPData
Debug Hex(arrSysexMessage(i))
Next
; MHI\lpData = @arrSysexMessage() ; MIDI Header pointer to MIDI data.
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) ; Recycle Sysex Buffer
EndSelect
EndWith
EndProcedure
Procedure MIDIinit(OutDev, InDev, *MIDIInProc=-1,Instrument=0) ;ONLY CALLED ON STARTUP! MIDIinproc default solo show Note on, Note off
Define iMidiInterface.i, i.l,sText.s
If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf
; The MidiInProc function is the callback function for handling incoming MIDI messages. MidiInProc is a placeholder for the application-supplied function name.
; The address of this function can be specified in the callback-address parameter of the midiInOpen function.
If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR
If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End: EndIf
EndIf
; The midiInStart function starts MIDI input on the specified MIDI input device. hMidiIn is the handle to the MIDI input device. This function resets the time stamp to zero;
; time stamp values For subsequently received messages are relative to the time that this function was called. Calling this function when input is already started has no effect,
; and the function returns zero.
midiOutOpen_(@_hMIDIout, OutDev, 0, 0, 0);Öppnar midi-interface. LPHMIDIOUT=lphmo=pointer to an HMIDIOUT handle.
; This location is filled with a handle identifying the opened MIDI output device.
; The handle is used To identify the device in calls To other MIDI output functions. OutDev=uDeviceID=Identifier of the MIDI output device that is to be opened.
; 3rd placeholder = dwCallback and 0 means no callback is desired. 4th placeholder is dwCallbackInstance. Last placeholder is dwFlags=callbackflag.
midiOutShortMsg_(_hMIDIout, 192 | Instrument<<8 ) ; Sends a short MIDI message (here a Patch Change) to the specified MIDI output device. HMIDIOUT=hmo=Handle to the MIDI output device.
; This parameter can also be the handle of a MIDI stream cast To HMIDIOUT.
; The 2nd placeholder is dwMsg=similar to #MM_MIM_DATA above.
If _hMIDIIn And _hMIDIout
If midiConnect_(_hMIDIIn, _hMIDIout, 0);The midiConnect function connects a MIDI input device to a MIDI thru or output device,
; or connects a MIDI thru device To a MIDI output device.
; First inpDeviceHandle, then outpDevHandle, 3rd placeholder must be zero.
MessageRequester("Error","Can't connect MIDI",0) :End
EndIf
EndIf
EndProcedure
MIDIResult = MIDIRequester(@OutDevice, @InDevice)
If MIDIResult & #MIDIRequ_OutSet : Debug "Output device: " + Str(OutDevice) : EndIf
If MIDIResult & #MIDIRequ_InSet : Debug "Input device: " + Str(InDevice) : EndIf
MIDIinit(OutDevice,InDevice);*** Is called only once! ****
OpenWindow(0, 10, 10, 300, 200, "MIDI Test")
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Newbie