/// <summary> /// Create MusicXML.scorepartwisePart object by VsqTrack instance. /// </summary> /// <param name="track"></param> /// <param name="timesig_table"></param> /// <returns></returns> private scorepartwisePart createScorePart(VsqTrack track, TimesigVector timesig_table, TempoVector tempo_table) { var part = new scorepartwisePart(); var note_list = quantizeTrack(track, timesig_table, tempo_table); var measures = new List <scorepartwisePartMeasure>(); int measure = 0; Timesig timesig = new Timesig(0, 0); while (0 < note_list.Count) { int measure_start_clock = timesig_table.getClockFromBarCount(measure); int measure_end_clock = timesig_table.getClockFromBarCount(measure + 1); var tempo_change_in_measure = new TempoVector(); tempo_change_in_measure.AddRange( tempo_table .Where((tempo) => measure_start_clock <= tempo.Clock && tempo.Clock < measure_end_clock) .Select((tempo) => (TempoTableEntry)tempo.Clone())); // get the list of TiedEvent, contained in target measure. var in_measure_tied_note_list = note_list .Where((tied_event) => { int tied_event_start = tied_event.Clock; int tied_event_end = tied_event.Clock + tied_event.Length; return ((measure_start_clock <= tied_event_start && tied_event_start < measure_end_clock) || (measure_start_clock <= tied_event_end && tied_event_end < measure_end_clock) || (tied_event_start <= measure_start_clock && measure_end_clock <= tied_event_end)); }); // get the list of MusicXML.note. var in_measure_note_list = in_measure_tied_note_list .SelectMany((tied_event) => { var result = new List <object>(); int clock = tied_event.Clock; foreach (var note in tied_event) { int length = (int)note.duration.First; if (measure_start_clock <= clock && clock + length <= measure_end_clock) { var tempo_change = tempo_change_in_measure .FirstOrDefault((tempo) => tempo.Clock == clock); if (tempo_change != null) { var direction = new direction(); direction.placement = abovebelow.above; direction.placementSpecified = true; direction.directiontype = new directiontype[] { new directiontype() }; direction.directiontype[0].metronome.Add(new metronome()); var perminute = new perminute(); perminute.Value = getTempo(tempo_change).ToString(); direction.directiontype[0].metronome[0].Items = new object[] { notetypevalue.quarter, perminute }; direction.sound = new sound(); direction.sound.tempo = getTempo(tempo_change); direction.sound.tempoSpecified = true; result.Add(direction); } result.Add(note); } clock += length; } return(result); }); var partwise_measure = new scorepartwisePartMeasure(); partwise_measure.number = (measure + 1).ToString(); var items = new List <object>(); var measure_timesig = timesig_table.getTimesigAt(measure_start_clock); if (!measure_timesig.Equals(timesig)) { var attributes = new MusicXML.attributes(); attributes.divisions = 480; attributes.divisionsSpecified = true; attributes.time = new time[] { new time() }; attributes.time[0].beats.Add(measure_timesig.numerator.ToString()); attributes.time[0].beattype.Add(measure_timesig.denominator.ToString()); attributes.time[0].symbol = timesymbol.common; attributes.time[0].symbolSpecified = true; items.Add(attributes); } timesig = measure_timesig; items.AddRange(in_measure_note_list); partwise_measure.Items = items.ToArray(); measures.Add(partwise_measure); note_list.RemoveAll((tied_event) => tied_event.Clock + tied_event.Length <= measure_end_clock); measure++; } part.measure = measures.ToArray(); return(part); }
private void Init(TimesigVector timesig_table, TempoVector tempo_table, int clock_start, int length, int note_number, bool create_rest) { clock_ = clock_start; length_ = length; // 着目している範囲内のテンポのみを取り出す var small_tempo_table = new TempoVector(); small_tempo_table.AddRange( tempo_table .Where((tempo) => clock_start <= tempo.Clock && tempo.Clock < clock_start + length) .Select((tempo) => (TempoTableEntry)tempo.Clone())); // <pitch> エレメントのテンプレートを作成 MusicXML.pitch pitch = null; if (!create_rest) { pitch = new pitch(); int octave = VsqNote.getNoteOctave(note_number) + 1; step step; if (Enum.TryParse <step>(VsqNote.getNoteStringBase(note_number), out step)) { pitch.step = step; } pitch.octave = octave.ToString(); int alter = VsqNote.getNoteAlter(note_number); if (alter != 0) { pitch.alter = alter; pitch.alterSpecified = true; } } int clock_end = clock_start + length; int current_clock = clock_start; while (current_clock < clock_start + length) { int next_bar_clock = timesig_table.getClockFromBarCount(timesig_table.getBarCountFromClock(current_clock) + 1); int next_tempo_change = clock_end; if (small_tempo_table.Count > 0) { try { next_tempo_change = small_tempo_table .First((tempo) => { return(current_clock < tempo.Clock && tempo.Clock < clock_end); }) .Clock; } catch (InvalidOperationException) { } } int next_separation_point = Math.Min(Math.Min(clock_end, next_bar_clock), next_tempo_change); int remain = next_separation_point - current_clock; var template = templates_ .OrderByDescending((note) => note.duration.First) .FirstOrDefault((note) => note.duration.First <= remain); if (template == null) { break; } else { var note = template.Clone(); if (create_rest) { note.rest.Add(new rest()); } else { note.pitch.Add(pitch.Clone()); note.stem = new stem(); note.stem.Value = stemvalue.up; } notes_.Add(note); current_clock += (int)note.duration.First; } } // connect note with tie if (!create_rest && notes_.Count >= 2) { for (int i = 0; i < notes_.Count; ++i) { var note = notes_[i]; var tied_list = new List <tied>(); if (i < notes_.Count - 1) { var start_tie = new tie(); start_tie.type = startstop.start; note.tie.Add(start_tie); var tied = new tied(); tied.type = startstopcontinue.start; tied_list.Add(tied); } if (0 < i) { var stop_tie = new tie(); stop_tie.type = startstop.stop; note.tie.Add(stop_tie); var tied = new tied(); tied.type = startstopcontinue.stop; tied_list.Add(tied); } var notations = new notations(); notations.Items = tied_list.ToArray(); note.notations = new MusicXML.notations[] { notations }; } } }