private Voice CreateMergedVoice(Dictionary <string, Voice> voices) { if (voices.Count == 1) { return(voices.Values.First()); } MutableVoice mergedVoice = new MutableVoice(); List <Sentence> allSentences = voices.Values.SelectMany(voice => voice.Sentences).ToList(); List <Note> allNotes = allSentences.SelectMany(sentence => sentence.Notes).ToList(); // Sort notes by start beat allNotes.Sort((note1, note2) => note1.StartBeat.CompareTo(note2.StartBeat)); // Find sentence borders List <int> lineBreaks = allSentences.Select(sentence => sentence.LinebreakBeat).Where(lineBreak => lineBreak > 0).ToList(); lineBreaks.Sort(); int lineBreakIndex = 0; int nextLineBreakBeat = lineBreaks[lineBreakIndex]; // Create sentences MutableSentence mutableSentence = new MutableSentence(); foreach (Note note in allNotes) { if (!mutableSentence.GetNotes().IsNullOrEmpty() && (nextLineBreakBeat >= 0 && note.StartBeat > nextLineBreakBeat)) { // Finish the last sentence mutableSentence.SetLinebreakBeat(nextLineBreakBeat); mergedVoice.Add((Sentence)mutableSentence); mutableSentence = new MutableSentence(); lineBreakIndex++; if (lineBreakIndex < lineBreaks.Count) { nextLineBreakBeat = lineBreaks[lineBreakIndex]; } else { lineBreakIndex = -1; } } mutableSentence.Add(note); } // Finish the last sentence mergedVoice.Add((Sentence)mutableSentence); return((Voice)mergedVoice); }
public void TestInit() { mv = new MutableVoice(); }
public static Dictionary <string, Voice> ParseFile(string path, Encoding enc, IEnumerable <string> voiceIdentifiers) { Dictionary <string, MutableVoice> res = new Dictionary <string, MutableVoice>(); foreach (string voiceIdentifier in voiceIdentifiers) { res.Add(voiceIdentifier, new MutableVoice()); } MutableVoice currentVoice = null; MutableSentence currentSentence = null; bool endFound = false; // if this is a solo song (without a named voice) then just add one with identifier "" (empty string) if (res.Count == 0) { res.Add("", new MutableVoice()); currentVoice = res[""]; } using (StreamReader reader = TxtReader.GetFileStreamReader(path, enc)) { uint lineNumber = 0; while (!endFound && !reader.EndOfStream) { ++lineNumber; string line = reader.ReadLine(); switch (line[0]) { case '#': // headers are ignored at this stage break; case 'E': // finish any current open sentence if (currentVoice != null && currentSentence != null) { currentVoice.Add((Sentence)currentSentence); } // now we are done endFound = true; break; case 'P': // save the current sentence, if any if (currentVoice != null && currentSentence != null) { currentVoice.Add((Sentence)currentSentence); } // switch to the new voice try { currentVoice = res[line]; currentSentence = null; } catch (KeyNotFoundException) { ThrowLineError(lineNumber, "No such voice: " + line); } break; case '-': if (currentVoice == null) { ThrowLineError(lineNumber, "Linebreak encountered but no voice is active"); } else if (currentSentence == null) { ThrowLineError(lineNumber, "Linebreak encountered without preceding notes"); } try { currentSentence.SetLinebreakBeat(ParseLinebreak(line.Substring(2))); currentVoice.Add((Sentence)currentSentence); currentSentence = null; } catch (VoicesBuilderException e) { ThrowLineError(lineNumber, e.Message); } break; case ':': case '*': case 'F': case 'R': case 'G': if (currentVoice == null) { ThrowLineError(lineNumber, "Note encountered but no voice is active"); } else if (currentSentence == null) { currentSentence = new MutableSentence(); } try { currentSentence.Add(ParseNote(line)); } catch (VoicesBuilderException e) { ThrowLineError(lineNumber, e.Message); } break; default: ThrowLineError(lineNumber, "Invalid instruction: " + line); break; } } } Dictionary <string, Voice> actualRes = new Dictionary <string, Voice>(); foreach (var item in res) { actualRes.Add(item.Key, (Voice)item.Value); } return(actualRes); }