- Home /
Why is the keypress only registered on the second press?
Hi, this is a bit specialist but, I'm building a visualizer based on MIDI Input for live music performances. The idea is that you generate an object or whatever (in this case a star) with each press of a key on a MIDI controller keyboard.
I'm using keijiro's MidiJack code. To avoid having to create a separate 'if' statement for each of the 128 values for note numbers in MIDI I'm trying to grab the note number from the 'History' of MIDI Messages as a way of making the program respond to any note inputted. I also have this number displayed on screen.
My problem is that the number onscreen will update upon the first keypress, but it won't actually do anything until the second press of the same key. This isn't very useful for music as most note events are unique in a melody.
Just to clarify that I have had this 100% working with if statements that contain a specified note number, just not with this way of trying to retrieve the number from the list. I really hope someone can explain what I've done wrong, I'm really new to this!
Thanks!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MidiJack;
public class SpawnOBJ : MonoBehaviour
{
public Vector3 ObjectSpawnPosition;
public GameObject star; //Object to spawn is assigned in Unity Editor
public float flareSize;
private int starCount;
GameObject[] stars;
string notesGUI;
string noteStatusGUI;
string velocityGUI;
public int noteNumber;
bool noteOn;
bool noteOff;
public Texture fader;
private Color guiColor;
public float alphaLevel;
private float t;
public float duration; //sets fade length in seconds
Controls Controls = new Controls();
MidiDriver midiDriver;
private void Start()
{
starCount = 0;
Cursor.visible = false;
guiColor = Color.black;
alphaLevel = 0.0f;
notesGUI = 0.ToString();
}
void Update()
{
stars = GameObject.FindGameObjectsWithTag("Star");
starCount = stars.Length;
Controls.GUIhide();
Controls.GUIfade();
Controls.reset();
Controls.Zoom();
Controls.Quit();
foreach (var message in MidiDriver.Instance.History)
{
notesGUI = message.data1.ToString();//Retrieves the note number byte from MIDI interface and converts to string for GUI
noteStatusGUI = message.status.ToString();
velocityGUI = message.data2.ToString();
noteNumber = int.Parse(notesGUI); //Retrieves the note number byte from MIDI interface and converts to int for triggering
}
noteOn = MidiMaster.GetKeyDown(noteNumber);
noteOff = MidiMaster.GetKeyUp(noteNumber);
ObjectSpawnPosition = new Vector3
(Random.Range(-30f, 30f), Random.Range(-30f, 30f), Random.Range(5f, 120f)); //Random position for star spawning.
flareSize = Random.Range(0.1f, 1f); //Random brightness (size) of star flares.
//if (starCount < 300 && GameObject.Find("endMontage").GetComponent<playVideo>().isPlaying == false) //Sets Star instance limit and stop creation if video is playing
if (starCount < 300)
{
if (noteOn)
{
GameObject.Find("SolarFlare").GetComponent<LensFlare>().brightness = flareSize;
Instantiate(star, ObjectSpawnPosition, Quaternion.identity);
Debug.Log("MIDI");
}
if (Input.GetKeyDown(KeyCode.X)) //Spawns star object, used for testing.
{
GameObject.Find("SolarFlare").GetComponent<LensFlare>().brightness = flareSize;
Instantiate(star, ObjectSpawnPosition, Quaternion.identity);
}
}
}
private void OnGUI() //Draws the current number of stars onto screen and control hints
{
if (Controls.CountGUIEnabled)
{
GUI.Label(new Rect(0, 0, 200, 20), "Star Count:" + starCount);
GUI.Label(new Rect(0, 15, 200, 20), "Press R to Restart");
GUI.Label(new Rect(0, 30, 200, 20), "Press Z to Zoom");
GUI.Label(new Rect(0, 45, 200, 20), "Press V to Play Video");
GUI.Label(new Rect(0, 60, 200, 20), "Press S to Toggle GUI");
GUI.Label(new Rect(0, 75, 200, 20), "Press F to Fade Out");
GUI.Label(new Rect(0, 90, 200, 20), "Press Esc to Quit");
GUI.Label(new Rect(0, 105, 1000, 20), "Status: " + noteStatusGUI + " Note Number: " + notesGUI + " Velocity: " + velocityGUI); //Displays MIDI Note Number in GUI
}
if (Controls.GUIfadeOut)
{
if (t < 1) //sets time reference for fade
{
t += Time.deltaTime / duration;
}
GUI.color = guiColor;
guiColor.a = alphaLevel;
alphaLevel = Mathf.SmoothStep(-0.5f, 1, t); //Fades texture alpha from 0 to 1
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), fader, ScaleMode.StretchToFill, true, 10.0F); //Draws texture over screen
}
}
}
Answer by TheTechn0mancer · Jun 21, 2017 at 04:50 PM
stars = GameObject.FindGameObjectsWithTag("Star");
This isn't a very efficient way to grab the stars if you want to do it every frame.
Thanks for the tip! I'm not sure if that's causing the problem though.
I don't think it is the source of your problem, but performance-wise but you should create an Array and add the stars when you create them.
Answer by Linkthehylian04 · Jun 22, 2017 at 02:23 PM
Just make a function for each note, then put the if then sentence for the note in each one.
The only problem with that is if you want to change what the notes are triggering, you have to do it 128 times, right? I'm trying to make something which just responds to all 128 notes in the same way. $$anonymous$$y plan is to use this as a basis for a variety of different applications. Any clarification would be great, I'm so lost!
Answer by soniccustard · Jun 22, 2017 at 04:12 PM
I just made this, it does the same thing, but it makes much more sense, still has the same problem og only triggering on the second keypress, though.
using UnityEngine;
using MidiJack;
public class DelegateTester : MonoBehaviour
{
public GameObject cube;
int noteNumber;
public Vector3 ObjectSpawnPosition;
private void Update()
{
ObjectSpawnPosition = new Vector3
(Random.Range(-30f, 30f), Random.Range(-30f, 30f), Random.Range(5f, 120f));
if (MidiMaster.GetKeyDown(noteNumber))
{
makeCube();
}
}
void NoteOn(MidiChannel channel, int note, float velocity)
{
noteNumber = note;
Debug.Log("NoteOn: " + channel + "," + note + "," + velocity);
}
void OnEnable()
{
MidiMaster.noteOnDelegate += NoteOn;
}
void OnDisable()
{
MidiMaster.noteOnDelegate -= NoteOn;
}
void makeCube()
{
Instantiate(cube, ObjectSpawnPosition, Quaternion.identity);
}
}
Your answer
Follow this Question
Related Questions
Using MIDI input in a Unity game 0 Answers
Audio source play stop in Unity5 3 Answers
Prevent Feedback while recording audio RT 0 Answers
Play music in Unity without repeating a song 3 Answers
Issue: CrossPlatformInput...Multiple Inputs not taken, 0 Answers