Exemple #1
0
        public void Process(IPianoEvent e)
        {
            if (e is PedalChange pedal)
            {
                if (context.Output != null)
                {
                    context.Output(pedal);
                }
                return;
            }

            var staff            = GetStaffForEvent(e);
            var elements         = context.Score.Parts[0].Staves[staff - 1].Elements;
            var noteReleaseQueue = StavesUpcomingNoteReleaseQueue[staff - 1];
            var notePressQueue   = StavesUpcomingNotePressQueue[staff - 1];
            var pressedNotes     = StavesPressedNotes[staff - 1];
            var clock            = context.ElementIndices[staff - 1];

            var previousGroup = clock > 0 ? elements[clock - 1] : null;
            var currentGroup  = clock < elements.Length ? elements[clock] : null;
            var nextGroup     = clock < elements.Length - 1 ? elements[clock + 1] : null;

            var isFinished = currentGroup == null;
            var isStarting = previousGroup == null;


            switch (e)
            {
            case NoteRelease release:
                var physicalPitch = release.Pitch;

                var wasMappedPitchesFound = pressedNotes.ContainsKey(physicalPitch);

                if (!wasMappedPitchesFound)
                {
                    Trace.WriteLine($"{physicalPitch} was physically pressed and should correspond to the virtual playing of a notated note or chord, but the key press was not found to be linked to any virtually pressed notes.");
                    return;
                }

                var mappedPitches = pressedNotes[physicalPitch];
                if (context.Output != null)
                {
                    pressedNotes.Remove(physicalPitch);
                    foreach (var mappedPitch in mappedPitches)
                    {
                        context.Output(new NoteRelease()
                        {
                            Pitch = mappedPitch
                        });
                    }
                }
                break;

            case NotePress press:
                if (isFinished)
                {
                    return;
                }

                ProcessChord(physicalNotePressed: press, previousGroup !, currentGroup !, nextGroup !, pressedNotes);

                context.LastProcessedElementIndices[staff - 1] = context.ElementIndices[staff - 1];
                context.ElementIndices[staff - 1] += 1;

                context.Processed?.Invoke();
                break;
            }
        }
        public void Process(IPianoEvent e)
        {
            /* Pedal events don't advance the score or interact with notes in any way. */
            if (e is PedalChange)
            {
                if (context.Output != null)
                {
                    context.Output(e);
                }
                return;
            }

            var staff            = GetStaffForEvent(e);
            var elements         = context.Score.Parts[0].Staves[staff - 1].Elements;
            var noteReleaseQueue = StavesUpcomingNoteReleaseQueue[staff - 1];
            var notePressQueue   = StavesUpcomingNotePressQueue[staff - 1];
            var pressedNotes     = StavesPressedNotes[staff - 1];
            var clock            = context.ElementIndices[staff - 1];

            var previousGroup = clock > 0 ? elements[clock - 1] : null;
            var currentGroup  = clock < elements.Length ? elements[clock] : null;
            var nextGroup     = clock < elements.Length - 1 ? elements[clock + 1] : null;

            var isFinished = currentGroup == null;
            var isStarting = previousGroup == null;

            if (isFinished)
            {
                return;
            }

            switch (e)
            {
            case NoteRelease release:
                var physicalPitch = release.Pitch;

                /* Don't release notes before they are pressed */
                if (notePressQueue.Exists(x => x.Pitch == physicalPitch))
                {
                    noteReleaseQueue.Add(new NoteRelease()
                    {
                        Pitch = physicalPitch
                    });
                    return;
                }

                var wasMappedPitchFound = pressedNotes.ContainsKey(physicalPitch);

                if (!wasMappedPitchFound)
                {
                    Trace.WriteLine($"No pitch mapping found for {physicalPitch}, but it was a previously pressed note.");
                    return;
                }

                var mappedPitch = pressedNotes[physicalPitch];
                if (context.Output != null)
                {
                    pressedNotes.Remove(physicalPitch);
                    context.Output(new NoteRelease()
                    {
                        Pitch = mappedPitch
                    });
                }
                break;

            case NotePress press:
                if (pressedNotes.ContainsKey(press.Pitch) || notePressQueue.Exists(x => x.Pitch == press.Pitch))
                {
                    Console.WriteLine($"Ignoring {press.Pitch} because it's already pressed.");

                    if (pressedNotes.ContainsKey(press.Pitch))
                    {
                        Console.WriteLine($"   -> Pressed Notes Pitches: {new String(pressedNotes.SelectMany(a => $"{a.Key}: {a.Value} {Environment.NewLine}").ToArray())}");
                    }

                    if (notePressQueue.Exists(x => x.Pitch == press.Pitch))
                    {
                        Console.WriteLine($"   -> Note Press Queue Pitches: {new String(notePressQueue.SelectMany(a => $"{a.Pitch}: {a.Velocity} {Environment.NewLine}").ToArray())}");
                    }
                    // You can't press the same key if it's already being held down
                    // You can only do it on Android devices while testing
                    return;
                }

                notePressQueue.Add(press);

                var filteredCurrentGroup    = GetFilteredCurrentGroup(currentGroup !);
                var numRequiredNotesPressed = filteredCurrentGroup.Count();
                var areEnoughNotesPressed   = notePressQueue.Count >= numRequiredNotesPressed;

                if (areEnoughNotesPressed)
                {
                    foreach (NotePress notePress in notePressQueue)
                    {
                        ProcessChord(targetNotePress: notePress, notePresses: notePressQueue, previousGroup !, filteredCurrentGroup, nextGroup !, pressedNotes);
                    }
                    notePressQueue.Clear();

                    foreach (var noteRelease in noteReleaseQueue)
                    {
                        Process(noteRelease);
                    }
                    noteReleaseQueue.Clear();

                    context.LastProcessedElementIndices[staff - 1] = context.ElementIndices[staff - 1];
                    context.ElementIndices[staff - 1] += 1;

                    context.Processed?.Invoke();
                }
                break;
            }
        }