List <MusicSymbol> AddRests(List <MusicSymbol> symbols, TimeSignature time) { int prevtime = 0; List <MusicSymbol> result = new List <MusicSymbol>(symbols.Count); foreach (MusicSymbol symbol in symbols) { int starttime = symbol.StartTime; RestSymbol[] rests = GetRests(time, prevtime, starttime); if (rests != null) { foreach (RestSymbol r in rests) { result.Add(r); } } result.Add(symbol); /* Set prevtime to the end time of the last note/symbol. */ if (symbol is ChordSymbol) { ChordSymbol chord = (ChordSymbol)symbol; prevtime = Math.Max(chord.EndTime, prevtime); } else { prevtime = Math.Max(starttime, prevtime); } } return(result); }
FindConsecutiveChords(List <MusicSymbol> symbols, TimeSignature time, int startIndex, int[] chordIndexes, ref int horizDistance) { int i = startIndex; int numChords = chordIndexes.Length; while (true) { horizDistance = 0; /* Find the starting chord */ while (i < symbols.Count - numChords) { if (symbols[i] is ChordSymbol) { ChordSymbol c = (ChordSymbol)symbols[i]; if (c.Stem != null) { break; } } i++; } if (i >= symbols.Count - numChords) { chordIndexes[0] = -1; return(false); } chordIndexes[0] = i; bool foundChords = true; for (int chordIndex = 1; chordIndex < numChords; chordIndex++) { i++; int remaining = numChords - 1 - chordIndex; while ((i < symbols.Count - remaining) && (symbols[i] is BlankSymbol)) { horizDistance += symbols[i].Width; i++; } if (i >= symbols.Count - remaining) { return(false); } if (!(symbols[i] is ChordSymbol)) { foundChords = false; break; } chordIndexes[chordIndex] = i; horizDistance += symbols[i].Width; } if (foundChords) { return(true); } /* Else, start searching again from index i */ } }
/** Find the initial clef to use for this staff. Use the clef of * the first ChordSymbol. */ private Clef FindClef(List <MusicSymbol> list) { foreach (MusicSymbol m in list) { if (m is ChordSymbol) { ChordSymbol c = (ChordSymbol)m; return(c.Clef); } } return(Clef.Treble); }
public void TestNotesOverlap() { SheetMusic.SetNoteSize(false); KeySignature key = new KeySignature(0, 0); int quarter = 400; TimeSignature time = new TimeSignature(4, 4, quarter, 60000); int num1 = WhiteNote.BottomTreble.Number(); int num2 = num1 + 1; MidiNote note1 = new MidiNote(0, 0, num1, quarter); MidiNote note2 = new MidiNote(0, 0, num2, quarter); List<MidiNote> notes = new List<MidiNote>(2); notes.Add(note1); notes.Add(note2); ChordSymbol chord = new ChordSymbol(notes, key, time, Clef.Treble, null); Assert.AreEqual(chord.ToString(), "ChordSymbol clef=Treble start=0 end=400 width=25 hastwostems=False AccidSymbol accid=Sharp whitenote=F4 clef=Treble width=9 Note whitenote=F4 duration=Quarter leftside=True Note whitenote=F4 duration=Quarter leftside=True Stem duration=Quarter direction=1 top=F4 bottom=F4 end=E5 overlap=False side=2 width_to_pair=0 receiver_in_pair=False "); }
CreateBeamedChords(List <MusicSymbol>[] allsymbols, TimeSignature time, int numChords, bool startBeat) { int[] chordIndexes = new int[numChords]; ChordSymbol[] chords = new ChordSymbol[numChords]; foreach (List <MusicSymbol> symbols in allsymbols) { int startIndex = 0; while (true) { int horizDistance = 0; bool found = FindConsecutiveChords(symbols, time, startIndex, chordIndexes, ref horizDistance); if (!found) { break; } for (int i = 0; i < numChords; i++) { chords[i] = (ChordSymbol)symbols[chordIndexes[i]]; } if (ChordSymbol.CanCreateBeam(chords, time, startBeat)) { ChordSymbol.CreateBeam(chords, horizDistance); startIndex = chordIndexes[numChords - 1] + 1; } else { startIndex = chordIndexes[0] + 1; } /* What is the value of startIndex here? * If we created a beam, we start after the last chord. * If we failed to create a beam, we start after the first chord. */ } } }
/** Calculate the start and end time of this staff. */ private void CalculateStartEndTime() { starttime = endtime = 0; if (symbols.Count == 0) { return; } starttime = symbols[0].StartTime; foreach (MusicSymbol m in symbols) { if (endtime < m.StartTime) { endtime = m.StartTime; } if (m is ChordSymbol) { ChordSymbol c = (ChordSymbol)m; if (endtime < c.EndTime) { endtime = c.EndTime; } } } }
List <ChordSymbol> CreateChords(List <MidiNote> midinotes, KeySignature key, TimeSignature time, ClefMeasures clefs) { int i = 0; List <ChordSymbol> chords = new List <ChordSymbol>(); List <MidiNote> notegroup = new List <MidiNote>(12); int len = midinotes.Count; while (i < len) { int starttime = midinotes[i].StartTime; Clef clef = clefs.GetClef(starttime); /* Group all the midi notes with the same start time * into the notes list. */ notegroup.Clear(); notegroup.Add(midinotes[i]); i++; while (i < len && midinotes[i].StartTime == starttime) { notegroup.Add(midinotes[i]); i++; } /* Create a single chord from the group of midi notes with * the same start time. */ ChordSymbol chord = new ChordSymbol(notegroup, key, time, clef, this); chords.Add(chord); } return(chords); }
public int GetHorizontalScrollDestination(int currentPulseTime, int prevPulseTime) { int scrollDestination = 0; /* If there's nothing to unshade, or shade, return */ if ((starttime > prevPulseTime || endtime < prevPulseTime) && (starttime > currentPulseTime || endtime < currentPulseTime)) { return(scrollDestination); } /* Skip the left side Clef symbol and key signature */ int xpos = keysigWidth; MusicSymbol curr = null; ChordSymbol prevChord = null; int prev_xpos = 0; /* Loop through the symbols. * Unshade symbols where start <= prevPulseTime < end * Shade symbols where start <= currentPulseTime < end */ for (int i = 0; i < symbols.Count; i++) { curr = symbols[i]; if (curr is BarSymbol) { xpos += curr.Width; continue; } int start = curr.StartTime; int end = 0; if (i + 2 < symbols.Count && symbols[i + 1] is BarSymbol) { end = symbols[i + 2].StartTime; } else if (i + 1 < symbols.Count) { end = symbols[i + 1].StartTime; } else { end = endtime; } /* If we've past the previous and current times, we're done. */ if ((start > prevPulseTime) && (start > currentPulseTime)) { if (scrollDestination == 0) { scrollDestination = xpos; } return(scrollDestination); } // If symbol is in the current time, draw a shaded background if ((start <= currentPulseTime) && (currentPulseTime < end)) { scrollDestination = xpos; } if (curr is ChordSymbol) { ChordSymbol chord = (ChordSymbol)curr; if (chord.Stem != null && !chord.Stem.Receiver) { prevChord = (ChordSymbol)curr; prev_xpos = xpos; } } xpos += curr.Width; } return(scrollDestination); }
/// <summary> /// Shade all the chords played in the given time. /// Un-shade any chords shaded in the previous pulse time. /// Store the x coordinate location where the shade was drawn. /// </summary> /// <param name="g"></param> /// <param name="shadeBrush"></param> /// <param name="pen"></param> /// <param name="currentPulseTime"></param> /// <param name="prevPulseTime"></param> /// <param name="x_shade"></param> public void ShadeNotes(Graphics g, SolidBrush shadeBrush, Pen pen, int currentPulseTime, int prevPulseTime, ref int x_shade) { // If there's nothing to unshade, or shade, return if ((starttime > prevPulseTime || endtime < prevPulseTime) && (starttime > currentPulseTime || endtime < currentPulseTime)) { return; } // Skip the left side Clef symbol and key signature int xpos = keysigWidth; MusicSymbol curr = null; ChordSymbol prevChord = null; int prev_xpos = 0; // Loop through the symbols. // Unshade symbols where start <= prevPulseTime < end // Shade symbols where start <= currentPulseTime < end for (int i = 0; i < symbols.Count; i++) { curr = symbols[i]; if (curr is BarSymbol) { xpos += curr.Width; continue; } int start = curr.StartTime; int end = 0; if (i + 2 < symbols.Count && symbols[i + 1] is BarSymbol) { end = symbols[i + 2].StartTime; } else if (i + 1 < symbols.Count) { end = symbols[i + 1].StartTime; } else { end = endtime; } // If we've past the previous and current times, we're done. if ((start > prevPulseTime) && (start > currentPulseTime)) { if (x_shade == 0) { x_shade = xpos; } return; } // If symbol is in the current time, draw a shaded background if ((start <= currentPulseTime) && (currentPulseTime < end)) { x_shade = xpos; g.TranslateTransform(xpos, 0); g.FillRectangle(shadeBrush, 0, 0, curr.Width, this.Height); g.TranslateTransform(-xpos, 0); } if (curr is ChordSymbol) { ChordSymbol chord = (ChordSymbol)curr; if (chord.Stem != null && !chord.Stem.Receiver) { prevChord = (ChordSymbol)curr; prev_xpos = xpos; } } xpos += curr.Width; } }
public void TestSixteenthDuration() { SheetMusic.SetNoteSize(false); KeySignature key = new KeySignature(0, 0); int quarter = 400; TimeSignature time = new TimeSignature(4, 4, quarter, 60000); int num1 = WhiteNote.BottomTreble.Number(); MidiNote note1 = new MidiNote(0, 0, num1, quarter/4); List<MidiNote> notes = new List<MidiNote>(2); notes.Add(note1); ChordSymbol chord = new ChordSymbol(notes, key, time, Clef.Treble, null); Assert.AreEqual(chord.ToString(), "ChordSymbol clef=Treble start=0 end=100 width=16 hastwostems=False Note whitenote=F4 duration=Sixteenth leftside=True Stem duration=Sixteenth direction=1 top=F4 bottom=F4 end=G5 overlap=False side=2 width_to_pair=0 receiver_in_pair=False "); Assert.AreEqual(chord.AboveStaff, SheetMusic.NoteHeight); }
/** We're connecting the stems of three or more chords using a horizontal beam. * Adjust the vertical endpoint of the stems, so that the middle chord stems * are vertically in between the first and last stem. */ static void LineUpStemEnds(ChordSymbol[] chords) { Stem firstStem = chords[0].Stem; Stem lastStem = chords[chords.Length-1].Stem; Stem middleStem = chords[1].Stem; if (firstStem.Direction == Stem.Up) { /* Find the highest stem. The beam will either: * - Slant downwards (first stem is highest) * - Slant upwards (last stem is highest) * - Be straight (middle stem is highest) */ WhiteNote top = firstStem.End; foreach (ChordSymbol chord in chords) { top = WhiteNote.Max(top, chord.Stem.End); } if (top == firstStem.End && top.Dist(lastStem.End) >= 2) { firstStem.End = top; middleStem.End = top.Add(-1); lastStem.End = top.Add(-2); } else if (top == lastStem.End && top.Dist(firstStem.End) >= 2) { firstStem.End = top.Add(-2); middleStem.End = top.Add(-1); lastStem.End = top; } else { firstStem.End = top; middleStem.End = top; lastStem.End = top; } } else { /* Find the bottommost stem. The beam will either: * - Slant upwards (first stem is lowest) * - Slant downwards (last stem is lowest) * - Be straight (middle stem is highest) */ WhiteNote bottom = firstStem.End; foreach (ChordSymbol chord in chords) { bottom = WhiteNote.Min(bottom, chord.Stem.End); } if (bottom == firstStem.End && lastStem.End.Dist(bottom) >= 2) { middleStem.End = bottom.Add(1); lastStem.End = bottom.Add(2); } else if (bottom == lastStem.End && firstStem.End.Dist(bottom) >= 2) { middleStem.End = bottom.Add(1); firstStem.End = bottom.Add(2); } else { firstStem.End = bottom; middleStem.End = bottom; lastStem.End = bottom; } } /* All middle stems have the same end */ for (int i = 1; i < chords.Length-1; i++) { Stem stem = chords[i].Stem; stem.End = middleStem.End; } }
/** We're connecting the stems of two chords using a horizontal beam. * Adjust the vertical endpoint of the stems, so that they're closer * together. For a dotted 8th to 16th beam, increase the stem of the * dotted eighth, so that it's as long as a 16th stem. */ static void BringStemsCloser(ChordSymbol[] chords) { Stem firstStem = chords[0].Stem; Stem lastStem = chords[1].Stem; /* If we're connecting a dotted 8th to a 16th, increase * the stem end of the dotted eighth. */ if (firstStem.Duration == NoteDuration.DottedEighth && lastStem.Duration == NoteDuration.Sixteenth) { if (firstStem.Direction == Stem.Up) { firstStem.End = firstStem.End.Add(2); } else { firstStem.End = firstStem.End.Add(-2); } } /* Bring the stem ends closer together */ int distance = Math.Abs(firstStem.End.Dist(lastStem.End)); if (firstStem.Direction == Stem.Up) { if (WhiteNote.Max(firstStem.End, lastStem.End) == firstStem.End) lastStem.End = lastStem.End.Add(distance/2); else firstStem.End = firstStem.End.Add(distance/2); } else { if (WhiteNote.Min(firstStem.End, lastStem.End) == firstStem.End) lastStem.End = lastStem.End.Add(-distance/2); else firstStem.End = firstStem.End.Add(-distance/2); } }
/** Connect the chords using a horizontal beam. * * spacing is the horizontal distance (in pixels) between the right side * of the first chord, and the right side of the last chord. * * To make the beam: * - Change the stem directions for each chord, so they match. * - In the first chord, pass the stem location of the last chord, and * the horizontal spacing to that last stem. * - Mark all chords (except the first) as "receiver" pairs, so that * they don't draw a curvy stem. */ public static void CreateBeam(ChordSymbol[] chords, int spacing) { Stem firstStem = chords[0].Stem; Stem lastStem = chords[chords.Length-1].Stem; /* Calculate the new stem direction */ int newdirection = -1; foreach (ChordSymbol chord in chords) { if (chord.HasTwoStems) { newdirection = chord.Stem.Direction; break; } } if (newdirection == -1) { WhiteNote note1; WhiteNote note2; note1 = (firstStem.Direction == Stem.Up ? firstStem.Top : firstStem.Bottom); note2 = (lastStem.Direction == Stem.Up ? lastStem.Top : lastStem.Bottom); newdirection = StemDirection(note1, note2, chords[0].Clef); } foreach (ChordSymbol chord in chords) { chord.Stem.Direction = newdirection; } if (chords.Length == 2) { BringStemsCloser(chords); } else { LineUpStemEnds(chords); } firstStem.SetPair(lastStem, spacing); for (int i = 1; i < chords.Length; i++) { chords[i].Stem.Receiver = true; } }
/** Return true if the chords can be connected, where their stems are * joined by a horizontal beam. In order to create the beam: * * - The chords must be in the same measure. * - The chord stems should not be a dotted duration. * - The chord stems must be the same duration, with one exception * (Dotted Eighth to Sixteenth). * - The stems must all point in the same direction (up or down). * - The chord cannot already be part of a beam. * * - 6-chord beams must be 8th notes in 3/4, 6/8, or 6/4 time * - 3-chord beams must be either triplets, or 8th notes (12/8 time signature) * - 4-chord beams are ok for 2/2, 2/4 or 4/4 time, any duration * - 4-chord beams are ok for other times if the duration is 16th * - 2-chord beams are ok for any duration * * If startQuarter is true, the first note should start on a quarter note * (only applies to 2-chord beams). */ public static bool CanCreateBeam(ChordSymbol[] chords, TimeSignature time, bool startQuarter) { int numChords = chords.Length; Stem firstStem = chords[0].Stem; Stem lastStem = chords[chords.Length-1].Stem; if (firstStem == null || lastStem == null) { return false; } int measure = chords[0].StartTime / time.Measure; NoteDuration dur = firstStem.Duration; NoteDuration dur2 = lastStem.Duration; bool dotted8_to_16 = false; if (chords.Length == 2 && dur == NoteDuration.DottedEighth && dur2 == NoteDuration.Sixteenth) { dotted8_to_16 = true; } if (dur == NoteDuration.Whole || dur == NoteDuration.Half || dur == NoteDuration.DottedHalf || dur == NoteDuration.Quarter || dur == NoteDuration.DottedQuarter || (dur == NoteDuration.DottedEighth && !dotted8_to_16)) { return false; } if (numChords == 6) { if (dur != NoteDuration.Eighth) { return false; } bool correctTime = ((time.Numerator == 3 && time.Denominator == 4) || (time.Numerator == 6 && time.Denominator == 8) || (time.Numerator == 6 && time.Denominator == 4) ); if (!correctTime) { return false; } if (time.Numerator == 6 && time.Denominator == 4) { /* first chord must start at 1st or 4th quarter note */ int beat = time.Quarter * 3; if ((chords[0].StartTime % beat) > time.Quarter/6) { return false; } } } else if (numChords == 4) { if (time.Numerator == 3 && time.Denominator == 8) { return false; } bool correctTime = (time.Numerator == 2 || time.Numerator == 4 || time.Numerator == 8); if (!correctTime && dur != NoteDuration.Sixteenth) { return false; } /* chord must start on quarter note */ int beat = time.Quarter; if (dur == NoteDuration.Eighth) { /* 8th note chord must start on 1st or 3rd quarter note */ beat = time.Quarter * 2; } else if (dur == NoteDuration.ThirtySecond) { /* 32nd note must start on an 8th beat */ beat = time.Quarter / 2; } if ((chords[0].StartTime % beat) > time.Quarter/6) { return false; } } else if (numChords == 3) { bool valid = (dur == NoteDuration.Triplet) || (dur == NoteDuration.Eighth && time.Numerator == 12 && time.Denominator == 8); if (!valid) { return false; } /* chord must start on quarter note */ int beat = time.Quarter; if (time.Numerator == 12 && time.Denominator == 8) { /* In 12/8 time, chord must start on 3*8th beat */ beat = time.Quarter/2 * 3; } if ((chords[0].StartTime % beat) > time.Quarter/6) { return false; } } else if (numChords == 2) { if (startQuarter) { int beat = time.Quarter; if ((chords[0].StartTime % beat) > time.Quarter/6) { return false; } } } foreach (ChordSymbol chord in chords) { if ((chord.StartTime / time.Measure) != measure) return false; if (chord.Stem == null) return false; if (chord.Stem.Duration != dur && !dotted8_to_16) return false; if (chord.Stem.isBeam) return false; } /* Check that all stems can point in same direction */ bool hasTwoStems = false; int direction = Stem.Up; foreach (ChordSymbol chord in chords) { if (chord.HasTwoStems) { if (hasTwoStems && chord.Stem.Direction != direction) { return false; } hasTwoStems = true; direction = chord.Stem.Direction; } } /* Get the final stem direction */ if (!hasTwoStems) { WhiteNote note1; WhiteNote note2; note1 = (firstStem.Direction == Stem.Up ? firstStem.Top : firstStem.Bottom); note2 = (lastStem.Direction == Stem.Up ? lastStem.Top : lastStem.Bottom); direction = StemDirection(note1, note2, chords[0].Clef); } /* If the notes are too far apart, don't use a beam */ if (direction == Stem.Up) { if (Math.Abs(firstStem.Top.Dist(lastStem.Top)) >= 11) { return false; } } else { if (Math.Abs(firstStem.Bottom.Dist(lastStem.Bottom)) >= 11) { return false; } } return true; }
public void ShadeNotes(Graphics g, SolidBrush shadeBrush, Pen pen, float x_shade, bool shade) { /* Skip the left side Clef symbol and key signature */ int xpos = keysigWidth; MusicSymbol curr = null; ChordSymbol prevChord = null; int prev_xpos = 0; /* Loop through the symbols. * Unshade symbols where start <= prevPulseTime < end * Shade symbols where start <= currentPulseTime < end */ for (int i = 0; i < symbols.Count; i++) { curr = symbols[i]; if (curr is BarSymbol) { xpos += curr.Width; continue; } int start = curr.StartTime; int end = 0; if (i + 2 < symbols.Count && symbols[i + 1] is BarSymbol) { end = symbols[i + 2].StartTime; } else if (i + 1 < symbols.Count) { end = symbols[i + 1].StartTime; } else { end = endtime; } /* If we've past, we're done. */ if (x_shade < xpos) { return; } bool redrawLines = false; /* If symbol is in the current time, draw a shaded background */ if (xpos <= x_shade && x_shade < xpos + curr.Width) { if (shade) { g.TranslateTransform(xpos, 0); g.FillRectangle(shadeBrush, 0, 0, curr.Width, this.Height); curr.Draw(g, pen, ytop); g.TranslateTransform(-xpos, 0); //redrawLines = true; if (curr is ChordSymbol) { (curr as ChordSymbol).Play(); } } else { g.TranslateTransform(xpos - 2, -2); g.FillRectangle(Brushes.White, 0, 0, curr.Width + 4, this.Height + 4); g.TranslateTransform(-(xpos - 2), 2); g.TranslateTransform(xpos, 0); curr.Draw(g, pen, ytop); g.TranslateTransform(-xpos, 0); } redrawLines = true; } /* If either a gray or white background was drawn, we need to redraw * the horizontal staff lines, and redraw the stem of the previous chord. */ if (redrawLines) { ReDrawLines(g, pen, curr, xpos, prevChord, prev_xpos); } if (curr is ChordSymbol) { ChordSymbol chord = (ChordSymbol)curr; if (chord.Stem != null && !chord.Stem.Receiver) { prevChord = (ChordSymbol)curr; prev_xpos = xpos; } } xpos += curr.Width; } }
/** Connect chords of the same duration with a horizontal beam. * numChords is the number of chords per beam (2, 3, 4, or 6). * if startBeat is true, the first chord must start on a quarter note beat. */ private static void CreateBeamedChords(List<MusicSymbol>[] allsymbols, TimeSignature time, int numChords, bool startBeat) { int[] chordIndexes = new int[numChords]; ChordSymbol[] chords = new ChordSymbol[numChords]; foreach (List<MusicSymbol> symbols in allsymbols) { int startIndex = 0; while (true) { int horizDistance = 0; bool found = FindConsecutiveChords(symbols, time, startIndex, chordIndexes, ref horizDistance); if (!found) { break; } for (int i = 0; i < numChords; i++) { chords[i] = (ChordSymbol)symbols[ chordIndexes[i] ]; } if (ChordSymbol.CanCreateBeam(chords, time, startBeat)) { ChordSymbol.CreateBeam(chords, horizDistance); startIndex = chordIndexes[numChords-1] + 1; } else { startIndex = chordIndexes[0] + 1; } /* What is the value of startIndex here? * If we created a beam, we start after the last chord. * If we failed to create a beam, we start after the first chord. */ } } }
public void TestStemUpBass() { SheetMusic.SetNoteSize(false); KeySignature key = new KeySignature(0, 0); int quarter = 400; TimeSignature time = new TimeSignature(4, 4, quarter, 60000); int num1 = WhiteNote.BottomBass.Number(); int num2 = num1 + 2; MidiNote note1 = new MidiNote(0, 0, num1, quarter); MidiNote note2 = new MidiNote(0, 0, num2, quarter); List<MidiNote> notes = new List<MidiNote>(2); notes.Add(note1); notes.Add(note2); ChordSymbol chord = new ChordSymbol(notes, key, time, Clef.Bass, null); Assert.AreEqual(chord.ToString(), "ChordSymbol clef=Bass start=0 end=400 width=16 hastwostems=False Note whitenote=A3 duration=Quarter leftside=True Note whitenote=B3 duration=Quarter leftside=False Stem duration=Quarter direction=1 top=B3 bottom=A3 end=A4 overlap=True side=2 width_to_pair=0 receiver_in_pair=False "); }
/** Shade all the chords played in the given time. * Un-shade any chords shaded in the previous pulse time. * Store the x coordinate location where the shade was drawn. */ public void ShadeNotes(Graphics g, SolidBrush shadeBrush, Pen pen, int currentPulseTime, int prevPulseTime, ref int x_shade) { /* If there's nothing to unshade, or shade, return */ if ((starttime > prevPulseTime || endtime < prevPulseTime) && (starttime > currentPulseTime || endtime < currentPulseTime)) { return; } /* Skip the left side Clef symbol and key signature */ int xpos = keysigWidth; MusicSymbol curr = null; ChordSymbol prevChord = null; int prev_xpos = 0; /* Loop through the symbols. * Unshade symbols where start <= prevPulseTime < end * Shade symbols where start <= currentPulseTime < end */ for (int i = 0; i < symbols.Count; i++) { curr = symbols[i]; if (curr is BarSymbol) { xpos += curr.Width; continue; } int start = curr.StartTime; int end = 0; if (i + 2 < symbols.Count && symbols[i + 1] is BarSymbol) { end = symbols[i + 2].StartTime; } else if (i + 1 < symbols.Count) { end = symbols[i + 1].StartTime; } else { end = endtime; } /* If we've past the previous and current times, we're done. */ if ((start > prevPulseTime) && (start > currentPulseTime)) { if (x_shade == 0) { x_shade = xpos; } return; } /* If shaded notes are the same, we're done */ if ((start <= currentPulseTime) && (currentPulseTime < end) && (start <= prevPulseTime) && (prevPulseTime < end)) { x_shade = xpos; return; } bool redrawLines = false; /* If symbol is in the previous time, draw a white background */ if ((start <= prevPulseTime) && (prevPulseTime < end)) { g.TranslateTransform(xpos - 2, -2); g.FillRectangle(Brushes.White, 0, 0, curr.Width + 4, this.Height + 4); g.TranslateTransform(-(xpos - 2), 2); g.TranslateTransform(xpos, 0); curr.Draw(g, pen, ytop); g.TranslateTransform(-xpos, 0); redrawLines = true; } /* If symbol is in the current time, draw a shaded background */ if ((start <= currentPulseTime) && (currentPulseTime < end)) { x_shade = xpos; g.TranslateTransform(xpos, 0); g.FillRectangle(shadeBrush, 0, 0, curr.Width, this.Height); curr.Draw(g, pen, ytop); g.TranslateTransform(-xpos, 0); redrawLines = true; } /* If either a gray or white background was drawn, we need to redraw * the horizontal staff lines, and redraw the stem of the previous chord. */ if (redrawLines) { int line = 1; int y = ytop - SheetMusic.LineWidth; pen.Width = 1; g.TranslateTransform(xpos - 2, 0); for (line = 1; line <= 5; line++) { g.DrawLine(pen, 0, y, curr.Width + 4, y); y += SheetMusic.LineWidth + SheetMusic.LineSpace; } g.TranslateTransform(-(xpos - 2), 0); if (prevChord != null) { g.TranslateTransform(prev_xpos, 0); prevChord.Draw(g, pen, ytop); g.TranslateTransform(-prev_xpos, 0); } if (showMeasures) { DrawMeasureNumbers(g, pen); } if (lyrics != null) { DrawLyrics(g, pen); } } if (curr is ChordSymbol) { ChordSymbol chord = (ChordSymbol)curr; if (chord.Stem != null && !chord.Stem.Receiver) { prevChord = (ChordSymbol)curr; prev_xpos = xpos; } } xpos += curr.Width; } }
public void TestWholeDuration() { SheetMusic.SetNoteSize(false); KeySignature key = new KeySignature(0, 0); int quarter = 400; TimeSignature time = new TimeSignature(4, 4, quarter, 60000); int num1 = WhiteNote.BottomTreble.Number(); MidiNote note1 = new MidiNote(0, 0, num1, quarter*4); List<MidiNote> notes = new List<MidiNote>(2); notes.Add(note1); ChordSymbol chord = new ChordSymbol(notes, key, time, Clef.Treble, null); Assert.AreEqual(chord.ToString(), "ChordSymbol clef=Treble start=0 end=1600 width=16 hastwostems=False Note whitenote=F4 duration=Whole leftside=True "); }
/** Create the chord symbols for a single track. * @param midinotes The Midinotes in the track. * @param key The Key Signature, for determining sharps/flats. * @param time The Time Signature, for determining the measures. * @param clefs The clefs to use for each measure. * @ret An array of ChordSymbols */ private List<ChordSymbol> CreateChords(List<MidiNote> midinotes, KeySignature key, TimeSignature time, ClefMeasures clefs) { int i = 0; List<ChordSymbol> chords = new List<ChordSymbol>(); List<MidiNote> notegroup = new List<MidiNote>(12); int len = midinotes.Count; while (i < len) { int starttime = midinotes[i].StartTime; Clef clef = clefs.GetClef(starttime); /* Group all the midi notes with the same start time * into the notes list. */ notegroup.Clear(); notegroup.Add(midinotes[i]); i++; while (i < len && midinotes[i].StartTime == starttime) { notegroup.Add(midinotes[i]); i++; } /* Create a single chord from the group of midi notes with * the same start time. */ ChordSymbol chord = new ChordSymbol(notegroup, key, time, clef, this); chords.Add(chord); } return chords; }
public void OnClick(Graphics g, SolidBrush shadeBrush, Pen pen, float x) { /* Skip the left side Clef symbol and key signature */ int xpos = keysigWidth; MusicSymbol curr = null; ChordSymbol prevChord = null; int prev_xpos = 0; for (int i = 0; i < symbols.Count; i++) { curr = symbols[i]; int start = curr.StartTime; int end = 0; if (i + 2 < symbols.Count && symbols[i + 1] is BarSymbol) { end = symbols[i + 2].StartTime; } else if (i + 1 < symbols.Count) { end = symbols[i + 1].StartTime; } else { end = endtime; } /* If we've past, we're done. */ if (x < xpos) { return; } bool redrawLines = false; /* If symbol is in the current time, draw a shaded background */ if (xpos <= x && x < xpos + curr.Width) { if (curr is RestSymbol) { Insert(g, shadeBrush, pen, i, xpos); redrawLines = true; } } /* If either a gray or white background was drawn, we need to redraw * the horizontal staff lines, and redraw the stem of the previous chord. */ if (redrawLines) { ReDrawLines(g, pen, curr, xpos, prevChord, prev_xpos); } if (curr is ChordSymbol) { ChordSymbol chord = (ChordSymbol)curr; if (chord.Stem != null && !chord.Stem.Receiver) { prevChord = (ChordSymbol)curr; prev_xpos = xpos; } } xpos += curr.Width; } }