Sending MIDI Data
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by Stan.
Hi,
I am a complete newbie at PB, and would appreciate any help dealing
with sending MIDI commands from PB ( I am trying to make a semi-random
composer for my MIDI racks, kind of poor man's Max or (Korg) Karma thing ).
TIA.
Learning and Love are what life is all about ... [ PB. registered user ]
Hi,
I am a complete newbie at PB, and would appreciate any help dealing
with sending MIDI commands from PB ( I am trying to make a semi-random
composer for my MIDI racks, kind of poor man's Max or (Korg) Karma thing ).
TIA.
Learning and Love are what life is all about ... [ PB. registered user ]
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ricardo.
WillinYork has a very nice MIDI app, contact him or follow his post in the forum : )Hi,
I am a complete newbie at PB, and would appreciate any help dealing
with sending MIDI commands from PB ( I am trying to make a semi-random
composer for my MIDI racks, kind of poor man's Max or (Korg) Karma thing ).
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by Stan.
Here is what you need :
=====================================================================
; Simple MIDI messages access
;
; Copyright 02/2002 by Stan a.k.a [url]mailto:Daniel-Marc.Ducros@lcpc.fr">Daniel-Marc.Ducros@lcpc.fr
;
; Credits :
;
; - ALL DLL INTERFACE PROVIDED BY Mr. SKUNKS
;
Procedure.s Get_Dev_Caps( Device_Num.l, *Cap_Pointer.MIDIOUTCAPS, Cap_Size.l )
CallDLL3( 4, Device_Num, *Cap_Pointer, Cap_Size )
n.w = DLLNum( )
name_string.s = " "
If n = 0
j = 0
While *Cap_Pointer\szPname[j]
PokeB( @name_string+j, *Cap_Pointer\szPname[j] )
j = j + 1
Wend
PokeB( @name_string+j, *Cap_Pointer\szPname[j] )
EndIf
ProcedureReturn name_string
EndProcedure
; Opens the MIDI device and return a pointer to it in
Procedure.w Midi_Out_Open( *Device_Pointer.l, Dev_Num.l )
Null.l = 0
CallDLL5( 1, *Device_Pointer, Dev_Num, Null, Null, Null ) ; No CallBack ...
ProcedureReturn DLLNum( )
EndProcedure
; Closes the MIDI device
Procedure.w Midi_Out_Close( Midi_Device.l )
CallDLL1( 2, Midi_Device )
ProcedureReturn DLLNum( )
EndProcedure
; Changes sound ( GM set only )
;
Procedure.w Change_Sound( Sound.b, Channel.b, *Midi_Device.l )
Zp.l = 0
PokeB( ( @Zp ) + 1, Sound ) ; New sound number ( see a GM synth doc )
PokeB( ( @Zp ) + 0, $Bf + Channel ) ; MIDI Change program message ( n = MIDI Channel - 1 )
CallDLL2( 3, *Midi_Device, Zp ) ; Send the whole shebang !
ProcedureReturn DLLNum( )
EndProcedure
; Begins to play Note , with a velocity , on MIDI Channel
; on MIDI device pointed by
Procedure.w Note_On( Note.b, Vel.b, Channel.b, Midi_Device.l )
Zp.l = 0
PokeB( ( @Zp ) + 2, Vel ) ; Velocity 0 = NoteOff ( on most Synths ) 64 = mp, 127 = ff
PokeB( ( @Zp ) + 1, Note ) ; Note 0 = C-2 127 = G8 ( Depending on synth ... )
PokeB( ( @Zp ) + 0, $8f + Channel ) ; MIDI Note On Msg 0x9n ( n = MIDI Channel - 1 )
CallDLL2( 3, Midi_Device, Zp ) ; Send the whole shebang !
ProcedureReturn DLLNum( )
EndProcedure
; Stop Note , with a velocity , on MIDI Channel
; on MIDI device pointed by
Procedure.w Note_Off( Note.b, Vel.b, Channel.b, Midi_Device.l )
Zp.l = 0
PokeB( ( @Zp ) + 2, Vel ) ; Velocity ( Depends on Synth ... Most don't use it ... )
PokeB( ( @Zp ) + 1, Note ) ; Note 0 = C-2 127 = G8 ( Depending on synth ... )
PokeB( ( @Zp ) + 0, $7f + Channel ) ; MIDI Note Off Msg 0x8n ( n = MIDI Channel - 1 )
CallDLL2( 3, Midi_Device, Zp ) ; Send the whole shebang !
ProcedureReturn DLLNum( )
EndProcedure
N.w = Get_Num_Devs( )
For Midi_Dev.l = -1 To N - 1 ; -1 = "Magic" value !!! ( Microsoft MIDI Mapper )
PrintN( Get_Dev_Caps( Midi_Dev, @midicap, Cap_Size.l ) ) ; Get device properties and print name
Midi_Out_Open( @Device_Pointer, Midi_Dev ) ; Open device
Note.b = 48
Vel.b = 40
Chan.b = 1
Sound.b = 0
For ii = 0 To 4 ; Make some noise
Change_Sound( Sound, Chan, Device_Pointer ) ; Select sound
Note_On( Note, Vel, Chan, Device_Pointer ) ; Play 1 note
Delay( 500 ) ; Wait a bit
Note_Off( Note, Vel, Chan, Device_Pointer ) ; Stop note
Note = Note + 12 ; 1 octave up
Vel = Vel + 20 ; Strike harder next time
Sound = Sound + 10
Next ii
Midi_Out_Close( Device_Pointer )
Next Midi_Dev
=====================================================================
This works under 98SE, could people with other OS ( W2000, XP ... ),
let me know if it still work for them ?
TIA
Learning and Love are what life is all about ... [ PB. registered user ]
Hi,Hi,
I am a complete newbie at PB, and would appreciate any help dealing
with sending MIDI commands from PB ( I am trying to make a semi-random
composer for my MIDI racks, kind of poor man's Max or (Korg) Karma thing ).
TIA.
Here is what you need :
=====================================================================
; Simple MIDI messages access
;
; Copyright 02/2002 by Stan a.k.a [url]mailto:Daniel-Marc.Ducros@lcpc.fr">Daniel-Marc.Ducros@lcpc.fr
;
; Credits :
;
; - ALL DLL INTERFACE PROVIDED BY Mr. SKUNKS
;
Procedure.s Get_Dev_Caps( Device_Num.l, *Cap_Pointer.MIDIOUTCAPS, Cap_Size.l )
CallDLL3( 4, Device_Num, *Cap_Pointer, Cap_Size )
n.w = DLLNum( )
name_string.s = " "
If n = 0
j = 0
While *Cap_Pointer\szPname[j]
PokeB( @name_string+j, *Cap_Pointer\szPname[j] )
j = j + 1
Wend
PokeB( @name_string+j, *Cap_Pointer\szPname[j] )
EndIf
ProcedureReturn name_string
EndProcedure
; Opens the MIDI device and return a pointer to it in
Procedure.w Midi_Out_Open( *Device_Pointer.l, Dev_Num.l )
Null.l = 0
CallDLL5( 1, *Device_Pointer, Dev_Num, Null, Null, Null ) ; No CallBack ...
ProcedureReturn DLLNum( )
EndProcedure
; Closes the MIDI device
Procedure.w Midi_Out_Close( Midi_Device.l )
CallDLL1( 2, Midi_Device )
ProcedureReturn DLLNum( )
EndProcedure
; Changes sound ( GM set only )
;
Procedure.w Change_Sound( Sound.b, Channel.b, *Midi_Device.l )
Zp.l = 0
PokeB( ( @Zp ) + 1, Sound ) ; New sound number ( see a GM synth doc )
PokeB( ( @Zp ) + 0, $Bf + Channel ) ; MIDI Change program message ( n = MIDI Channel - 1 )
CallDLL2( 3, *Midi_Device, Zp ) ; Send the whole shebang !
ProcedureReturn DLLNum( )
EndProcedure
; Begins to play Note , with a velocity , on MIDI Channel
; on MIDI device pointed by
Procedure.w Note_On( Note.b, Vel.b, Channel.b, Midi_Device.l )
Zp.l = 0
PokeB( ( @Zp ) + 2, Vel ) ; Velocity 0 = NoteOff ( on most Synths ) 64 = mp, 127 = ff
PokeB( ( @Zp ) + 1, Note ) ; Note 0 = C-2 127 = G8 ( Depending on synth ... )
PokeB( ( @Zp ) + 0, $8f + Channel ) ; MIDI Note On Msg 0x9n ( n = MIDI Channel - 1 )
CallDLL2( 3, Midi_Device, Zp ) ; Send the whole shebang !
ProcedureReturn DLLNum( )
EndProcedure
; Stop Note , with a velocity , on MIDI Channel
; on MIDI device pointed by
Procedure.w Note_Off( Note.b, Vel.b, Channel.b, Midi_Device.l )
Zp.l = 0
PokeB( ( @Zp ) + 2, Vel ) ; Velocity ( Depends on Synth ... Most don't use it ... )
PokeB( ( @Zp ) + 1, Note ) ; Note 0 = C-2 127 = G8 ( Depending on synth ... )
PokeB( ( @Zp ) + 0, $7f + Channel ) ; MIDI Note Off Msg 0x8n ( n = MIDI Channel - 1 )
CallDLL2( 3, Midi_Device, Zp ) ; Send the whole shebang !
ProcedureReturn DLLNum( )
EndProcedure
N.w = Get_Num_Devs( )
For Midi_Dev.l = -1 To N - 1 ; -1 = "Magic" value !!! ( Microsoft MIDI Mapper )
PrintN( Get_Dev_Caps( Midi_Dev, @midicap, Cap_Size.l ) ) ; Get device properties and print name
Midi_Out_Open( @Device_Pointer, Midi_Dev ) ; Open device
Note.b = 48
Vel.b = 40
Chan.b = 1
Sound.b = 0
For ii = 0 To 4 ; Make some noise
Change_Sound( Sound, Chan, Device_Pointer ) ; Select sound
Note_On( Note, Vel, Chan, Device_Pointer ) ; Play 1 note
Delay( 500 ) ; Wait a bit
Note_Off( Note, Vel, Chan, Device_Pointer ) ; Stop note
Note = Note + 12 ; 1 octave up
Vel = Vel + 20 ; Strike harder next time
Sound = Sound + 10
Next ii
Midi_Out_Close( Device_Pointer )
Next Midi_Dev
=====================================================================
This works under 98SE, could people with other OS ( W2000, XP ... ),
let me know if it still work for them ?
TIA
Learning and Love are what life is all about ... [ PB. registered user ]
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by El_Choni.
Hi,
Thanks for your code! Anyway, I had to change the following lines to avoid Windows crash (page fault at Kernel32.dll, etc.) after showing Midi Mapper:
For this one:
Don't ask me why I did it this way, just figured out what was going on in the proc and substituted it for something less 'C like' (* reminds me of C, horror).
Did anybody else have this problem? Bye,
El_Choni
Hi,
Thanks for your code! Anyway, I had to change the following lines to avoid Windows crash (page fault at Kernel32.dll, etc.) after showing Midi Mapper:
Code: Select all
Procedure.s Get_Dev_Caps(Device_Num.l, *Cap_Pointer.MIDIOUTCAPS, Cap_Size.l)
CallDLL3(4, Device_Num, *Cap_Pointer, Cap_Size)
n.w = DLLNum( )
name_string.s = " "
If n = 0
j = 0
While *Cap_Pointer\szPname[j]
PokeB(@name_string+j, *Cap_Pointer\szPname[j])
j = j + 1
Wend
PokeB( @name_string+j, *Cap_Pointer\szPname[j] )
EndIf
ProcedureReturn name_string
EndProcedure
Code: Select all
Procedure.s Get_Dev_Caps(Device_Num.l, *Cap_Pointer.MIDIOUTCAPS, Cap_Size.l)
CallDLL3(4, Device_Num, *Cap_Pointer, Cap_Size)
n.w = DLLNum()
name_string.s = " "
If n = 0
name_string = PeekS(@*Cap_Pointer\szPname[0])
EndIf
ProcedureReturn name_string
EndProcedure
Did anybody else have this problem? Bye,
El_Choni
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by fred.
. Just an advice: try to use a structure when possible instead of ugly pokes..
For Example:
Structure MidiControl
Channel.b
Note.b
Velocity.b
EndStructure
Zp.MidiControl\Velocity = Vel
Zp\Note = Note
Zp\Channel = $7f+Channel
Could replace the three following lines (note than the structure need to be declared once at programme top):
PokeB( ( @Zp ) + 2, Vel )
PokeB( ( @Zp ) + 1, Note )
PokeB( ( @Zp ) + 0, $7f + Channel)
It's easier to read, faster and smaller (in exec size). Thanks for your nice MIDI example.
Fred - AlphaSND
No problem about it; Ultimate word : Don't tell me this code is not the best one, I am just a C programmer ...
For Example:
Structure MidiControl
Channel.b
Note.b
Velocity.b
EndStructure
Zp.MidiControl\Velocity = Vel
Zp\Note = Note
Zp\Channel = $7f+Channel
Could replace the three following lines (note than the structure need to be declared once at programme top):
PokeB( ( @Zp ) + 2, Vel )
PokeB( ( @Zp ) + 1, Note )
PokeB( ( @Zp ) + 0, $7f + Channel)
It's easier to read, faster and smaller (in exec size). Thanks for your nice MIDI example.
Fred - AlphaSND
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by MrVainSCL.
Hi Stan!
Nice example you posted! Have someone a working example how to play/stop/loop MidiFiles, using complete API commands instead to use the MovieLib?
Thanks in advance...
PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...
greetz
MrVainSCL! aka Thorsten
Hi Stan!
Nice example you posted! Have someone a working example how to play/stop/loop MidiFiles, using complete API commands instead to use the MovieLib?
PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...
greetz
MrVainSCL! aka Thorsten
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by Paul.
I would do it this way...
(and my version doesn't require anyone to send me anything)
Edited by - paul on 13 February 2002 23:45:55
I would do it this way...
(and my version doesn't require anyone to send me anything)
Code: Select all
Structure MIDIDATA
Channel.b
Note.b
Velocity.b
Null.b
EndStructure
midi.MIDIOUTCAPS
devices=midiOutGetNumDevs_()
For devnum=-1 To devices-1
If midiOutGetDevCaps_(devnum,@midi,SizeOf(MIDIOUTCAPS))=0
If midi\wVoices>0
midiport=devnum
EndIf
EndIf
Next
*hMidiOut.l
result=midiOutOpen_(@hMidiOut,midiport,0,0,0)
Note.b=48
Vel.b=127
Channel.b=1
Instrument.b=1
dMsg.MIDIDATA\Note=Instrument
dMsg\Channel=$bf+Channel
result=midiOutShortMsg_(hMidiOut,PeekW(dMsg))
For x=1 To 30
dMsg\Velocity=Vel
dMsg\Note=Note
dMsg\Channel=$8f+Channel
result=midiOutShortMsg_(hMidiOut,PeekL(dMsg))
Delay(50)
dMsg\Channel=$7f+Channel
result=midiOutShortMsg_(hMidiOut,PeekL(dMsg))
Note+2
Next
result=midiOutClose_(hMidiOut)
Edited by - paul on 13 February 2002 23:45:55
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by MrVainSCL.
Hi Paul!
Very nice and small example source! That is what i would call a optimized code! I tested your example and there is a very small mistake/error... Here is the correct working version of Paul´s example:
PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...
greetz
MrVainSCL! aka Thorsten
Edited by - MrVainSCL on 13 February 2002 23:45:19
Hi Paul!
Very nice and small example source! That is what i would call a optimized code! I tested your example and there is a very small mistake/error... Here is the correct working version of Paul´s example:
Code: Select all
Structure MIDIDATA
Channel.b
Note.b
Velocity.b
Null.b
EndStructure
;
midi.MIDIOUTCAPS
devices=midiOutGetNumDevs_()
;
For devnum=-1 To devices-1
If midiOutGetDevCaps_(devnum,@midi,SizeOf (MIDIOUTCAPS))=0
If midi\wVoices>0
midiport=devnum
EndIf
EndIf
Next
;
*hMidiOut.l
result=midiOutOpen_(@hMidiOut,midiport,0,0,0)
;
Note.b = 48
Vel.b = 127
Channel.b = 1
Instrument.b = 1
;
dMsg.MIDIDATA\Note=Instrument
dMsg\Channel=$bf+Channel
result=midiOutShortMsg_(hMidiOut,PeekW(dMsg))
;
For x=1 To 30
dMsg\Velocity=Vel
dMsg\Note=Note
dMsg\Channel=$8f+Channel
result=midiOutShortMsg_(hMidiOut,PeekL(dMsg))
Sleep_(50)
dMsg\Channel=$7f+Channel
result=midiOutShortMsg_(hMidiOut,PeekW(dMsg))
Note+2
Next
;
result=midiOutClose_(hMidiOut)
PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...
greetz
MrVainSCL! aka Thorsten
Edited by - MrVainSCL on 13 February 2002 23:45:19
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by MrVainSCL.

No no... in your first posting there was following codeline:
Good morning Paul!It looks like all you changed was
Delay(50) to Sleep_(50)
Which of course works fine either way
What you forgot to correct was the second PeekW() should be PeekL()
No no... in your first posting there was following codeline:
- If midiOutGetDevCaps_(devnum,@midi,SizeOf To:devnum,@midi,SizeOf>(MIDIOUTCAPS))=0
- I corrected only this small mistake and changed Delay() to Sleep_() - right!
Btw have a look to the time when we have posted the stuff *lool* - Stay cool...
PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...
greetz
MrVainSCL! aka Thorsten
- I corrected only this small mistake and changed Delay() to Sleep_() - right!
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by Paul.
Hello MrVainSCL...
I really can't see what you are trying to correct??
I think the Forum is maybe messing things up because your code seems to have links in it.
Are you trying to put a (greater than sign) in?
If so, why?
Oh well.
Edited by - paul on 14 February 2002 00:13:30
Hello MrVainSCL...
I really can't see what you are trying to correct??
I think the Forum is maybe messing things up because your code seems to have links in it.
Are you trying to put a
Code: Select all
>If so, why?
Oh well.
Edited by - paul on 14 February 2002 00:13:30
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by MrVainSCL.
bye
PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...
greetz
MrVainSCL! aka Thorsten
Mhhhh its ok... i have copy paste your example with a link in it and so i corrected it... I dont have added the greater than sign... Let us forget this... your source is now working fine...I really can't see what you are trying to correct??
I think the Forum is maybe messing things up because your code seems to have links in it.
Are you trying to put a(greater than sign) in?Code: Select all
>
If so, why?
PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...
greetz
MrVainSCL! aka Thorsten