Jump to content

Recommended Posts

Posted (edited)

What is MIDI-Scripting?

First, a little explanation on what you can do with MIDI-Scripts. 
You can write a script that tells MIDI Device how to act based on the MIDI input message it receives.

Or the other way around you can send MIDI messages from a MIDI Device to a MIDI compatible software,
And script the behavior accordingly.

Writing your own MIDI-Script allows you to execute custom actions, such as play/pause, start/stop recording, ....


MIDI protocol

The protocol is based on messages.
A MIDI message is an instruction that controls some aspect of the receiving Device.

You have short messages (3 bytes) and system Exclusive messages (byte arrays).
the exclusive messages are also called SysEx messages.

Why needing this?

Apart from controlling music device, you can also you this controlling other types of devices and even software.

Most of them are music media related.

 

AutoIt MIDI software :

- MIDI library
- Peace Equalizer

 

MIDI-OX Com library :

MIDI-OX is a versatile utility that is great for troubleshooting MIDI hardware devices
It also acts as a System Exclusive SysEx librarian, which allows you to send (dump) and receive SysEx data

Nevertheless this is quite old software, it is still alive and kicking.

Mentioned many times on the internet as the Swiss Army knife for debugging input and output MIDI messages.

It has a GUI interface but as well is has COM interface.

Download here :

I wrote a quick example to convert the it to AutoIT

#AutoIt3Wrapper_UseX64=N
#include <MsgBoxConstants.au3>

; Initialize SvenP 's  error handler
$oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

;~  Create object
Local $mox = ObjCreate("MIDIOX.MOXScript.1")

; Custom sink object
Local $oMoxEvents = ObjEvent($mox, "OnTrigger_")

Local $Now = $mox.GetSystemTime

$mox.Sleep(2500)

If $mox.GetSystemTime Then
   ConsoleWrite("At least 2½ second has passed" & @CRLF)
EndIf


Local $n1 = $mox.InstanceCount
Local $n2 = $mox.InstanceNumber

ConsoleWrite("Instances : " & $n2 & " " & $n2 & @CRLF)

$mox.FireMidiInput = 1 ; begins input
$mox.DivertMidiInput = 1 ; when set, routes all data

MsgBox (0,"Midi-OX","Press OK to end MIDI Loop") ; sits in a message loop

; -----------------------------------------------------------
;This is the function that gets called by MIDI-OX
Func OnTrigger_MidiInput( $timestamp, $status, $chan, $dat1, $dat2)
   ; ship it right back
   $mox.OutputMidiMsg ($status + $chan, $dat1, $dat2)
EndFunc

; -----------------------------------------------------------
; The MIDI Input Devices
Local $str = "Sys MIDI Input Devices: " & $mox.SysMidiInCount
Local $strWrk = $mox.GetFirstSysMidiInDev

while $strWrk <> ""
   $str = $str & @CRLF & " " & $strWrk
   $strWrk = $mox.GetNextSysMidiInDev
Wend

ConsoleWrite(@CRLF)
ConsoleWrite($Str  & @CRLF)
ConsoleWrite(@CRLF)

; -----------------------------------------------------------
; The MIDI Input Devices
Local $str = "Sys MIDI Output Devices: " & $mox.SysMidiOutCount
Local $strWrk = $mox.GetFirstSysMidiOutDev

while $strWrk <> ""
   $str = $str & @CRLF & " " & $strWrk
   $strWrk = $mox.GetNextSysMidiOutDev
Wend

ConsoleWrite(@CRLF)
ConsoleWrite($Str  & @CRLF)
ConsoleWrite(@CRLF)

; -----------------------------------------------------------
; The MIDI Next Open Input Device
Local $str =  "Open MIDI Input Devices: " & $mox.OpenMidiInCount
Local $strWrk = $mox.GetFirstOpenMidiInDev
while $strWrk <> ""
   $id = $mox.GetInPortID( $strWrk )
   $name = $mox.GetInPortName( $strWrk )
   $str = $str & @CRLF & " " & $strWrk &  " " & $id & " " & $name
   $strWrk = $mox.GetNextOpenMidiInDev
Wend

ConsoleWrite(@CRLF)
ConsoleWrite($Str  & @CRLF)
ConsoleWrite(@CRLF)

; -----------------------------------------------------------
; The MIDI Next Open Output Device
Local $str =  "Open MIDI Output Devices: " & $mox.OpenMidiOutCount
Local $strWrk = $mox.GetFirstOpenMidiOutDev
while $strWrk <> ""
   $id = $mox.GetOutPortID( $strWrk )
   $name = $mox.GetOutPortName( $strWrk )
   $str = $str & @CRLF & " " & $strWrk &  " " & $id & " " & $name
   $strWrk = $mox.GetNextOpenMidiOutDev
Wend

ConsoleWrite(@CRLF)
ConsoleWrite($Str  & @CRLF)
ConsoleWrite(@CRLF)

MsgBox (0,"Midi-OX","Press OK to end MIDI-OX version : " )


If MsgBox($MB_OKCANCEL, "Shutdown?", "OK to exit MIDI-OX version " & $mox.GetAppVersion ) = 1 Then
   $mox.ShutdownAtEnd = 1

    $mox.FireMidiInput = 0 ; stops MIDI input
    $mox.DivertMidiInput = 0

Else
   $mox.ShutdownAtEnd = 0
EndIf



Func MyErrFunc()
  $HexNumber=hex($oMyError.number,8)
  Msgbox(0,"AutoItCOM Test","We intercepted a COM Error !"       & @CRLF  & @CRLF & _
             "err.description is: "    & @TAB & $oMyError.description    & @CRLF & _
             "err.windescription:"     & @TAB & $oMyError.windescription & @CRLF & _
             "err.number is: "         & @TAB & $HexNumber              & @CRLF & _
             "err.lastdllerror is: "   & @TAB & $oMyError.lastdllerror   & @CRLF & _
             "err.scriptline is: "     & @TAB & $oMyError.scriptline     & @CRLF & _
             "err.source is: "         & @TAB & $oMyError.source         & @CRLF & _
             "err.helpfile is: "       & @TAB & $oMyError.helpfile       & @CRLF & _
             "err.helpcontext is: "    & @TAB & $oMyError.helpcontext _
            )
  SetError(1)  ; to check for after this function returns
Endfunc

 

Testing

Even if you do not have any hardware at your disposal, you can use this LoopBack MIDI driver.

This software can be used to create virtual loopback MIDI-ports to interconnect applications on Windows, that want to open hardware-MIDI-ports for communication.

Download here : https://www.tobias-erichsen.de/software/loopmidi.html 

 

MIDI Protocol Documentation (video)

A must see short video series in order to understand the basics of the MIDI protocol

Especially Part 1 / 2 / 4 / 5 / 7 are most valuable to get a good understanding.

MIDI Part 1 - MIDI Signal Path - YouTube

MIDI Part 2 - MIDI Message Types - YouTube

MIDI Part 3 - DIN MIDI - YouTube

MIDI Part 4 - MIDI Protocol Details - YouTube

MIDI Part 5 - Channel Messages - YouTube

MIDI Part 6 - MIDI Clock - YouTube

MIDI Part 7 - SYSEX, etc. - YouTube

 

Enjoy !

Edited by ptrex
Posted

Second Example :

Converted from the VBScript install with the MIDI-OX software

; MIDIOX Test - Event Sink Example
; Copyright (c) 2001 by Jamie O;Connell
;
; This script is an example of doing VBScript with MIDI-OX
#AutoIt3Wrapper_UseX64=N
#include <MsgBoxConstants.au3>

Local $mox
Local $str, $strWrk
Local $n, $ii, $nInst, $id
Local $bGo

; Initialize SvenP 's  error handler
Local $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

; Create object
 $mox = Objcreate("Midiox.MoxScript.1")

 ; Custom sink object
Local $oMoxEvents = ObjEvent($mox, "Sink_")

Local $str = "MIDI-OX"
Local $n = $mox.InstanceNumber

If $n > 0 Then
  $str = $str & ":" & String( $n )
Else
  MsgBox (0,"Info","No Instances")
EndIf

$str = $str & " " & $mox.GetAppVersion
$str = $str & " of " & $mox.InstanceCount
ConsoleWrite($str & @CRLF)

; *** System devices
$str = "Sys MIDI In Devices: " & $mox.SysMidiInCount & @CRLF
$strWrk = $mox.GetFirstSysMidiInDev

While $strWrk <> ""
   $id  = $mox.GetInPortID( $strWrk )
   $str = $str & @CRLF & String( $id ) & ")  " & $strWrk
   $strWrk = $mox.GetNextSysMidiInDev
WEnd

ConsoleWrite($str & @CRLF)

$str = "Sys MIDI Out Devices: " & $mox.SysMidiOutCount & @CRLF
$strWrk = $mox.GetFirstSysMidiOutDev

While $strWrk <> ""
   $id  = $mox.GetOutPortID( $strWrk )
   $str = $str & @CRLF & String( $id ) & ")  " & $strWrk
   $strWrk = $mox.GetNextSysMidiOutDev
WEnd

ConsoleWrite($str & @CRLF)

; *** MIDI-OX devices
$str = "Open MIDI In Devices: " & $mox.OpenMidiInCount & @CRLF
$strWrk = $mox.GetFirstOpenMidiInDev

While $strWrk <> ""
   $id  = $mox.GetInPortID( $strWrk )
   $str = $str & @CRLF & String( $id ) & ")  " & $strWrk
   $strWrk = $mox.GetNextOpenMidiInDev
WEnd

ConsoleWrite($str & @CRLF)

$str = "Open MIDI Out Devices: " & $mox.OpenMidiOutCount & @CRLF
$strWrk = $mox.GetFirstOpenMidiOutDev

While $strWrk <> ""
   $id  = $mox.GetOutPortID( $strWrk )
   $str = $str & @CRLF & String( $id ) & ")  " & $strWrk
   $strWrk = $mox.GetNextOpenMidiOutDev
WEnd

ConsoleWrite($str & @CRLF)

If MsgBox($MB_OKCANCEL, "Divert MIDI Input?", "Yes / No", "MIDI Notes"  ) = 1 Then
   $mox.DivertMidiInput = 1
Else
   $mox.DivertMidiInput = 0
EndIf

$mox.FireMidiInput = 1
MsgBox(0,"End", "Press OK to end MIDI Loop")

$mox.FireMidiInput = 0
$mox.DivertMidiInput = 0

; All done

If MsgBox($MB_OKCANCEL, "Shutdown?", "OK to exit MIDI-OX version " & $mox.GetAppVersion ) = 1 Then
   $mox.ShutdownAtEnd = 1

    $mox.FireMidiInput = 0 ; stops MIDI input
    $mox.DivertMidiInput = 0

Else
   $mox.ShutdownAtEnd = 0
EndIf

; Exit
;------------------------------------------
Func Sink_MidiInput( $ts, $port, $stat, $dat1, $dat2)

   ; Transpose up a minor 3d
   If $stat = 0x90 Or $stat = 0x80 Then
      $dat1 = $dat1 + 3
   EndIf

   $mox.OutputMiLocalsg (-1, $stat, $dat1, $dat2)

EndFunc

;------------------------------------------
; Connection point sink for SysEx

Func Sink_SysExInput( $strSysEx )
   $mox.SendSysExString ($strSysEx  )
EndFunc

;------------------------------------------

Func Sink_OnTerminateMidiInput()
   MsgBox(0,"TerminateMidiInput" ,"MIDI Input Termination Received From MIDI-OX")
   $mox.FireMidiInput = 0
   $mox.DivertMidiInput = 0
EndFunc


Func MyErrFunc()
  $HexNumber=hex($oMyError.number,8)
  Msgbox(0,"AutoItCOM Test","We intercepted a COM Error !"       & @CRLF  & @CRLF & _
             "err.description is: "    & @TAB & $oMyError.description    & @CRLF & _
             "err.windescription:"     & @TAB & $oMyError.windescription & @CRLF & _
             "err.number is: "         & @TAB & $HexNumber              & @CRLF & _
             "err.lastdllerror is: "   & @TAB & $oMyError.lastdllerror   & @CRLF & _
             "err.scriptline is: "     & @TAB & $oMyError.scriptline     & @CRLF & _
             "err.source is: "         & @TAB & $oMyError.source         & @CRLF & _
             "err.helpfile is: "       & @TAB & $oMyError.helpfile       & @CRLF & _
             "err.helpcontext is: "    & @TAB & $oMyError.helpcontext _
            )
  SetError(1)  ; to check for after this function returns
Endfunc

 

Enjoy !

Posted
Posted

I think that @czardas will be happy for using this stuff :)

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

  • 2 weeks later...

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
  • Recently Browsing   0 members

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