/// <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); }
// C2FORMAT.TXT line 85ff //LAYOUT (Beschreibung der Partitur-Formatvorlage) // if Dateikennung >= V2.1 // BYTE topDist // CHAR Ersatzzeichen fuer geschuetztes Leerzeichen ('\0' --> '$') // BYTE interDist // CHAR Ersatzzeichen fuer geschuetzten Bindestrich ('\0' --> '#') // else // INT topDist // INT interDist // endif // BYTE beamMode // FONT txtFont // BYTE txtAlign // BOOL allaBreve // UINT tempo // INT staves // if Dateikennung >= V2.1 // BYTE[16] nSound (Klang fuer Kanal 1 bis 16 // im 1. Byte ist hoechstes Bit gesetzt!) // BYTE[16] nVolume (Lautstaerke fuer Kanal 1 bis 16) // else (Version 2.0) // BYTE[9] nSound (Klang fuer Kanal 1 bis 9) // BYTE[9] nVolume (Lautstaerke fuer Kanal 1 bis 9) // endif // STAFF_LAYOUT[staves] //end private void ReadLAYOUT(byte[] buffer, ref uint position) { if (this.version >= FileVersion.V21) { Read(buffer, ref position, out BYTE topDist); Read(buffer, ref position, out CHAR spaceReplacement); Read(buffer, ref position, out BYTE interDist); Read(buffer, ref position, out CHAR dashReplacement); } else { Read(buffer, ref position, out INT topDist); Read(buffer, ref position, out INT interDist); } Read(buffer, ref position, out BYTE beamMode); this.ReadFONT(buffer, ref position); Read(buffer, ref position, out BYTE txtAlign); Read(buffer, ref position, out BOOL allaBreve); Read(buffer, ref position, out UINT tempo); Read(buffer, ref position, out INT staveCount); if (this.version >= FileVersion.V21) { var soundValues = new BYTE[16]; var volumeValues = new BYTE[16]; for (int i = 0; i < 16; i++) { Read(buffer, ref position, out soundValues[i]); } for (int i = 0; i < 16; i++) { Read(buffer, ref position, out volumeValues[i]); } } else { var soundValues = new BYTE[9]; var volumeValues = new BYTE[9]; for (int i = 0; i < 9; i++) { Read(buffer, ref position, out soundValues[i]); } for (int i = 0; i < 9; i++) { Read(buffer, ref position, out volumeValues[i]); } } // TODO hier hatte ich zuerst ein partlist-Array. R# hat eine Co-Varianz-Warnung angezeigt. Daher nun object-Array. this.Document.partlist = new partlist { Items = new object[staveCount] }; this.Document.part = new scorepartwisePart[staveCount]; this.InitStaves(staveCount); for (int i = 0; i < staveCount; i++) { // initialite partDescription structures for current staff var partDescription = new scorepart(); this.Document.partlist.Items[i] = partDescription; partDescription.id = "P" + (i + 1).ToString(CultureInfo.InvariantCulture); var partData = new scorepartwisePart { id = partDescription.id }; this.Document.part[i] = partData; var firstMeasure = new scorepartwisePartMeasure(); this.measures[i].Add(firstMeasure); firstMeasure.number = "1"; attributes att = firstMeasure.GetAttributes(); // 32 corresponds with duration values in readSTAFF() att.divisions = 32; att.divisionsSpecified = true; this.ReadSTAFFLAYOUT(buffer, ref position, i, partDescription); firstMeasure.AddClef( this.currentKeyForm[i], this.currentKeyLine[i], this.currentKeyOctavation[i]); } }