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); }
public void Input(IPianoEvent e) { if (context.Score.Parts.Length == 0) { return; } processor.Process(e); }
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);
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 Send(IPianoEvent e) { Received(e); }
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; } }