Jump to content

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

MIDI input library


  • Please log in to reply
90 replies to this topic
automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006

if (no midi events on a given midi port for longer than 1s)
{
    press some hotkey
}

My question above does not make much sense, as the midi input library accepts anyway midi events just from one single midi port. So this part is solved.

Finally I could try out this midi input library, it works so far fine, too bad that we have no examples for how to use getCC and getWheel.

Right now I am using somethink like this:
;--------------------  Midi "hotkey" mappings  ----------------------- 
...
listenCC(1, "do_something", 0)
listenWheel("do_something", 0)
...

;-------------------------Midi "hotkey" functions--------------------- 
do_something(note, vel)
{
	if (vel)
	{
	  ;getCC(ccNumber, channel)
	  ;getCC(1, 0)
              ; here I would like to add CC-speed dependent actions
	  MsgBox, I received pitch %note% with velocity %vel%
              Sleep, 150
	  MsgBox, I do something here!
	}
}

What I would like to do is differentiating between two different cc-change speeds:
- for slow cc-changes process_slow should run,
- for fast cc-changes process_fast should run.
To accomplish this I should get two CC values from two different time points and calculate the speed of change, define a decision criteria for slow/fast and it should work. Any ideas how I can do this? Some examples how to use getCC would be fine. Then I would like to do the same also with getWheel.

fridemar
  • Members
  • 16 posts
  • Last active: Oct 27 2008 12:27 AM
  • Joined: 16 Aug 2006
Yes, we need besides vel the dur(ation) attribute of a note, like Tim Thompson did it in Keykit (open C-source).

When vel=0, this is equivalent with note-off, so that when this event occurs, the dur should also be made available as the time difference t1-t0 of each note-on note-off.

Fridemar
PS.:
And dont forget to extend the midi library with outputs for the cheap Midi-keyboards... Hey ribbet.1 ... ;-)

PPS.:
By the way, can somebody tell us why

>Numpad9::
>Run C:\Programme\AutoHotkey\MidiKeys.ahk
>return

allows calling the MidiKeys script from Autohotkey.ini with numkey 9 but
not simply adding the call at the end of the initial script?

>Run C:\Programme\AutoHotkey\MidiKeys.ahk

How can we automatically have MidiKeys running on start-up?

I have modified it a bit, that it responds to each key in the following way:
vel>Threshold then uppercase letters
else lowercase.

Discriminating the duration would allow other niceties, such as automatic appending whitespace to the last letter in a seqence of letters and even
chord recognition (sum of the differences of the first keydowns below a certain threshold) ...
http://aboutUs.org/fridemar
Let's amplify each other's light :-)

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006

How can we automatically have MidiKeys running on start-up?

I have modified it a bit, that it responds to each key in the following way:
vel>Threshold then uppercase letters
else lowercase.

I put a link to the start-up dir.

I did a similar modification, except ignoring events under the threshold level:

	if (vel>15)
	{	  
	  Send {Enter}{Tab 2}%note%{Tab}%vel%{Space 2}
	}


automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
While listenCC works here, listenWheel does not. Anyone who tested listenWheel successfully?
listenCC(127, "do_something", 0)
listenWheel("do_something", 0)


fridemar
  • Members
  • 16 posts
  • Last active: Oct 27 2008 12:27 AM
  • Joined: 16 Aug 2006
Dear orbik,

again thank you for sharing your MidiIn DLL and its useful ahk wrapper library.

Looking into your C++ source, I noticed that
your callback

void CALLBACK midiInProc(HMIDIIN handle, UINT wMsg, DWORD dwInstance, DWORD midi_message, DWORD [color=red]midi_timestamp[/color])

has access to timing information "midi_timestamp".

It would be very helpful for the community, if you could extend the DLL
by a duration array

UINT ruleNoteDur[128][16];

in which a (NoteOffTime-NoteOnTime) duration for each of those 128 * 16 possible events is updated at NoteOffTime, whereas on NoteOnTime it is reset to 0 for each notified individual entry.

The listener-actor functions

noteXXX(notenumber, vel, .... 
bound by
listenNote(noteNumber, noteXXX, channel=0)

urgently need a duration parameter

noteXXX(notenumber, vel, [color=red]dur[/color], ....

For you it may be a small step, but for the community it is a big leap ... :-)

-- Fridemar
PS.:
Then we can script things like that:
* Holding down a key produces a repeating motiv/melody (with programmed midi_out or some other *.mid *.wav ,*.mp3 pattern).
* Releasing the key stops the music, leaving a well-defined duration, which lies in the cycle of its adherent command-intervals
* Combined with memo-lyrics, each sung syllable easily anchors a special sub-command in the memory of the user ... such that Worksongs now get a totally new meaning within the context of Midi-powered Autohotkey :p)



Ref:

[quote name="orbik"](Moved from the relevant topic in Wishlist http://www.autohotke.../topic2831.html.. now in the correct sub forum)


I made a small library for integrating midi input to ahk scripts. It consists of a dll that uses a callback function to store the most recent value for each key velocity, cc, pitch wheel and channel aftertouch for every channel.

....


To get midi input as windows messages you command the dll to send specific data only, and to specific message numbers. You can also directly ask any of the stored most recent values

I also wrote an ahk layer on top of the dll supposed to make it easier to use. It also creates a tray icon menu to select/change midi in device.

The dll file: http://ihme.org/~orb...ahk/midi_in.dll
Dll source (as a vc++ project): http://ihme.org/~orb...ahk/dll_source/
Dll function reference: http://ihme.org/~orb...i_in.readme.txt

...
....

listenNote(noteNumber, funcName, channel=0)
{
	global msgNum
	GoSub, sub_increase_msgnum
	DllCall("midi_in.dll\listenNote", Int,noteNumber, Int,channel, Int,msgNum)
	OnMessage(msgNum, funcName)
}


....
http://aboutUs.org/fridemar
Let's amplify each other's light :-)

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
Here is another example I am using, for reading/viewing in browsers (Opera) or Acrobat, e.g. in the AutoHotkey forum automatically while playing piano/midi keyboard. Opera has the nice feature that it jumps to the next link with {space} when you reach the end of the page (mostly).

;-------------------------Midi "hotkey" functions--------------------- 
do_something(note, vel)
{
	if (vel<=60 && vel>20)
	{
	  #Persistent
	  valuenew = %vel%
	  Send, {space}
	  Tooltip, note:%note%   velocity:%vel%
	  SetTimer, RemoveToolTip, 1000
	  return
	  
	  RemoveToolTip:
	  SetTimer, RemoveToolTip, Off
	  ToolTip
	  return
	}
        if (vel>60)
        {
	  #Persistent
	  valuenew = %vel%
	  Send, {PgUp}
	  Tooltip, note:%note%   velocity:%vel%
	  SetTimer, RemoveToolTip2, 1000
	  return
	  
	  RemoveToolTip2:
	  SetTimer, RemoveToolTip2, Off
	  ToolTip
	  return
	}
}
It's an example for how to combine normally unrelated tasks but which you both like, here: playing midi keyboard + reading something.

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
Having listenCCRange similar to listenNoteRange would be also useful.

fridemar
  • Members
  • 16 posts
  • Last active: Oct 27 2008 12:27 AM
  • Joined: 16 Aug 2006
Hi automaticman,

I solved the time-sensitivity problem with "A_TickCount" for note-ons and note-offs, although a "dur" -parameter would be more Midi-like.

How do you script in ahk a thread, that realizes a key repeat (of a PC-keyboard key),

* started by a note-on,
* terminated by its respective note-off?

-- fridemar

PS.:
To bridge two very agile communities, here is a link to the jfugue group,
who discuss a Java/Groovy based MidiSystem for composing:
<!-- m -->http://tech.groups.y... ... essage/132<!-- m -->.
As some Autohotkey members use COM-techniques, we could use Sriptom to connect both worlds ...



Having listenCCRange similar to listenNoteRange would be also useful.


http://aboutUs.org/fridemar
Let's amplify each other's light :-)

  • Guests
  • Last active:
  • Joined: --
I get the following error whenever I try and include the vanilla midi_in_lib.ahk in my script...

Posted Image

  • Guests
  • Last active:
  • Joined: --
looks like i need to take the coroutines out of the script and into the main script when using mini_in_lib.ahk as an #include

  • Guests
  • Last active:
  • Joined: --

looks like i need to take the coroutines out of the script and into the main script when using mini_in_lib.ahk as an #include


Put the include line after the auto-execute section (eg. last line of your script), or it will try to run the subroutines before the menu has been created.

Dabbler
  • Members
  • 5 posts
  • Last active: Jul 26 2009 08:03 AM
  • Joined: 29 Dec 2008
In the category better late than never a reply to the listenwheel question:
Listenwheel only has one value as reply, so asking 2 then waiting for the second to become something will be waiting for something that never happens, it should be like this in automaticman's example:

;preamble here
;make listenwheel call 'do_wheel' when there's a message
listenWheel("do_wheel", 0)
return
;the actual called function
do_wheel(wheelin)
{
   if (wheelin)
   {
; the var wheelin has the value received and is printed out to the screen
; (assuming you have something open that receives it, open a textdocument or something to test)

    send {Enter}wheel= %wheelin% 
          }
}

As you see there's 1 value returned and one value waited for with the 'if'
Note: the 'if' isn't needed since the function only gets called when there is a message so there's always data and only if the wheel is sending 0 does the if stop output when there's an 'if', but there's no need to prevent that, I left it in for clarification though since his original has the 'if'

Dabbler
  • Members
  • 5 posts
  • Last active: Jul 26 2009 08:03 AM
  • Joined: 29 Dec 2008
Additional sample script for visualisation of wheel and CC1.

;
; AutoHotkey Version: 1.0.47.x
; Language:       English
; Platform:       Win9x/NT
; Author:         Dabbler, edit from stuff by ribbet.1 and  others
;
; Script Function:
; Reads values from wheel and CC1 and displays them as progressbars
;	midi in, select device from shortcut menu, needs midi_in_lib.ahk and midi_in.dll in folder
; 
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance, Force

Gui, -Caption +Border  +ToolWindow
Gui, Color, EEAA99
Gui, +LastFound
WinSet, TransColor, EEAA99
Gui, Add, Progress,      w384 h10 cBlue -0x1 Range0-127 vbar_X  ; value goes upto 127, bar length is 384
Gui, Add, Progress, x+10 w384 h10 cRed   -0x1 Range0-16384 vbar_Y ; value goes upto 16384 (my CC1 controller's output), bar length is 384
Gui, Show, x5 y707 , W_Meter                  ; position and show, Adjust X & Y to suit your screen res

OnExit, sub_exit
if (midi_in_Open(0))
   ExitApp

;--------------------  Midi "hotkey" mappings  -----------------------

listenCC(1, "do_cc_one", 0)
listenWheel("do_wheel", 0)
return
;----------------------End of auto execute section--------------------

sub_exit:
   midi_in_Close()
ExitApp

;-------------------------Miscellaneous hotkeys-----------------------
Esc::ExitApp

;----------------------------------------------
;experiment

do_cc_one(ccnumber, ccvel)
{
   if (ccvel)
   {
left_bar :=  ccvel
GuiControl,, bar_X, %left_bar%
;    ccvel is the value
    
   }
}


do_wheel(wheelin)
{
right_bar :=  wheelin
GuiControl,, bar_Y, %right_bar%
;    wheelin is the value
    
}
;-------------------------  Midi input library  ----------------------
#include midi_in_lib.ahk

Just to keep midi-in alive I guess :)

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
Thanks Dabbler for your input, I will try them as soon as I am at my keyboard again, but I am sure it will just work.

Also keeping this midi-in topic alive I thought a little more how we could make out of midi-input into ahk a useful and general purpose control mechanism. Here are my thoughts so far, any additions, improvements are welcome.

Following scenario:

0. As a requirement I consider having a 5 octave midi keyboard in front of me where the available pitches for the notes are 36..96 which are all together 61 keys.


1. I want to map/spend one key, pitch=96, which is the highest key on this midi keyboard for toggling between normal playing mode and the command mode. So if you press 96 you enter command mode of the midi keyboard with characteristics as follows.

a) We are using only pitchclass information with values 0..11 where the pitchclass C would equal to 0 and B to 11. This means no matter on which octave you use those notes their function should be the same.

B) Further we want to distinguish between black keys as function keys similar to main menues in software applications and white keys as operations for these functions similar to menue entries in software applications.

c) For both black keys and white keys you are allowed to use up to five fingers simultaneously. They can be anyway in any octaves, it should be no problem to find a right space where you can use your fingers comfortably on those keys. This should give us enough combination cases both for the main menues and the menue entries.

d) The white keys should support additionally a sequence of multiple notes, when played as a melody exactly in that order resulting in some specific target operation.

Now I thought if we can generate for each black key combination set and white key combination set an orthogonal and unique integer number we can use this number to decide what should happen as action in AHK. What do you think, which methods would be interesting to create such unique integer numbers? I was thinking then to take this unique integer number and switch among multiple cases similar as already implemented in the EnterPad example somewhere in this forum. Of course each black key combination function and then the white key operation should be visually communicated to the user of this system e.g. via ToolTips.

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
Here is another idea for using the ahk midi input library:

Why not using the midi keyboard, e.g. limited to only one octave range again where a single hand can stay and reach any of the 12 keys comfortably, for controlling the mouse cursor position.

This idea could be also applied even to the pc keyboard, e.g. by using a special key to set the pc keyboard into this mouse cursor movement mode, e.g. this special key could be space, and all the other keys would relate to the absolute screen range from top to bottom splitted into five ranges as we have normally five rows on the pc keyboard, and horizontally split into 10 ranges. Then we could even have commands which would "zoom in" into a specific range and do the same splits just for that zoomed range, until we reach the cursor coordinate where we want to move. This could be a funny game.