void AlignSymbols(List <MusicSymbol>[] allsymbols, SymbolWidths widths) { for (int track = 0; track < allsymbols.Length; track++) { List <MusicSymbol> symbols = allsymbols[track]; List <MusicSymbol> result = new List <MusicSymbol>(); int i = 0; /* If a track doesn't have a symbol for a starttime, * add a blank symbol. */ foreach (int start in widths.StartTimes) { /* BarSymbols are not included in the SymbolWidths calculations */ while (i < symbols.Count && (symbols[i] is BarSymbol) && symbols[i].StartTime <= start) { result.Add(symbols[i]); i++; } if (i < symbols.Count && symbols[i].StartTime == start) { while (i < symbols.Count && symbols[i].StartTime == start) { result.Add(symbols[i]); i++; } } else { result.Add(new BlankSymbol(start, 0)); } } /* For each starttime, increase the symbol width by * SymbolWidths.GetExtraWidth(). */ i = 0; while (i < result.Count) { if (result[i] is BarSymbol) { i++; continue; } int start = result[i].StartTime; int extra = widths.GetExtraWidth(track, start); result[i].Width += extra; /* Skip all remaining symbols with the same starttime. */ while (i < result.Count && result[i].StartTime == start) { i++; } } allsymbols[track] = result; } }
/** Create a new SheetMusic control. * MidiFile is the parsed midi file to display. * SheetMusic Options are the menu options that were selected. * * - Apply all the Menu Options to the MidiFile tracks. * - Calculate the key signature * - For each track, create a list of MusicSymbols (notes, rests, bars, etc) * - Vertically align the music symbols in all the tracks * - Partition the music notes into horizontal staffs */ public void init(MidiFile file, MidiOptions options) { if (options == null) { options = new MidiOptions(file); } zoom = 1.0f; filename = file.FileName; SetColors(options.colors, options.shadeColor, options.shade2Color); pen = new Pen(Color.Black, 1); List <MidiTrack> tracks = file.ChangeMidiNotes(options); SetNoteSize(options.largeNoteSize); scrollVert = options.scrollVert; showNoteLetters = options.showNoteLetters; TimeSignature time = file.Time; if (options.time != null) { time = options.time; } if (options.key == -1) { mainkey = GetKeySignature(tracks); } else { mainkey = new KeySignature(options.key); } numtracks = tracks.Count; int lastStart = file.EndTime() + options.shifttime; /* Create all the music symbols (notes, rests, vertical bars, and * clef changes). The symbols variable contains a list of music * symbols for each track. The list does not include the left-side * Clef and key signature symbols. Those can only be calculated * when we create the staffs. */ List <MusicSymbol>[] symbols = new List <MusicSymbol> [numtracks]; for (int tracknum = 0; tracknum < numtracks; tracknum++) { MidiTrack track = tracks[tracknum]; ClefMeasures clefs = new ClefMeasures(track.Notes, time.Measure); List <ChordSymbol> chords = CreateChords(track.Notes, mainkey, time, clefs); symbols[tracknum] = CreateSymbols(chords, clefs, time, lastStart); } List <LyricSymbol>[] lyrics = null; if (options.showLyrics) { lyrics = GetLyrics(tracks); } /* Vertically align the music symbols */ SymbolWidths widths = new SymbolWidths(symbols, lyrics); // SymbolWidths widths = new SymbolWidths(symbols); AlignSymbols(symbols, widths); staffs = CreateStaffs(symbols, mainkey, options, time.Measure); CreateAllBeamedChords(symbols, time); if (lyrics != null) { AddLyricsToStaffs(staffs, lyrics); } /* After making chord pairs, the stem directions can change, * which affects the staff height. Re-calculate the staff height. */ foreach (Staff staff in staffs) { staff.CalculateHeight(); } BackColor = Color.White; SetZoom(1.0f); }