Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

MIDI IN support in AutoHotkey


  • Please log in to reply
66 replies to this topic
rockum
  • Members
  • 23 posts
  • Last active: Jul 11 2013 10:50 PM
  • Joined: 20 Dec 2007
Add me to the list of those desiring integrated MIDI input and output.

orbik
  • Members
  • 36 posts
  • Last active: Jul 11 2015 05:35 PM
  • Joined: 09 Apr 2008
Hello.

I've been wanting MIDI input for some time and given the lack of progress I had to try something myself. Ok, so I downloaded the source and thought it shouldn't need much change to implement it. But despite the heavy level of commenting in the code I couldn't quite grasp how it worked (I'd certainly like a more centralized documentation starting with an overview) as I'm not really an experienced programmer.

Next I tried Anatoly Larkin's method but couldn't quite get it work reasonably. For some reason after giving the callback function address to midiInOpen, the midi in driver almost came to a halt.

But you can make the midi driver send windows messages to the script instead of directly calling a function. Just replace the function address with a window handle and CALLBACK_FUNCTION with CALLBACK_WINDOW.
So far it seems you can't get the script's own window handle from within (let's add that to the wishlist, maybe a new built in variable.. A_ScriptHWND?), but by searching these forums I figured you can use a Gui window just as well:
Gui +LastFound
hWnd := WinExist()

So I pieced together a script that finally after realizing I need to *start* the device as well as open it :oops:, so far works without problems.

In fact the small mistake caused me quite a headache.. I already wrote a simple dll in the hopes it would work better. Though I had never wrote a single dll before (or anything concerning midi) but fortunately it's not very complicated.
Now the dll works too and I intend to work on it, but anyway here's the ahk script using winmm.dll directly: (needs more comments, i know but i'm lazy :()

;;"#defines"
DeviceID := 0
CALLBACK_WINDOW := 0x10000


#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
#Persistent

Gui, +LastFound
hWnd := WinExist()



MsgBox, hWnd = %hWnd%`nPress OK to open winmm.dll library

OpenCloseMidiAPI()
OnExit, Sub_Exit


MsgBox, winmm.dll loaded.`nPress OK to open midi device`nDevice ID = %DeviceID%`nhWnd = %hWnd%`ndwFlags = CALLBACK_WINDOW

hMidiIn =
VarSetCapacity(hMidiIn, 4, 0)

result := DllCall("winmm.dll\midiInOpen", UInt,&hMidiIn, UInt,DeviceID, UInt,hWnd, UInt,0, UInt,CALLBACK_WINDOW, "UInt")

If result
{
	MsgBox, error, midiInOpen returned %result%`n
	GoSub, sub_exit
}

hMidiIn := NumGet(hMidiIn) ; because midiInOpen writes the value in 32 bit binary number, AHK stores it as a string


MsgBox, Midi input device opened successfully`nhMidiIn = %hMidiIn%`n`nPress OK to start the midi device

result := DllCall("winmm.dll\midiInStart", UInt,hMidiIn)
If result
{
	MsgBox, error, midiInStart returned %result%`n
	GoSub, sub_exit
}


;	#define MM_MIM_OPEN         0x3C1           /* MIDI input */
;	#define MM_MIM_CLOSE        0x3C2
;	#define MM_MIM_DATA         0x3C3
;	#define MM_MIM_LONGDATA     0x3C4
;	#define MM_MIM_ERROR        0x3C5
;	#define MM_MIM_LONGERROR    0x3C6

OnMessage(0x3C1, "midiInHandler")
OnMessage(0x3C2, "midiInHandler")
OnMessage(0x3C3, "midiInHandler")
OnMessage(0x3C4, "midiInHandler")
OnMessage(0x3C5, "midiInHandler")
OnMessage(0x3C6, "midiInHandler")

return


sub_exit:

If (hMidiIn)
	DllCall("winmm.dll\midiInClose", UInt,hMidiIn)
OpenCloseMidiAPI()

ExitApp

;--------End of auto-execute section-----
;----------------------------------------


OpenCloseMidiAPI() {
   Static hModule 
   If hModule 
      DllCall("FreeLibrary", UInt,hModule), hModule := "" 
   If (0 = hModule := DllCall("LoadLibrary",Str,"winmm.dll")) { 
      MsgBox Cannot load library winmm.dll 
      ExitApp
   } 
} 



midiInHandler(hInput, midiMsg, wMsg) 
{
	statusbyte := midiMsg & 0xFF
	byte1 := (midiMsg >> 8) & 0xFF
	byte2 := (midiMsg >> 16) & 0xFF

	ToolTip,
	(
Received a message: %wMsg%
wParam = %hInput%
lParam = %midiMsg%
	statusbyte = %statusbyte%
	byte1 = %byte1%
	byte2 = %byte2%
	)

}

Esc::GoSub, sub_exit

My dll approach is a bit different. The idea was to have the dll call a specified window with messages specified separately for each input type, note/cc number and channel, and then only send messages where it's specified. And since I doubt the code tag would display c++ code properly, i put all relevant files to http://ihme.org/~orbik/midi4ahk/

Some parts of the scripts are borrowed from various fellow ahk users, and I wish I remembered who they were.

orbik
  • Members
  • 36 posts
  • Last active: Jul 11 2015 05:35 PM
  • Joined: 09 Apr 2008
Time for an update:

Seems that the hardest part of midi input in AutoHotkey is making the definition of "midi hotkeys" less painful. So I don't think there's anything short of full integration to the script engine, that would help here.

EDIT:
Message bulk moved to http://www.autohotke...pic.php?t=30715

autohotkeynutzer1962
  • Members
  • 3 posts
  • Last active: Mar 18 2011 07:23 PM
  • Joined: 17 Mar 2011
Hi friends,

I am not very well in the english language and I hope, I get some answers, that I will understand. It seems to me, that the theme here is about the theme, but I understand not much, cause my english lessons from school are to long ago :-(

My problem is the following thing:

I want to send a midicontrol order by using autohotkey, over my USB Midi-interface to an effectprocessor. Thats it.

It seems to me, that here I could find the solution of my problem.
Is there somebody, who can write me the neccessary skript?

Thank you very very much.

autohotkeynutzer1962
  • Members
  • 3 posts
  • Last active: Mar 18 2011 07:23 PM
  • Joined: 17 Mar 2011
ok, I just copied the scripts and it works. Hmmmm, sometimes it helps, if nobody answers. :D
But now I have a question, that I can not answer, cause I have no idea where I can find it, and the searchfunction gave no results.

In the script: Single Midi Event Example is a simple Note sent to the keyboard.

But how do I have to change the script, if I want to send an order to the modulation wheel?

Thanks for answering.

joemaffei
  • Members
  • 3 posts
  • Last active: May 21 2013 05:42 AM
  • Joined: 21 May 2013

old thread, but I just wanted to say that native MIDI support would be unbelievably useful. Right now, the music community is stuck with using Bome's, which is a fine application, but it looks like AHK is much more comprehensive and customizable.



Scoox
  • Members
  • 194 posts
  • Last active: Jun 09 2017 03:34 AM
  • Joined: 28 Nov 2010

old thread, but I just wanted to say that native MIDI support would be unbelievably useful. Right now, the music community is stuck with using Bome's, which is a fine application, but it looks like AHK is much more comprehensive and customizable.

 

+1

 

I tested Bome's MIDI translator and, although it's a great tool, the GUI-driven programming interface is very limiting, and doing anything sophisticated quickly becomes too tedious. I believe a lot of folks from the music community (producers and djs) would jump on the AHK bandwagon just for the MIDI features alone (and then realise how much they've been missing).


RegJump() - Jump to registry path in Regedit

HoverScroll() - HoverScroll() - Scroll controls without focus