private int width_to_pair; /** The width (in pixels) to the chord pair */ #endregion Fields #region Constructors /** Create a new stem. The top note, bottom note, and direction are * needed for drawing the vertical line of the stem. The duration is * needed to draw the tail of the stem. The overlap boolean is true * if the notes in the chord overlap. If the notes overlap, the * stem must be drawn on the right side. */ public Stem(WhiteNote bottom, WhiteNote top, NoteDuration duration, int direction, bool overlap) { this.top = top; this.bottom = bottom; this.duration = duration; this.direction = direction; this.notesoverlap = overlap; if (direction == Up || notesoverlap) side = RightSide; else side = LeftSide; end = CalculateEnd(); pair = null; width_to_pair = 0; receiver_in_pair = false; }
/** Return the time period (in pulses) the the given duration spans */ public int DurationToTime(NoteDuration dur) { int eighth = quarternote/2; int sixteenth = eighth/2; switch (dur) { case NoteDuration.Whole: return quarternote * 4; case NoteDuration.DottedHalf: return quarternote * 3; case NoteDuration.Half: return quarternote * 2; case NoteDuration.DottedQuarter: return 3*eighth; case NoteDuration.Quarter: return quarternote; case NoteDuration.DottedEighth: return 3*sixteenth; case NoteDuration.Eighth: return eighth; case NoteDuration.Triplet: return quarternote/3; case NoteDuration.Sixteenth: return sixteenth; case NoteDuration.ThirtySecond: return sixteenth/2; default: return 0; } }
/** Convert a note duration into a stem duration. Dotted durations * are converted into their non-dotted equivalents. */ public static NoteDuration GetStemDuration(NoteDuration dur) { if (dur == NoteDuration.DottedHalf) return NoteDuration.Half; else if (dur == NoteDuration.DottedQuarter) return NoteDuration.Quarter; else if (dur == NoteDuration.DottedEighth) return NoteDuration.Eighth; else return dur; }
public Note(float frequency, NoteDuration duration) { Frequency = frequency; Duration = duration; }
/** 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); }
/** Create a new Chord Symbol from the given list of midi notes. * All the midi notes will have the same start time. Use the * key signature to get the white key and accidental symbol for * each note. Use the time signature to calculate the duration * of the notes. Use the clef when drawing the chord. */ public ChordSymbol(List <MidiNote> midinotes, KeySignature key, TimeSignature time, Clef c, SheetMusic sheet) { int len = midinotes.Count; int i; hastwostems = false; clef = c; sheetmusic = sheet; starttime = midinotes[0].StartTime; endtime = midinotes[0].EndTime; // Midi Notes of the chord notes = new List <MidiNote>(); for (i = 0; i < midinotes.Count; i++) { if (i > 1) { if (midinotes[i].Number < midinotes[i - 1].Number) { // FAB a corriger //throw new System.ArgumentException("Chord notes not in increasing order by number"); } } endtime = Math.Max(endtime, midinotes[i].EndTime); notes.Add(midinotes[i]); } // Note data of the chord notedata = CreateNoteData(midinotes, key, time); accidsymbols = CreateAccidSymbols(notedata, clef); /* Find out how many stems we need (1 or 2) */ NoteDuration dur1 = notedata[0].duration; NoteDuration dur2 = dur1; int change = -1; for (i = 0; i < notedata.Length; i++) { dur2 = notedata[i].duration; if (dur1 != dur2) { change = i; break; } } if (dur1 != dur2) { /* We have notes with different durations. So we will need * two stems. The first stem points down, and contains the * bottom note up to the note with the different duration. * * The second stem points up, and contains the note with the * different duration up to the top note. */ hastwostems = true; stem1 = new Stem(notedata[0].whitenote, notedata[change - 1].whitenote, dur1, Stem.Down, NotesOverlap(notedata, 0, change) ); stem2 = new Stem(notedata[change].whitenote, notedata[notedata.Length - 1].whitenote, dur2, Stem.Up, NotesOverlap(notedata, change, notedata.Length) ); } else { /* All notes have the same duration, so we only need one stem. */ int direction = StemDirection(notedata[0].whitenote, notedata[notedata.Length - 1].whitenote, clef); stem1 = new Stem(notedata[0].whitenote, notedata[notedata.Length - 1].whitenote, dur1, direction, NotesOverlap(notedata, 0, notedata.Length) ); stem2 = null; } /* For whole notes, no stem is drawn. */ if (dur1 == NoteDuration.Whole) { stem1 = null; } if (dur2 == NoteDuration.Whole) { stem2 = null; } width = MinWidth; // Lync MidiNotes & NotesData foreach (NoteData note in notedata) { for (i = 0; i < notes.Count; i++) { if (notes[i].Number == note.number) { note.midinoteindex = i; break; } } } }
private int width; /** The width in pixels */ #endregion Fields #region Constructors /** Create a new rest symbol with the given start time and duration */ public RestSymbol(int start, NoteDuration dur) { starttime = start; duration = dur; width = MinWidth; }
private int width; /** The width in pixels */ /** Create a new rest symbol with the given start time and duration */ public RestSymbol(int start, NoteDuration dur) { starttime = start; duration = dur; width = MinWidth; }