/// <summary> /// 화음에서 특정 음(before)을 다른 음(after)으로 바꾸어 반환합니다. /// </summary> /// <param name="chord"></param> /// <param name="before"></param> /// <param name="after"></param> /// <returns></returns> static Chord ReviseNote(Chord chord, int before, int after) { Chord newChord = new Chord(); newChord.SetChordName(chord.GetChordName()); newChord.SetChordText(chord.GetChordText()); newChord.SetBass(chord.GetBass()); foreach (int n in chord.GetNotes()) { if (n == before) { newChord.AddNote(after); } else { newChord.AddNote(n); } } Debug.Log("Chord ReviseNote " + newChord.GetBass()); if (chord.GetBass() == before) { newChord.SetBass(after); } else { newChord.SetBass(chord.GetBass()); } return(newChord); }
/// <summary> /// 화음의 음들이 악보에 겹치지 않고 표시될 수 있도록 음의 위치를 보정합니다. /// 만약 한 옥타브 내에서 겹칠 수밖에 없는 화음이라면 다른 옥타브로도 음을 옮겨봅니다. /// 보정을 완료하고 그 화음을 반환합니다. /// isTreble은 낮은음자리표이면 false를, 높은음자리표이면 true를 넣습니다. /// 악보에서 겹친다는 뜻은 두 음의 y좌표가 0.125 이하만큼 차이 난다는 뜻입니다. /// </summary> /// <param name="chord"></param> /// <returns></returns> public static Chord ReviseScoreNotation(Chord chord, bool isTreble) { //if (CheckScoreNotation(chord)) return chord; List <Chord> enumerated = new List <Chord>(); List <Chord> temp = new List <Chord>(); Chord initChord = new Chord(); initChord.SetChordName(chord.GetChordName()); initChord.SetChordText(chord.GetChordText()); initChord.SetBass(chord.GetBass()); // Initialize (half moving) foreach (int n in chord.GetNotes()) { if (Note.NoteToAccidental(n) == 2) // b이면 { initChord.AddNote(n - 1); // #으로 통일 } else { initChord.AddNote(n); } } Debug.Log("Chord ReviseScoreNotation " + initChord.GetBass()); for (int i = 0; i < initChord.GetNotes().Count; i++) { if (isTreble && (initChord.GetNotes()[i] / 17 < 2 || initChord.GetNotes()[i] / 17 > 3)) { initChord = ReviseNote(initChord, initChord.GetNotes()[i], initChord.GetNotes()[i] % 17 + 34); } else if (!isTreble && (initChord.GetNotes()[i] / 17 < 0 || initChord.GetNotes()[i] / 17 > 1)) { initChord = ReviseNote(initChord, initChord.GetNotes()[i], initChord.GetNotes()[i] % 17 + 17); } } // Enumerate all possible cases (half moving) enumerated.Add(initChord); for (int i = 0; i < initChord.GetNotes().Count; i++) { if (Note.NoteToAccidental(initChord.GetNotes()[i]) == 1) { temp.Clear(); foreach (Chord c in enumerated) { temp.Add(ReviseNote(c, initChord.GetNotes()[i], initChord.GetNotes()[i] + 1)); } foreach (Chord t in temp) { enumerated.Add(t); } } } // Check each case (half moving) foreach (Chord c in enumerated) { //Debug.Log("enumerated " + c.NotesName()); if (CheckScoreNotation(c, isTreble)) { return(c); } } // 반음 조절로 실패한 경우 옥타브 조절을 시도 initChord = new Chord(); enumerated.Clear(); initChord.SetChordName(chord.GetChordName()); initChord.SetChordText(chord.GetChordText()); initChord.SetBass(chord.GetBass()); // Initialize (octave moving) foreach (int n in chord.GetNotes()) { initChord.AddNote((n % 17) + 17); } // Enumerate all possible cases (octave moving) enumerated.Add(initChord); for (int i = initChord.GetNotes().Count - 1; i >= 0; i--) { if (initChord.GetNotes()[i] / 17 == 1) { temp.Clear(); foreach (Chord c in enumerated) { temp.Add(ReviseNote(c, initChord.GetNotes()[i], initChord.GetNotes()[i] - 17)); } foreach (Chord t in temp) { enumerated.Add(t); } } } // Check each case (octave moving) foreach (Chord c in enumerated) { //Debug.Log("octave enumerated " + c.NotesName()); if (CheckScoreNotation(c, isTreble)) { return(c); } } return(null); }
public void poll() { OscBundle bundle = null; while (bundle == null) { bundle = (OscBundle)listener.Receive(); Thread.Sleep(1); } //Debug.Log("Received a bundle!"); List <OscMessage> messages = bundle.Messages; OscMessage lastMessage = bundle.Messages[bundle.Messages.Count - 1]; switch (lastMessage.Address) { case "/notes_receiver": Note note = new Note(); object midiNumber = lastMessage.Arguments[0]; object start = lastMessage.Arguments[1]; object duration = lastMessage.Arguments[2]; // Typecheck to make sure that message is intact if (midiNumber is int midiNumberInt) { note.MidiNumber = midiNumberInt; note.Start = (float)start; note.Duration = (float)duration; note.Starts.Add((float)start); note.Durations.Add((float)duration); individualNote = note; receivedNote = true; } break; case "/notes_complete": isDoneReceivingNotes = true; break; case "/chords_receiver": int i = 0; object commonName = lastMessage.Arguments[i]; // Typecheck to make sure that message is intact if (commonName is string commonNameString) { // Initialise chord object chord = new Chord(); chord.CommonName = commonNameString; // Add all subsequent ints (notes) to the chord object until separator "|" is hit object next = lastMessage.Arguments[++i]; while (next is int nextMidiNumberInt) { Note individualNote = new Note(nextMidiNumberInt); chord.AddNote(individualNote); next = lastMessage.Arguments[++i]; } // After notes (int) in OSC message it's beat and duration (floats) var chordStart = (float)next; next = lastMessage.Arguments[++i]; var chordDuration = (float)next; chord.Start = chordStart; chord.Duration = chordDuration; receivedChord = true; } break; } poll(); }