private IEnumerator TriggerChecks(float time, int totalBeats) { const int freq = 16; for (var i = 0; i <= totalBeats; i++) { var total = 0; var totalMiss = 0; for (var j = 0; j < freq; j++) { // Check for accuracy var ons = _midiDeviceController.GetOnKeys(); var deltaTime = Time.time - startTime; var eligible = noteDurations.FindAll(e => e.start <= deltaTime && e.end >= deltaTime); eligible.ForEach(e => { total++; if (!ons.Contains(PianoKeys.GetKeyFor(e.keyNum))) { totalMiss++; } }); yield return(new WaitForSeconds(time / freq)); } piano.PutInstantFeedback(total, totalMiss, totalBeats); } }
private void handleChannelMsg(object sender, ChannelMessageEventArgs e) { var keyNum = e.Message.Data1; if (e.Message.Command == ChannelCommand.NoteOn) { PianoBuilder.instance.ActivateKey(keyNum, Color.green); notesOn.Add(PianoKeys.GetKeyFor(keyNum)); } else if (e.Message.Command == ChannelCommand.NoteOff) { PianoBuilder.instance.DeactivateKey(keyNum); notesOn.Remove(PianoKeys.GetKeyFor(keyNum)); } }
public void SaveScoresAndViewFeedback(MidiSessionDto session, bool save = true) { var userEvents = session.userNoteDurations; var trackEvents = session.trackNoteDurations; Debug.Log("User events: " + userEvents.Count()); Debug.Log("Track events: " + trackEvents.Count()); var segments = MakeSegmentsFor(userEvents, trackEvents); var velocity = 1f / session.velocityIn * session.noteScale; var total = 0d; var correct = 0d; if (userEvents.Count == 0) { Debug.LogWarning("No midievents recorded"); } foreach (var e in segments) { var keyNum = e.Key; var list = e.Value; foreach (var m in list) { var key = PianoKeys.GetKeyFor(keyNum); total++; var go = Instantiate(cube); var lmraway = piano.GetLMRAwayVectorsForKey(key, MidiFileSequencer.calcX(m.offsetY / velocity + m.scaleY / 2f / velocity)); spawnedSegments.Add(go); var dummy = new GameObject(); var k = piano.GetKeyObj(key); dummy.transform.SetParent(k.transform); go.transform.SetParent(piano.transform); var dropdownScale = go.transform.localScale; go.transform.localScale = new Vector3(dropdownScale.x, m.scaleY / velocity, dropdownScale.z); go.transform.position = lmraway.away; Color color; switch (m.type) { case MidiSegment.SegmentType.EXTRA: color = Color.red; go.transform.localScale += new Vector3(.0001f, .0001f, .0001f); break; case MidiSegment.SegmentType.CORRECT: color = Color.green; go.transform.localScale += new Vector3(.0002f, .0002f, .0002f); correct++; break; case MidiSegment.SegmentType.MISSED: color = Color.yellow; break; default: color = Color.black; // WTF C#?? break; } var rder = go.GetComponent <Renderer>(); rder.material.color = color; var rotation = Quaternion.LookRotation(lmraway.centre - lmraway.away); go.transform.rotation = rotation; go.transform.Rotate(0, -90f, 90f); } } var accuracy = correct / total; Debug.Log("Displaying end feedback text"); int score; if (save) { score = (int)(accuracy * 100); } else { score = (int)(session.Accuracy * 100); } piano.showText(session.FormattedTrackName + ": " + score + "%", 50, false); if (save) // dont resave a loaded session { Debug.Log("Saving session - score = " + accuracy * 100); // Same but update accuracy var midiSessionDTO = new MidiSessionDto(RuntimeSettings.MIDI_FILE_NAME, accuracy, userEvents, session.trackNoteDurations, session.noteScale, session.velocityIn, session.offsetStartTime); new MidiSessionController().putMidiSession(midiSessionDTO); } }
private List <CompressedNoteDuration> ConvertToNoteDurationFromMidiEventStorage(List <MidiEventStorage> midiEvents) { var list = new List <CompressedNoteDuration>(); while (midiEvents.Count() > 0) { // Until we have an empty list, keep searching notes and end of it if (midiEvents.Count == 0) { break; } var head = midiEvents.First(); if (head.isEnd) { Debug.LogError("Unexpected end of note"); } var keyNum = head.keyNum; for (var i = 1; i < midiEvents.Count(); i++) { if (midiEvents[i].keyNum == keyNum) { if (!midiEvents[i].isEnd) { Debug.LogError("Double Start of a note"); return(list); } var item = midiEvents[i]; list.Add(new CompressedNoteDuration(head.time, item.time - head.time, PianoKeys.GetKeyFor(keyNum))); midiEvents.Remove(head); midiEvents.Remove(item); break; } } } return(list); }
public void Update() { if (RuntimeSettings.LOAD_SAVED_SESSION_AT_STARTUP) { Debug.Log("Loading a saved session"); RuntimeSettings.LOAD_SAVED_SESSION_AT_STARTUP = false; scoreView.SaveScoresAndViewFeedback(RuntimeSettings.CACHED_SESSION, false); RuntimeSettings.CACHED_SESSION = null; ClearPianoRoll(); startTime = -1f; } if (startTime < 0f) { return; } var deltaT = Time.time - startTime; var minDistDict = new Dictionary <PianoKey, float>(); foreach (var i in PianoKeys.GetAllKeys()) { minDistDict[i] = 2f; } noteDurations.ForEach(note => { if (!note.hasKeyBeenActivated && deltaT >= note.start - note.duration && deltaT < note.end - note.duration) { piano.ActivateKey(note.keyNum, Color.red, note.duration); note.hasKeyBeenActivated = true; } if (deltaT >= note.start - note.duration && deltaT < note.end - note.duration) { minDistDict[PianoKeys.GetKeyFor(note.keyNum)] = 0; return; } if (deltaT > note.end) { return; } if (deltaT >= note.start - 2f && deltaT <= note.start) { minDistDict[PianoKeys.GetKeyFor(note.keyNum)] = Mathf.Min(Mathf.Abs(note.start - deltaT), minDistDict[PianoKeys.GetKeyFor(note.keyNum)]); } }); foreach (var item in minDistDict) { float h, s, v; Color.RGBToHSV(colorDict[item.Key], out h, out s, out v); if (item.Value == 2f) { s = 0f; } else { s = (2 - item.Value) / 2 * s; } var newc = Color.HSVToRGB(h, s, v); newc.a = (2 - item.Value) / 2; if (newc.a >= 1f) { shouldKeyBeOn[item.Key] = true; } else { shouldKeyBeOn[item.Key] = false; } piano.UpdateDiskColor(item.Key, newc); } if (noteDurations.Last().hasKeyBeenActivated || Input.GetKeyDown(KeyCode.Escape)) { scoreView.ConvertEventsSaveScoresAndViewFeedback(_midiDeviceController.GetMidiEvents(), noteDurations.Select(x => new CompressedNoteDuration(x)).ToList(), notesScale, RuntimeSettings.GAME_SPEED, startTime); ClearPianoRoll(); startTime = -1f; } if (gameStarted) { var step = RuntimeSettings.GAME_SPEED * Time.deltaTime; foreach (var item in pianoRollDict) { if (item.Value.Count == 0) { continue; } var lmr = piano.GetLMRAwayVectorsForKey(item.Key); foreach (var obj in item.Value) { obj.transform.Translate(0, -step, 0); if (obj.transform.childCount > 0) { var co = obj.transform.GetChild(0); var childScale = co.transform.localScale; var mag = (obj.transform.position - lmr.centre).magnitude; if (mag < childScale.y) { var cs = co.transform.localScale.y; obj.transform.localScale = new Vector3(1f, mag / cs, 1f); } if (mag < 0.01f) { DestroyImmediate(co.gameObject); } } } } foreach (var obj in fineLines) { var center = PianoKeys.GetKeyFor(PianoBuilder.CENTRE); var centerAway = keyAwayDir[center]; obj.transform.position = Vector3.MoveTowards(obj.transform.position, centerAway.transform.position, step); } } }
private void SpawnNotesDropDown(List <Note> notes) { Debug.Log("Spawning piano roll notes"); ClearPianoRoll(); notes.ForEach(e => { var number = e.NoteNumber; float y; var key = PianoKeys.GetKeyFor(number); if (key == null) { return; } var startMusical = (MusicalTimeSpan)e.TimeAs(TimeSpanType.Musical, tempoMapManager.TempoMap); var lengthMusical = e.LengthAs(TimeSpanType.Musical, tempoMapManager.TempoMap); y = (float)startMusical.Numerator / startMusical.Denominator * notesScale; var delta = (MusicalTimeSpan)lengthMusical; var scale = (float)delta.Numerator / delta.Denominator * notesScale; var lmraway = piano.GetLMRAwayVectorsForKey(key); var obj = Instantiate(pianoRollObject); var dummy = new GameObject("dummy"); var awayVector = lmraway.away; var lmraway2 = piano.GetLMRAwayVectorsForKey(key, calcX(y + scale / 2f)); var lmraway3 = piano.GetLMRAwayVectorsForKey(key, calcX(y + scale)); if (!keyAwayDir.ContainsKey(key)) { var newO = new GameObject(); newO.transform.position = piano.GetLMRAwayVectorsForKey(key, -1).away; newO.transform.SetParent(piano.GetKeyObj(key).transform); keyAwayDir[key] = newO; } var keyPos = lmraway.centre; dummy.transform.position = lmraway3.away; dummy.transform.rotation = Quaternion.LookRotation(keyPos - awayVector); dummy.transform.Rotate(0, -90f, 90f); dummy.transform.SetParent(piano.transform); obj.transform.SetParent(dummy.transform); pianoRollObjects.Add(obj); var dropdownScale = obj.transform.localScale; obj.transform.localScale = new Vector3(dropdownScale.x, scale, dropdownScale.z); var rotation = Quaternion.LookRotation(keyPos - awayVector); obj.transform.rotation = rotation; obj.transform.Rotate(0, -90f, 90f); obj.transform.position = lmraway2.away; var rendererObj = obj.GetComponent <Renderer>(); rendererObj.material.color = colorDict[key]; var expectTime = ((lmraway2.away - keyPos).magnitude + scale / 2) / RuntimeSettings.GAME_SPEED; var expectEnd = scale / RuntimeSettings.GAME_SPEED; pianoRollDict[key].Add(dummy); noteDurations.Add(new NoteDuration(expectTime, expectEnd, key)); }); // Spawn fine lines (horizontal) var lastNoteMusicalStart = (MusicalTimeSpan)notes.Last().TimeAs(TimeSpanType.Musical, tempoMapManager.TempoMap); var lastNoteMusicalLen = (MusicalTimeSpan)notes.Last().LengthAs(TimeSpanType.Musical, tempoMapManager.TempoMap); var lastNoteMuscialEnd = lastNoteMusicalStart + lastNoteMusicalLen; var lastBeatY = (float)lastNoteMuscialEnd.Numerator / lastNoteMusicalLen.Denominator * notesScale; var beatDelta = 1f * notesScale; var midKey = PianoKeys.GetKeyFor(PianoBuilder.CENTRE); var totalBeatsI = (int)(lastBeatY / beatDelta); for (var i = 1; i <= totalBeatsI; i++) { var line = Instantiate(fineLine); var v = piano.GetLMRAwayVectorsForKey(midKey, calcX(beatDelta * i)); var dummy = new GameObject("dummy Fineline"); dummy.transform.position = v.away; dummy.transform.SetParent(piano.GetKeyObj(midKey).transform); line.transform.SetParent(dummy.transform); line.transform.position = v.away; var rotation = Quaternion.LookRotation(v.centre - v.away); line.transform.rotation = rotation; line.transform.Rotate(0, 0f, 90f); fineLines.Add(dummy); } timeBetweenBeats = beatDelta / RuntimeSettings.GAME_SPEED; totalBeats = totalBeatsI; }