Jump to content
Sign in to follow this  
psynegy

MIDI Control Change

Recommended Posts

psynegy

Hi everyone,

I'm trying to get autoit to work with my brand new Behringer BCF2000. I've located the MIDI UDF (http://www.autoitscript.com/forum/index.php?showtopic=37072) but whilst this allows me to send the data for a MIDI note, I am struggling to work out how to adapt it to send the control change.

Basically, I'm having trouble generating the output 'msg'.

#include <MIDI.au3>

$open = _MidiOutOpen()
_midiOutShortMsg($open, 0x00517FB0)
;Data 1: 81/H51, Data 2: 127/H7F, MIDI Status: 176/HB0  
MsgBox(0, "", "Waiting...")
_midiOutclose($open)

Any ideas? :D

Edit:

I've just found this:

Private Function CreateMidiMsg(bytNote As Byte, bytVol As Byte, bytStatus As Byte) As Long
'
' Pack the data into a Long variable
'   Byte 0 (LSB)    = Status
'   Byte 1          = Note
'   Byte 2          = Volume
'   Byte 3          = 00
'
CreateMidiMsg = (bytVol * (16 ^ 4))
CreateMidiMsg = CreateMidiMsg + (bytNote * (16 ^ 2))
CreateMidiMsg = CreateMidiMsg + bytStatus
End Function

I'm trying to make some sense of it, I'd definitely appreciate any pointers. Working with hexadecimal is a new thing to me.

Edited by psynegy

Share this post


Link to post
Share on other sites
PsaltyDS

You don't have to work with the hex. Let the math do it for you:

; Function _CreateMidiMsg($iNote, $iVol, $iStatus)
; Where:    All parameters have valid range 0 to 255
;       $iNote = Note value 
;       $iVol = Volume value
;       $iStatus = Status value
;
; Packs the data into an INT32 format
;   Byte 0 (LSB)    = Status
;   Byte 1          = Note
;   Byte 2          = Volume
;   Byte 3          = 00
;
; Returns:  On success = formatted INT32 MIDI message
;           On failure = 0, @error = 1, @extended = number of parameter out of range
Func _CreateMidiMsg($iNote, $iVol, $iStatus)
    Select
        Case $iNote > 255 Or $iNote < 0
            Return SetError(1, 1, 0)
        Case $iVol > 255 Or $iVol < 0
            Return SetError(1, 2, 0)
        Case $iStatus > 255 Or $iStatus < 0
            Return SetError(1, 3, 0)
    EndSelect
    Local $iMidiMsg = $iVol * 2^16 ; Byte 2
    $iMidiMsg += $iNote * 2^8 ; Byte 1
    $iMidiMsg += $iStatus ; Byte 0
    Return $iMidiMsg
EndFunc

:D

Edit: Using it in you original script would look like this:

#include <MIDI.au3>

$open = _MidiOutOpen()
;Data 1: 81/H51, Data 2: 127/H7F, MIDI Status: 176/HB0  
$iMsg = _CreateMidiMsg(127, 81, 176) ; vol = 127, note = 81, status = 176
_midiOutShortMsg($open, $iMsg)
MsgBox(0, "", "Waiting...")
_midiOutclose($open)

; Function _CreateMidiMsg($iNote, $iVol, $iStatus)
; Where:    All parameters have valid range 0 to 255
;       $iNote = Note value 
;       $iVol = Volume value
;       $iStatus = Status value
;
; Packs the data into an INT32 format
;   Byte 0 (LSB)    = Status
;   Byte 1          = Note
;   Byte 2          = Volume
;   Byte 3          = 00
;
; Returns:  On success = formatted INT32 MIDI message
;           On failure = 0, @error = 1, @extended = number of parameter out of range
Func _CreateMidiMsg($iNote, $iVol, $iStatus)
    Select
        Case $iNote > 255 Or $iNote < 0
            Return SetError(1, 1, 0)
        Case $iVol > 255 Or $iVol < 0
            Return SetError(1, 2, 0)
        Case $iStatus > 255 Or $iStatus < 0
            Return SetError(1, 3, 0)
    EndSelect
    Local $iMidiMsg = $iVol * 2^16 ; Byte 2
    $iMidiMsg += $iNote * 2^8 ; Byte 1
    $iMidiMsg += $iStatus ; Byte 0
    Return $iMidiMsg
EndFunc

Note the potential confusion because the prototype function you provided lists the parameters in a different order from how they are packed in the message word.

:huggles:

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
psynegy

I'll give it a try when I get back from work. Many thanks!

Share this post


Link to post
Share on other sites
psynegy

It seems that I've been barking up the wrong tree a little. I've spent hours trying to get that right (which is now perfect thanks to you) but my problems are deeper. I've been trying to get that working but for some reason the initial _MidiOutOpen command doesn't work.

Func _midiOutOpen($devid=0,$callback=0,$instance=0,$flags=0)

    $struct = DllStructCreate("udword")

    $ret = Dllcall("winmm.dll","long","midiOutOpen","ptr",DllStructGetPtr($struct),"int",$devid,"long",$callback,"long",$instance,"long",$flags)
    if not @error Then
        MsgBox(0, "Error", "Error: " & $ret[0])
        $Get = Dllstructgetdata($struct,1)
        Return $get
    Else
        MsgBox(0, "Error", "Error: " & $ret[0])
        Return $ret[0]
    EndIf
EndFunc

(I've used a MsgBox for debug, it returns 11 (which is the error code for MMSYSERR_INVALPARAM) which means the pointer is invalid... apparently.)

Seems that @error doesn't get thrown... oh well.

Any ideas?

Share this post


Link to post
Share on other sites
87450kalle

It seems that I've been barking up the wrong tree a little. I've spent hours trying to get that right (which is now perfect thanks to you) but my problems are deeper. I've been trying to get that working but for some reason the initial _MidiOutOpen command doesn't work.

Func _midiOutOpen($devid=0,$callback=0,$instance=0,$flags=0)

    $struct = DllStructCreate("udword")

    $ret = Dllcall("winmm.dll","long","midiOutOpen","ptr",DllStructGetPtr($struct),"int",$devid,"long",$callback,"long",$instance,"long",$flags)
    if not @error Then
        MsgBox(0, "Error", "Error: " & $ret[0])
        $Get = Dllstructgetdata($struct,1)
        Return $get
    Else
        MsgBox(0, "Error", "Error: " & $ret[0])
        Return $ret[0]
    EndIf
EndFunc

(I've used a MsgBox for debug, it returns 11 (which is the error code for MMSYSERR_INVALPARAM) which means the pointer is invalid... apparently.)

Seems that @error doesn't get thrown... oh well.

Any ideas?

I had the same problem, changed $struct = DllStructCreate("udword") to $struct = DllStructCreate("dword") and now it is working...

//Johan

Share this post


Link to post
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
Sign in to follow this  

×