Jump to content

Midi UDF


MattyD
 Share

Recommended Posts

Indeed, DJ Controller manufactures just use (and abuse) the MIDI protocol 😉

Makes it really fun doing MIDI mapping 🤪

Lucky we have the MIDI Udf to help out !

When I have some time available, I will see how to fit in the Peace Equalizer app and the MIDI interface 👍

Link to comment
Share on other sites

Hi All -

New Release: Version 1.5.

Theres been a MASSIVE update to the helpfiles, so I'm hoping they should pass as a half decent reference now.
Just be aware the chm files may require "unblocking", as they'll likely get tagged as being "from the internet".

Right click the file > properties > Unblock and apply.

image.png.341bc38744754f7ac570cd8755d2c85e.png

Apart from the documentation, notable changes are:

- Support for 3D Audio Controllers.
- Builtin routine for a midi panic button
- Active sensing functionality for output devices.
- midi_ReadMsg & _midi_SendMsg can work with short messages in a variety of formats (Thanks to ptrex)
- Window message registration has been moved to _midi_Startup (Thanks to Peter)

And a bunch more stuff that was fixed that you can find in the helpfile ;)

Link to comment
Share on other sites

Just great Matty B) I'll look into it and integrate it in the next Peace version. The moving of the Window message registration to _midi_Startup seems logical. Thanks. And the chms look very nice, very clean. Great work!

Creator of the Peace equalizer, an interface for Equalizer APO. Besides Peace, my library of functions is also available on SourceForge.

Link to comment
Share on other sites

Hi all,

This may be a bit premature, but here is release 1.6.

SCITE integration:
- The helpfile can be brought up with the f1 key when on a _midi_* or _midiAPI_* funcation. Based on the fantastic work of @water .
- Alternate data streams will be stripped when the helpfile is installed to localappdata. This fixes the "unblock file" problem detailed previously.

API:
- Fixed alignment issue with the midihdr tag when compiling as x64.
(the [MM_]MOM_POSITIONCB callback can now correctly locate midi events in a buffer.)

UDF:
- Fixed input buffers not being unprepared before disposal when closing devices.
*** EXPEREMENTAL ***
- Output devices are now opened as streaming devices.
- Added ability to record and playback midi messages.
- Added ability to write and playback standard midi files.
- Added a mechanism for recieving "cue" and "marker" meta events during playback.
- Added ability to modify playback tempo

Be aware that the experimental features are still very early in development, and implementation is likely change drastically down the track!
If anyone is looking for a ealier version of the project, you'll find all previous releases on the sourceforge page.

Happy coding,

Matt

Link to comment
Share on other sites

  • 2 weeks later...

Just a quick one.

I've just found that sending sysex messages has broken with the last release.
Despite what MS says, it seems you can't use _midi_OutLongMsg with stream handles! ("not supported" errors a-plenty).

There's a good number of functions in the UDF that rely on this, so I would suggest sticking with 1.5 for now.

Link to comment
Share on other sites

Hi folks,

Quick announcement about the band-aid release for 1.6.

V1.6.1:

Script breaking:
- A streaming device handle must be explicitly be requested with _midi_OpenOutput for sequence playback. (new parameter- req. for experimental functions)

Non-script breaking:
- Output devices are no longer opened as streaming devices by default. (reverted behaviour which fixes a multitude of functions)
- Fixed cases where _midi_GetOutputName & _midi_GetInputName were returning False instead of a blank string on failure.

Link to comment
Share on other sites

Hi all, here is release 1.7 of the UDF

The main focus of this release was to bring in some MSC support, which is mainly used with lighting consoles.
MSC can also (potentially) control things like fireworks, and flys/trusses etc. So in the unlikely event anyone is trying to do that, dont! (i.e. read the disclaimer in the helpfile)

Changelog:

- Added some Midi Show Control (MSC) support
- Fixed issue where _midi_CloseOutput failed to close non-stream handles.
- Fixed example scripts for sequence functions.
- Updated reference list links in the helpfile. The midi.org site has been updated, which broke hyperlinks.
- Modified internals for _midi_PackSize

Link to comment
Share on other sites

Hi MattyD,

I am not familiar with MSC (yet). 

Looked at the protol on the internet and looks interesting !

https://help2.malighting.com/Page/grandMA2/remote_control_msc/en/3.3

I have Dj controller that support DMX Lighting. Not sure if this protoco is compatible ...

https://support.numark.com/en/support/solutions/articles/69000797886-how-to-set-up-and-sync-engine-lighting-with-dmx-lights

Anyhow I will dig into this a bit more.

Link to comment
Share on other sites

yeah all good :)

so DMX is the standard way of controlling lights/fog machines etc, which is usually handled by a lighting console. Typically you'd pre-program a bunch of scenes/cues etc into a cuelist for a show. So in a nutshell, MSC gives you away to navigate those.

Not to cast a downer on things, but I'd be pretty surprised to find a DJ kit that supports MSC. I think it'd more likely generate DMX traffic triggered by pulses in the music.

happy  to be proven wrong though!

Link to comment
Share on other sites

  • 6 months later...

Hi MattyD

Firstly, thanks for your efforts in the Midi arena, they are very welcome.

I am interested in using AutoIt to send Midi messages to an app on the same machine. That app is "Guitar Rig 6" (GR6)  - which simulates guitar amplifiers and effects. So, for example, I currently use a Behriinger pedal board that sends midi signals via a USB port to Gr6 but I'dlike to be able to do so using AutoIt if possible.

In order for GR6 to process midi signals from the pedal board, I need to change its settings to assign the pedal board as it's input device from a drop down menu of available connected devices. Is there a way, using your UDF, that I could somehow make GR6 aware of an AutoIT script genereated "device" such that it would appear in the dropdown list of connected devices and therefore allow me to send midi messages to it?

Many thanks    

Link to comment
Share on other sites

You are very welcome :)

Yeah, this should be acheivable. What you're probably looking for is a midi loopback driver.  I've just downloaded this one and it seems to be working ok. I've no idea what the latency is like though - hopefully it'll be ok.

Let me know how you get on!

Link to comment
Share on other sites

Thank you very much. That's taken me quite a few steps forward and it successfully registers throughput from messages sent using your routines. The GR6 software also recognises  the device I "created" using loopMidi so I connected GR6 to that device to receive its incoming messages. My only problem now is that GR6 does not appear to be receiving the messages. If loopMidi is receiving them do I have to create a second device in LoopMidi and somehow redirect the incoming message to that device, then connect GR6 to the second device?

I could, of course, just be doing something dumb! 🙂

Link to comment
Share on other sites

  • 2 weeks later...

Hi MattyD

Your UDF is getting me places, thank you once again for putting in your considerable effort and making the results available to novices like myself! So far I can do anything I want with sending midi messages to GR6 which is great and I now one to go a step further and receive data from a midi foot controller that I also use successfully with my GR6 Windows app. I've used a midi monitor app (MidiView) and GR6 to verify that my laptop is receiving midi messages from the foot pedals OK but I am failing miserably to read the messages in AutoIt using _midi_ReadMsg. To rub salt in I can't find any help on your library. F1 does nothing in SciTE and when I open the help file from explorer I see only contents (no text in the right pane). I'm probably making a beginner's mistake but I can't figure it out what the problem is. If it helps, this is my code:

Func FnuMidiReceive($sDesc, $iValue)
  Local $sErrMsg = "", $aMIDIDevs[10], $iLoopCnt=0
  If $iMidiInDev = -1 Then                          ;Initialise
    _midiAPI_Startup()
    Local $aMidiIn = _midi_EnumInputs()
    MsgBox(0,"","Ubound = " & UBound($aMidiIn))
    For $iIdx = 0 to UBound($aMidiIn) - 1
      If  $aMidiIn[$iIdx] = "USB Midi Cable" Then
        FnuDebug("Device " & $iIdx & "(" & $aMidiIn[$iIdx] & ") is available for input")
        $iMidiInDev = _midiAPI_InOpen($iIdx)
        If @Error <> 0 Then FnuDebug("Midi open error: " & @error)
        ExitLoop
      EndIf
    Next
  EndIf
  Local $aMidiMsg[99]
  While 1=1
    $aMidiMsg = _midi_ReadMsg($iMidiInDev,$MFMT_DECODED_ARR)
    If @error = 0 Then
      FnuDebug("Midi message received")
      Sleep(5000)
    Else
      FnuDebug("Waiting for Midi message (" & @error & ")")
      Sleep(500)
    EndIf
  Wend
EndFunc

I was hoping to see "Midi message received" every time I press a pedal (and blue light on cable flashes to indicate midi message sent) but all I get is "Waiting for Midi message (1)" every half second (@error=1). Could I be missing important initialisation steps or perhaps my loop is not how it should be done? Any guidance you could offer would be greatly appreciated, thanks.

Edited by Fritterandwaste
Highlight code
Link to comment
Share on other sites

Ok no problems - a couple of things.

To directly open the chm file you'll probably need to "unblock" it as detailed here. That should hopefully fix the problem you're having with only seeing the table of contents.

Contextual help allows you to click anywhere on a valid _midi_* or _midiAPI_* function name and press f1 to pull up the documentation for it. For this to work you'll likely need the full editor Scite4Autoit if you haven't installed it already. Then unzip midi.zip, run the "install.au3" script and restart scite. Please let me know if this doesn't work.

The first  issue with your example above is that we're mixing the API and UDF libraries. You should use the UDF functions (_midi_*  ones) unless you're planning on doing some low level, annoying, teeth grinding stuff. So use _midi_Startup() not _midiAPI_Startup() etc...

Secondly, the UDF queues incoming midi messages, and _midi_ReadMsg grabs the next message from that queue which is waiting to be processed. After a period of time the UDF discards old, unprocessed messages - so be sure to call _midi_ReadMsg regularly. Waiting 500ms is way too long between reads, and 5 seconds is an eternity...

There are a bunch of examples in the .\UDF\Example folder so check them out too :) - here's the _midi_readMsg.au3 one.  I'm not sure what your pedal is outputting, but for a generic footswitch we'll probably want to change $CC_MODWHEEL to $CC_FOOT so we're monitoring CC 4 instead of CC 1. And if we're unsure we can always inspect $aMsg[] to find out what the pedal is sending. Hope that makes sense.

#include <GUIConstants.au3>
#include <midi.au3>

Example()

Func Example()

    Local $hGUI, $hEdit
    Local $asDevices, $hDevice
    Local $aMsg, $sLine

    $hGUI = GUICreate("Close To Exit", 220, 500)
    _midi_Startup($hGUI)

    GUICtrlCreateLabel("Close the window to finish", 4, 4, 200, 20)
    $hEdit = GUICtrlCreateEdit("", 4, 28, 212, 468)
    GUICtrlSetFont(-1, -1, -1, -1, "Consolas")

    $asDevices = _midi_EnumInputs()
    If Not @error Then $hDevice = _midi_OpenInput(SelDevice($asDevices, "Input:"))
    If Not @error Then

        GUISetState()
        GUICtrlSetData($hEdit, StringFormat("Move the modulation wheel.\r\n\r\n"), 1)

        While 1
            $aMsg = _midi_ReadMsg($hDevice)
            If Not @error Then
                Switch $aMsg[0]
                    Case $MSG_CC
                        If $aMsg[2] = $CC_MODWHEEL Then
                            $sLine = StringFormat("ModWheel chan[%s] value[%02X]\r\n", $aMsg[1], $aMsg[3])
                            GUICtrlSetData($hEdit, $sLine, 1)
                        EndIf
                EndSwitch
            Else
                ;GUIGetMsg introduces ~10ms delay in the loop to prevent CPU ramping.
                ;To increase responsiveness it is recommended to idle the CPU only when the midi
                ;input queue is empty (i.e. when _midi_ReadMsg fails).
                If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop

                ;GUIOnEvent mode can be used to decrease jitter caused by the above method.
            EndIf
        WEnd
    Else
        MsgBox(0, "Error", "An input device is unavailable.")
    EndIf

    _midi_CloseInput($hDevice)
    GUIDelete($hGUI)
    _midi_Shutdown()
EndFunc

Func SelDevice($asDevices, $sPrompt)
    Local $sDevList, $sDefaultDev
    Local $hCombo, $hOK, $iDevID

    For $i = 0 To UBound($asDevices) -1
        If Not $i Then $sDefaultDev = $asDevices[$i]
        $sDevList &= $asDevices[$i] & "|"
    Next

    GUICreate("Select Device", 270, 100)
    GUICtrlCreateLabel($sPrompt, 14, 14, 56, 21, $SS_CENTERIMAGE)
    $hCombo = GUICtrlCreateCombo("", 74, 14, 182, 25, $CBS_DROPDOWNLIST)
    GUICtrlSetData($hCombo, $sDevList, $sDefaultDev)
    $hOK = GUICtrlCreateButton("Select", 176, 61, 80, 25, $BS_DEFPUSHBUTTON)

    GUISetState()

    While 1
        Switch GUIGetMsg()
            Case $hOK, $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd
    $iDevID = GUICtrlSendMsg($hCombo, $CB_GETCURSEL, 0, 0)
    GUIDelete()

    Return $iDevID
EndFunc

 

Edited by MattyD
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   1 member

×
×
  • Create New...