Module: gmcl_midi

This module is in alpha stage, but I suspect I’ll have VERY little time to update this after university begins next week.

WHAT IS IT?
This module redirects MIDI events to Garry’s mod and calls a simple MIDI hook.
That means that you could play music on a keyboard or digital piano such as this one:

No joke, this is actually the one I have. It’s from 1998 :D.

And Garry’s mod would know which notes you are playing.

HOW TO USE
As of this moment, the module has two functions and one hook. You gotta keep it simple.
[lua]
require(“midi”)

– You MUST call this function before the MIDI hook will work. You need to connect to the actual MIDI device.
– The default value for the “port” parameter is 0. An error will be thrown if there are no MIDI devices connected to the PC. Hence the check.
if table.Count(midi.GetPorts()) > 0 then – use table.Count here, the first index is 0
print(“opening midi”)
midi.Open()
end

print(midi.Open())

hook.Add(“MIDI”, “print midi events”, function(time, code, par1, par2, …)
print("A midi event happened at "… time … “, which is " … SysTime() - time … " seconds ago!”)
– The code is a byte (number between 0 and 254).
print(“MIDI EVENT”, code, par1, par2, …)
print(“Event code:”, midi.GetCommandCode(code))
print(“Event channel:”, midi.GetCommandChannel(code))
print(“Event name:”, midi.GetCommandName(code))

-- The parameters of the code
print("parameters", par1, par2, ...)

end)

– Only listen for 10 minutes
timer.Simple(600, function()
if not midi.IsOpened() then return end – closing MIDI will error if it isn’t opened
midi.Close() – Call midi.Close when you want to stop receiving MIDI events. Closing is NOT obligatory.
end)
[/lua]
These are standard MIDI codes. Read more about the MIDI protocol

MEDIA
Here’s a screenshot of me pressing and releasing (I believe) c’ with the above sample code.

HOW TO INSTALL/API DOCUMENTATION
All in the readme.

DOWNLOAD AND SOURCE
The design has cross platform in mind. However, the machine I’m currently on runs Windows right now. I might reboot in Linux later to compile it there.

Download:
Windows

Source:

FUCK! I just sold my keyboard a week ago!
Really good job ftpje

Well what would this be used for other then the piano from the workshop?

Playing Gmod with a musical keyboard instead of a computer keyboard

This is very cool Falco, I would be surprised if you can get it to work under Linux though (I could be wrong of course) because I’ve never seen midi work in Linux and I’ve been using it for 15 years.

Extra keybinds (bind toolmodes to keyboard keys!) music gamemodes, guitar hero shit. Recording and sharing music.

You could use the pitch bend as a one dimensional joystick.

Fuck you could create a gamemode where you teach people to play piano.

Now I just need a mini midi controller so I can make a guitar hero gamemode

I was just thinking and brain storming on how to do this the other day…

I fucking love you…

Guitar hero multi player on gmod here we come!

Time to buy a new keyboard.

You’re literally my hero

If you wanted to do this the best way would be to get an xbox 360 wireless controller adapter with an xbox 360 guitar hero controller and use the xbox KEY_ enums, I actually want to go buy a controller and do this now!

I compiled a Linux version and added it to the v0.0.3 release. I can’t get my keyboard to work on Linux. Someone please try it:

Hey, SDL has some midi bindings doesn’t it it.

I have a library that’s supposed to be cross platform. I’m not recoding the entire thing for another (hugely bloated) library.

Module updated to send time information with each key.

Playing music is a VERY time sensitive thing. 100ms off can sound terrible. That’s why I added a time parameter to the MIDI hook. Regardless of your FPS, you will accurately know when a note was played.

The time is based on SysTime, which might make it somewhat harder to network, but it’s simply the most accurate time measurement.

Can you share your ‘gmcl_midi on MacDGUy’s playable piano’ script?

can you run midi files through this and pretend you’re a keyboard wizard?

Probably, yes.

[lua]require(“midi”)
print(midi.Open(0))
print(midi.IsOpened())

local MIDIKeys = {
[36] = { Sound = “a1” }, – C
[37] = { Sound = “b1” },
[38] = { Sound = “a2” },
[39] = { Sound = “b2” },
[40] = { Sound = “a3” },
[41] = { Sound = “a4” },
[42] = { Sound = “b3” },
[43] = { Sound = “a5” },
[44] = { Sound = “b4” },
[45] = { Sound = “a6” },
[46] = { Sound = “b5” },
[47] = { Sound = “a7” },
[48] = { Sound = “a8” }, – c
[49] = { Sound = “b6” },
[50] = { Sound = “a9” },
[51] = { Sound = “b7” },
[52] = { Sound = “a10” },
[53] = { Sound = “a11” },
[54] = { Sound = “b8” },
[55] = { Sound = “a12” },
[56] = { Sound = “b9” },
[57] = { Sound = “a13” },
[58] = { Sound = “b10” },
[59] = { Sound = “a14” },
[60] = { Sound = “a15” }, – c’
[61] = { Sound = “b11” },
[62] = { Sound = “a16” },
[63] = { Sound = “b12” },
[64] = { Sound = “a17” },
[65] = { Sound = “a18” },
[66] = { Sound = “b13” },
[67] = { Sound = “a19” },
[68] = { Sound = “b14” },
[69] = { Sound = “a20” },
[70] = { Sound = “b15” },
[71] = { Sound = “a21” },
[72] = { Sound = “a22” }, – c’’
[73] = { Sound = “b16” },
[74] = { Sound = “a23” },
[75] = { Sound = “b17” },
[76] = { Sound = “a24” },
[77] = { Sound = “a25” },
[78] = { Sound = “b18” },
[79] = { Sound = “a26” },
[80] = { Sound = “b19” },
[81] = { Sound = “a27” },
[82] = { Sound = “b20” },
[83] = { Sound = “a28” },
[84] = { Sound = “a29” }, – c’’’
[85] = { Sound = “b21” },
[86] = { Sound = “a30” },
[87] = { Sound = “b22” },
[88] = { Sound = “a31” },
[89] = { Sound = “a32” },
[90] = { Sound = “b23” },
[91] = { Sound = “a33” },
[92] = { Sound = “b24” },
[93] = { Sound = “a34” },
[94] = { Sound = “b25” },
[95] = { Sound = “a35” },
}

hook.Add(“MIDI”, “playablePiano”, function(time, command, note, velocity)
local instrument = LocalPlayer().Instrument
if !IsValid( instrument ) then return end

-- Zero velocity NOTE_ON substitutes NOTE_OFF
if !midi || midi.GetCommandName( command ) != "NOTE_ON" || velocity == 0 || !MIDIKeys || !MIDIKeys[note] then return end

// instrument:OnRegisteredKeyPlayed(MIDIKeys[note].Sound)

net.Start("InstrumentNetwork")
    net.WriteEntity(instrument)
    net.WriteInt(INSTNET_PLAY, 3)
    net.WriteString(MIDIKeys[note].Sound)
net.SendToServer()

end)
[/lua]