예제 #1
0
        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);
            }
        }
예제 #2
0
        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));
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
        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;
        }