Example #1
0
        public byte GetStaffForEvent(IPianoEvent e)
        {
            switch (e)
            {
            case NotePress press:
                for (int i = 0; i < STAFF_PLAY_RANGES.Length; i++)
                {
                    var range = STAFF_PLAY_RANGES[i];
                    if (press.Pitch >= range.Start.Value && press.Pitch < range.End.Value)
                    {
                        return((byte)(i + 1));
                    }
                }
                return(0);

            case NoteRelease release:
                for (int i = 0; i < STAFF_PLAY_RANGES.Length; i++)
                {
                    var range = STAFF_PLAY_RANGES[i];
                    if (release.Pitch >= range.Start.Value && release.Pitch < range.End.Value)
                    {
                        return((byte)(i + 1));
                    }
                }
                return(0);
            }

            return(0);
        }
Example #2
0
        public void Input(IPianoEvent e)
        {
            if (context.Score.Parts.Length == 0)
            {
                return;
            }

            processor.Process(e);
        }
Example #3
0
 private void OnInterpreterOutput(IPianoEvent e)
 {
     foreach (var output in Engine.MidiOutputs)
     {
         switch (e)
         {
         case PedalChange pedal:
             output.Send(new byte[]
             {
                 MidiEvent.CC,
                 pedal.Pedal switch
                 {
                     PedalKind.UnaCorda => 67,
                     PedalKind.Sostenuto => 66,
                     PedalKind.Sustain => 64,
                     _ => 64
                 },
                 pedal.Position
             }, 0, 3, 0);
Example #4
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;
            }
        }
Example #5
0
 public void Send(IPianoEvent e)
 {
     Received(e);
 }
Example #6
0
 internal void SendOutput(IPianoEvent e)
 {
     Output?.Invoke(e);
 }
        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;
            }
        }