public static void Initialize() { if (_init) { return; } //both midi in and midi out have the same ports uint portCount = MidiInput.GetPortCount(); //check if there are no midi devices available if (portCount == 0) { //print warning Debug.LogError("MIDIOUT: No Midi Output Devices Found!"); //leave return; } //setup output device handles OutPorts = new IntPtr[portCount]; for (uint i = 0; i < portCount; i++) { OutPorts[i] = MidiInternal.rtmidi_out_create_default(); MidiInternal.rtmidi_open_port(OutPorts[i], i, "LopeaMidi: Out " + i); } _handler = new GameObject("Midi Output"); _handler.hideFlags = HideFlags.HideInHierarchy; _handler.AddComponent <MidiOutput>(); _init = true; }
//Inside this update function is the hotswapping support for MIDI output devices. void Update() { uint current = GetCurrentPortCount(); if (current != portCount) { if (current == 0) { Shutdown(); } else { for (int i = 0; i < OutPorts.Length; i++) { MidiInternal.rtmidi_out_free(OutPorts[i]); OutPorts[i] = IntPtr.Zero; } count = current; OutPorts = new IntPtr[portCount]; for (uint i = 0; i < portCount; i++) { OutPorts[i] = MidiInternal.rtmidi_out_create_default(); MidiInternal.rtmidi_open_port(OutPorts[i], i, "LopeaMidi: Out " + i); } } } }
public static void SendRawData(uint port, byte[] data) { if (!_init) { //setup values Initialize(); //if initialization did not happen, print error message if (!_init) { //if something went wrong, print error Debug.LogError("Data to MIDI not sent!\n An error occured during the Initialization process!"); return; } } //check if port is valid if (port < OutPorts.Length) { //send message MidiInternal.rtmidi_out_send_message(OutPorts[port], data, data.Length); } else { Debug.LogError("Device port #" + port + " is invalid for output!"); } }
public static void Shutdown() { //check if the device was already shutdown if (!_init) { return; } //call the OnShutdown Method OnShutdown?.Invoke(); OnShutdown = null; //free all handles... for (int i = 0; i < OutPorts.Length; i++) { MidiInternal.rtmidi_out_free(OutPorts[i]); OutPorts[i] = IntPtr.Zero; } //erase everything OutPorts = null; _handler = null; //set init flag to false _init = false; }
public static bool Initialize() { if (_initialized) { return(true); } var portCount = MidiInput.GetPortCount(); if (portCount == 0) { return(false); } devices = new IntPtr[portCount]; for (uint i = 0; i < portCount; i++) { devices[i] = MidiInternal.rtmidi_in_create_default(); MidiInternal.rtmidi_in_ignore_types(devices[i], true, false, false); MidiInternal.rtmidi_open_port(devices[i], i, "Why am i doing this? " + i); } startTime = EditorApplication.timeSinceStartup; EditorApplication.update += Update; EditorApplication.playModeStateChanged += EditorApplicationOnplayModeStateChanged; _initialized = true; return(true); }
//frees RtMidiDevice static void freeHandle(IntPtr device) { //free pointer MidiInternal.rtmidi_in_free(device); //set pointer to null device = IntPtr.Zero; }
void OnDisable() { MidiInternal.rtmidi_in_free(ptr); MidiInternal.rtmidi_out_free(o); ptr = IntPtr.Zero; o = IntPtr.Zero; }
// Start is called before the first frame update void Start() { circles = new List <CircleData>(); circles.Add(new CircleData(0, center)); ptr = MidiInternal.rtmidi_in_create_default(); o = MidiInternal.rtmidi_out_create_default(); MidiInternal.rtmidi_open_port(ptr, 2, "da."); MidiInternal.rtmidi_open_port(o, 2, "yus."); // StartCoroutine(getdata()); }
static uint GetCurrentPortCount() { IntPtr handle = MidiInternal.rtmidi_out_create_default(); //get port count uint count = MidiInternal.rtmidi_get_port_count(handle); //free handle FreeHandle(handle); return(count); }
/// <summary> /// Get the number of midi devices available /// </summary> /// <returns>Number of MIDI devices connected.</returns> public static uint GetPortCount() { //create RTMidiDevice IntPtr handle = MidiInternal.rtmidi_in_create_default(); //get port count uint count = MidiInternal.rtmidi_get_port_count(handle); //free handle freeHandle(handle); return(count); }
//add device static void addDevice(uint port) { //create reference to RtMidi device IntPtr reference = MidiInternal.rtmidi_in_create_default(); //get port count //not using GetPortCount to avoid creating another RtMididevice uint count = MidiInternal.rtmidi_get_port_count(reference); //check if port number is invalid if (port >= count) { //send error Debug.LogError(string.Format("Port Number {0} cannot be used for Midi Input!\nPort range 0-{1}", port, count - 1)); //free reference freeHandle(reference); //quit return; } //get port name string name = MidiInternal.rtmidi_get_port_name(reference, port); //ignore types MidiInternal.rtmidi_in_ignore_types(reference, false, false, false); //add port to RtMidi device MidiInternal.rtmidi_open_port(reference, port, "LopeaMidi port: " + name); //create midi input handle MidiInDevice device = new MidiInDevice(port, reference, name); //add to array if (currdevices == null) { currdevices = new MidiInDevice[1]; currdevices[0] = device; } else { var newdevices = new MidiInDevice[currdevices.Length + 1]; for (int i = 0; i < currdevices.Length; i++) { newdevices[i] = currdevices[i]; } newdevices[currdevices.Length] = device; currdevices = newdevices; } }
private static void Update() { if (!_initialized) { return; } if (EditorApplication.isPlaying || EditorApplication.timeSinceStartup - startTime > 10 || devices.Length != MidiInput.GetPortCount()) { OnNextNote?.Invoke(new MidiID(-1, -1, -1, MidiStatus.Dummy)); Shutdown(); return; } IntPtr messages = Marshal.AllocHGlobal(1024); IntPtr size = Marshal.AllocHGlobal(4); for (int i = 0; i < devices.Length; i++) { while (true) { Marshal.WriteInt32(size, 1024); MidiInternal.rtmidi_in_get_message(devices[i], messages, size); if (Marshal.ReadInt32(size) == 0) { break; } byte[] m = new byte[Marshal.ReadInt32(size)]; Marshal.Copy(messages, m, 0, m.Length); var status = (MidiStatus)((m[0] >> 4)); if (status == MidiStatus.NoteOff) { status = MidiStatus.NoteOn; } OnNextNote?.Invoke(new MidiID(m[0] & 0x0F, m[1], i, status)); Shutdown(); Marshal.FreeHGlobal(size); Marshal.FreeHGlobal(messages); return; } } //deallocate pointers Marshal.FreeHGlobal(size); Marshal.FreeHGlobal(messages); }
//add device static MidiInDevice CreateDevice(uint port) { //create reference to RtMidi device IntPtr reference = MidiInternal.rtmidi_in_create_default(); //get port name string name = MidiInternal.rtmidi_get_port_name(reference, port); //ignore types MidiInternal.rtmidi_in_ignore_types(reference, false, false, false); //add port to RtMidi device MidiInternal.rtmidi_open_port(reference, port, "LopeaMidi port: " + name); //create midi input handle return(new MidiInDevice(port, reference, name)); }
public static void Shutdown() { if (!_initialized) { return; } for (int i = 0; i < devices.Length; i++) { MidiInternal.rtmidi_close_port(devices[i]); MidiInternal.rtmidi_in_free(devices[i]); devices[i] = (IntPtr)0; } _initialized = false; OnNextNote = null; EditorApplication.update = null; EditorApplication.playModeStateChanged -= EditorApplicationOnplayModeStateChanged; }
static void RestartDevices() { //cannot restart device if it hasn't started in the first place, if (!_initialized) { return; } var newPortCount = GetPortCount(); //find the device removed/added for (uint i = 0; i < newPortCount; i++) { string name = MidiInternal.rtmidi_get_port_name(currdevices[0].ptr, i); for (int j = 0; j < currdevices.Length; j++) { if (currdevices[j].name == name) { continue; } //once found, print message else if (currdevices[j].name != name && j == currdevices.Length - 1) { if (portCount < newPortCount) { print("Midi Device Added: " + name); } else { print("Midi Device Removed: " + currdevices[j].name); } } } } //shutdown the system Shutdown(); //reinitialize system Initialize(); }
/// <summary> /// Get the name of a vaild output device based on its device port number /// </summary> /// <param name="port">port number to get it's value from</param> /// <returns>string containing the name of the port, empty string if the port number is invalid.</returns> public static string GetPortName(uint port) { //if system has not been initialized, if (!_init) { //initialize system Initialize(); //leave if the initialization failed, if (!_init) { return(String.Empty); } } if (port > count) { return(string.Empty); } return(MidiInternal.rtmidi_get_port_name(OutPorts[0], port)); }
/// <summary> /// Gets the name of the port based on the port number given. /// </summary> /// <param name="port">port number to find the name of.</param> /// <returns></returns> public static string GetPortName(uint port) { //check if the value exists... if (port >= portCount) { //if not, print error and return nothing. Debug.LogError("MIDI port given does not exist when trying to find port name!"); return(string.Empty); } //if the system has not been initialized... if (!_initialized) { //create a reference to the port IntPtr refPort = MidiInternal.rtmidi_in_create_default(); //get name string name = MidiInternal.rtmidi_get_port_name(refPort, port); //free port freeHandle(refPort); return(name); } //system has already been initialized, get port name from device return(currdevices[port].name); }
// Update is called once per frame void Update() { list = new List <byte>(); for (int i = 0; i < header.Length; i++) { list.Add(header[i]); } list.Add(15); list.Add(0); for (int i = 0; i < circles.Count; i++) { if (circles[i].timer >= 100) { circles.RemoveAt(i); } var data = circles[i]; data.timer += Time.deltaTime * 30; circles[i] = data; } for (int i = 0, y = 0; y < 10; y++) { for (int x = 0; x < 10; x++, i++) { //reset color colors[i] = Color.black; for (int j = 0; j < circles.Count; j++) { float dist = Vector2.Distance(new Vector2(x, y), circles[j].center); Color col = gradient.Evaluate(Mathf.Sin(dist + Time.time * 30) / 2 + 0.5f); if (Mathf.Abs(dist - circles[j].timer) < 1) { colors[i] = col; } } //Color col = gradient.Evaluate(Mathf.Sin((x + y + Time.time) * Mathf.PI)); // checkerboard pattern list.Add((byte)(colors[i].r * 62)); list.Add((byte)(colors[i].g * 62)); list.Add((byte)(colors[i].b * 62)); } } list.Add(247); MidiInternal.rtmidi_out_send_message(o, list.ToArray(), list.Count); //store pointers IntPtr message = IntPtr.Zero; IntPtr size = IntPtr.Zero; //allocate pointers size = Marshal.AllocHGlobal(4); message = Marshal.AllocHGlobal(1024); // useful code right here while (true) { //get data from Midi device MidiInternal.rtmidi_in_get_message(ptr, message, size); //store size of message int s = Marshal.ReadInt32(size); //check if no message is sent if (s == 0) { //de-allocate and exit loop Marshal.FreeHGlobal(message); Marshal.FreeHGlobal(size); break; } //change center position byte[] data = new byte[s]; for (int i = 0; i < data.Length; i++) { data[i] = Marshal.ReadByte(message, i); } //change center changeCenter(data); } }
static void RestartDevices() { //cannot restart device if it hasn't started in the first place, if (!_initialized) { return; } var newPortCount = GetPortCount(); if (newPortCount == 0) { for (uint i = 0; i < portCount; i++) { print("Midi Device Removed: " + currdevices[i].name); } portCount = 0; Shutdown(); } else { //find the device removed/added for (uint i = 0; i < newPortCount; i++) { string name = MidiInternal.rtmidi_get_port_name(currdevices[0].ptr, i); for (int j = 0; j < currdevices.Length; j++) { if (currdevices[j].name == name) { continue; } //once found, print message if (currdevices[j].name != name && j == currdevices.Length - 1) { if (portCount < newPortCount) { print("Midi Device Added: " + name); } else { print("Midi Device Removed: " + currdevices[j].name); } } } } portCount = newPortCount; for (uint i = 0; i < currdevices.Length; i++) { removeDevice(i); } currdevices = null; currdevices = new MidiInDevice[portCount]; for (uint i = 0; i < portCount; i++) { currdevices[i] = CreateDevice(i); } } }
//On every frame, get current status of each midi device and store all its values. void Update() { //Loop based on Keijiro Takahashi's implementation. //https://github.com/keijiro/jp.keijiro.rtmidi/ if (_initialized) { //check if a device has been added/removed. if (portCount != GetPortCount()) { RestartDevices(); //if there are no devices available, quit if (!_initialized) { return; } } //allocate memory for messages IntPtr messages = Marshal.AllocHGlobal(1024); IntPtr size = Marshal.AllocHGlobal(4); //loop for every device active for (int i = 0; i < currdevices.Length; i++) { int currsize = 0; //loop indefinitely while (true) { //write max size for parameter (max size for a midi message is 1024 bytes) Marshal.WriteInt32(size, 1024); //get message and store timestamp double timestamp = MidiInternal.rtmidi_in_get_message(currdevices[i].ptr, messages, size); //parse size currsize = Marshal.ReadInt32(size); //if the message is empty, quit if (currsize == 0) { break; } //store messages in array byte[] m = new byte[currsize]; Marshal.Copy(messages, m, 0, currsize); // //parse message // //store new data MidiData data; //get status byte byte status = m[0]; //store data data = new MidiData((float)timestamp, //time since last midi message (MidiStatus)((status >> 4)), //midi type (8-15 defined) (status & 0x0F), //channel bit (0-15) m[1], //data1 byte (stores midi note ID usually) (currsize == 2) ? byte.MinValue : m[2], //data2 byte (sometimes this is 0 due to the length of the message) m, //raw data of the message i); //device port ID //some devices for whatever reason have both note on and off to be the same value //so note on/off status is based on velocity if (data.status == MidiStatus.NoteOn || data.status == MidiStatus.NoteOff) { data.status = (data.data2 != 0) ? MidiStatus.NoteOn : MidiStatus.NoteOff; } //add data to the device currdevices[i].AddData(data); } } //deallocate pointers Marshal.FreeHGlobal(size); Marshal.FreeHGlobal(messages); } }