Пример #1
0
 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 ");
 }
Пример #2
0
        private int ytop; /** The y pixel of the top of the staff */

        #endregion Fields

        #region Constructors

        /** Create a new staff with the given list of music symbols,
         * and the given key signature.  The clef is determined by
         * the clef of the first chord symbol. The track number is used
         * to determine whether to join this left/right vertical sides
         * with the staffs above and below. The SheetMusicOptions are used
         * to check whether to display measure numbers or not.
         */
        public Staff(List<MusicSymbol> symbols, KeySignature key, 
                 MidiOptions options,
                 int tracknum, int totaltracks)
        {
            keysigWidth = SheetMusic.KeySignatureWidth(key);
            this.tracknum = tracknum;
            this.totaltracks = totaltracks;
            showMeasures = (options.showMeasures && tracknum == 0);
            measureLength = options.time.Measure;
            Clef clef = FindClef(symbols);

            clefsym = new ClefSymbol(clef, 0, false);
            keys = key.GetSymbols(clef);
            this.symbols = symbols;
            CalculateWidth(options.scrollVert);
            CalculateHeight();
            CalculateStartEndTime();
            FullJustify();
        }
Пример #3
0
        private int measureLength;          /** The time (in pulses) of a measure */

        /** Create a new staff with the given list of music symbols,
         * and the given key signature.  The clef is determined by
         * the clef of the first chord symbol. The track number is used
         * to determine whether to join this left/right vertical sides
         * with the staffs above and below. The SheetMusicOptions are used
         * to check whether to display measure numbers or not.
         */
        public Staff(List <MusicSymbol> symbols, KeySignature key,
                     MidiOptions options,
                     int tracknum, int totaltracks)
        {
            keysigWidth      = SheetMusic.KeySignatureWidth(key);
            this.tracknum    = tracknum;
            this.totaltracks = totaltracks;
            showMeasures     = (options.showMeasures && tracknum == 0);
            measureLength    = options.time.Measure;
            Clef clef = FindClef(symbols);

            clefsym      = new ClefSymbol(clef, 0, false);
            keys         = key.GetSymbols(clef);
            this.symbols = symbols;
            CalculateWidth(options.scrollVert);
            CalculateHeight();
            CalculateStartEndTime();
            FullJustify();
        }
Пример #4
0
        CreateNoteData(List <MidiNote> midinotes, KeySignature key,
                       TimeSignature time)
        {
            int len = midinotes.Count;

            NoteData[] notedata = new NoteData[len];

            for (int i = 0; i < len; i++)
            {
                MidiNote midi = midinotes[i];
                notedata[i]           = new NoteData();
                notedata[i].number    = midi.Number;
                notedata[i].leftside  = true;
                notedata[i].whitenote = key.GetWhiteNote(midi.Number);
                notedata[i].duration  = time.GetNoteDuration(midi.EndTime - midi.StartTime);
                notedata[i].accid     = key.GetAccidental(midi.Number, midi.StartTime / time.Measure);

                if (i > 0 && (notedata[i].whitenote.Dist(notedata[i - 1].whitenote) == 1))
                {
                    /* This note (notedata[i]) overlaps with the previous note.
                     * Change the side of this note.
                     */

                    if (notedata[i - 1].leftside)
                    {
                        notedata[i].leftside = false;
                    }
                    else
                    {
                        notedata[i].leftside = true;
                    }
                }
                else
                {
                    notedata[i].leftside = true;
                }
            }
            return(notedata);
        }
Пример #5
0
        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);
        }
Пример #6
0
        /** Given the raw midi notes (the note number and duration in pulses),
         * calculate the following note data:
         * - The white key
         * - The accidental (if any)
         * - The note duration (half, quarter, eighth, etc)
         * - The side it should be drawn (left or side)
         * By default, notes are drawn on the left side.  However, if two notes
         * overlap (like A and B) you cannot draw the next note directly above it.
         * Instead you must shift one of the notes to the right.
         *
         * The KeySignature is used to determine the white key and accidental.
         * The TimeSignature is used to determine the duration.
         */
        private static NoteData[] CreateNoteData(List<MidiNote> midinotes, KeySignature key,
            TimeSignature time)
        {
            int len = midinotes.Count;
            NoteData[] notedata = new NoteData[len];

            for (int i = 0; i < len; i++) {
            MidiNote midi = midinotes[i];
            notedata[i] = new NoteData();
            notedata[i].number = midi.Number;
            notedata[i].leftside = true;
            notedata[i].whitenote = key.GetWhiteNote(midi.Number);
            notedata[i].duration = time.GetNoteDuration(midi.EndTime - midi.StartTime);
            notedata[i].accid = key.GetAccidental(midi.Number, midi.StartTime / time.Measure);

            if (i > 0 && (notedata[i].whitenote.Dist(notedata[i-1].whitenote) == 1)) {
                /* This note (notedata[i]) overlaps with the previous note.
                 * Change the side of this note.
                 */

                if (notedata[i-1].leftside) {
                    notedata[i].leftside = false;
                } else {
                    notedata[i].leftside = true;
                }
            } else {
                notedata[i].leftside = true;
            }
            }
            return notedata;
        }
Пример #7
0
        private int width; /** The width of the chord */

        #endregion Fields

        #region Constructors

        /** 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;

            for (i = 0; i < midinotes.Count; i++) {
            if (i > 1) {
                if (midinotes[i].Number < midinotes[i-1].Number) {
                    throw new System.ArgumentException("Chord notes not in increasing order by number");
                }
            }
            endtime = Math.Max(endtime, midinotes[i].EndTime);
            }

            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;
        }
Пример #8
0
        CreateStaffsForTrack(List <MusicSymbol> symbols, int measurelen,
                             KeySignature key, MidiOptions options,
                             int track, int totaltracks)
        {
            int          keysigWidth = KeySignatureWidth(key);
            int          startindex  = 0;
            List <Staff> thestaffs   = new List <Staff>(symbols.Count / 50);

            while (startindex < symbols.Count)
            {
                /* startindex is the index of the first symbol in the staff.
                 * endindex is the index of the last symbol in the staff.
                 */
                int endindex = startindex;
                int width    = keysigWidth;
                int maxwidth;

                /* If we're scrolling vertically, the maximum width is PageWidth. */
                if (scrollVert)
                {
                    maxwidth = SheetMusic.PageWidth;
                }
                else
                {
                    maxwidth = 2000000;
                }

                while (endindex < symbols.Count &&
                       width + symbols[endindex].Width < maxwidth)
                {
                    width += symbols[endindex].Width;
                    endindex++;
                }
                endindex--;

                /* There's 3 possibilities at this point:
                 * 1. We have all the symbols in the track.
                 *    The endindex stays the same.
                 *
                 * 2. We have symbols for less than one measure.
                 *    The endindex stays the same.
                 *
                 * 3. We have symbols for 1 or more measures.
                 *    Since measures cannot span multiple staffs, we must
                 *    make sure endindex does not occur in the middle of a
                 *    measure.  We count backwards until we come to the end
                 *    of a measure.
                 */

                if (endindex == symbols.Count - 1)
                {
                    /* endindex stays the same */
                }
                else if (symbols[startindex].StartTime / measurelen ==
                         symbols[endindex].StartTime / measurelen)
                {
                    /* endindex stays the same */
                }
                else
                {
                    int endmeasure = symbols[endindex + 1].StartTime / measurelen;
                    while (symbols[endindex].StartTime / measurelen ==
                           endmeasure)
                    {
                        endindex--;
                    }
                }
                int range = endindex + 1 - startindex;
                if (scrollVert)
                {
                    width = SheetMusic.PageWidth;
                }
                Staff staff = new Staff(symbols.GetRange(startindex, range),
                                        key, options, track, totaltracks);
                thestaffs.Add(staff);
                startindex = endindex + 1;
            }
            return(thestaffs);
        }
Пример #9
0
        /** 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;
        }
Пример #10
0
 /** Return true if this key signature is equal to key signature k */
 public bool Equals(KeySignature k)
 {
     if (k.num_sharps == num_sharps && k.num_flats == num_flats)
     return true;
     else
     return false;
 }
Пример #11
0
        private SheetMusic sheetmusic;      /** Used to get colors and other options */


        /** 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;

            for (i = 0; i < midinotes.Count; i++)
            {
                if (i > 1)
                {
                    if (midinotes[i].Number < midinotes[i - 1].Number)
                    {
                        throw new System.ArgumentException("Chord notes not in increasing order by number");
                    }
                }
                endtime = Math.Max(endtime, midinotes[i].EndTime);
            }

            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;
        }
Пример #12
0
 /** Get the width (in pixels) needed to display the key signature */
 public static int KeySignatureWidth(KeySignature key)
 {
     ClefSymbol clefsym = new ClefSymbol(Clef.Treble, 0, false);
     int result = clefsym.MinWidth;
     AccidSymbol[] keys = key.GetSymbols(Clef.Treble);
     foreach (AccidSymbol symbol in keys) {
     result += symbol.MinWidth;
     }
     return result + SheetMusic.LeftMargin + 5;
 }
Пример #13
0
    public void TestGetAccidentalSameMeasure()
    {
        KeySignature k;

        /* G Major, F# */
        k = new KeySignature(1, 0);

        int note = NoteScale.ToNumber(NoteScale.C, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.C);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.C);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Fsharp, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.F, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Natural);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Fsharp, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Sharp);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Bflat, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Flat);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.A, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.A);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.B, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Natural);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Bflat, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Flat);

        /* F Major, Bflat */
        k = new KeySignature(0, 1);

        note = NoteScale.ToNumber(NoteScale.G, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.G);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.G);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Bflat, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.B, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Natural);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Bflat, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Flat);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.B);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Fsharp, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Sharp);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.G, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.G);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.F, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Natural);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.None);

        note = NoteScale.ToNumber(NoteScale.Fsharp, 1);
        Assert.AreEqual(k.GetWhiteNote(note).Letter, WhiteNote.F);
        Assert.AreEqual(k.GetAccidental(note, 1), Accid.Sharp);
    }
Пример #14
0
    public void TestGetAccidental()
    {
        int measure = 1;
        KeySignature k;
        Accid[] expected = new Accid[12];
        for (int i = 0; i < 12; i++) {
            expected[i] = Accid.None;
        }
        expected[NoteScale.Bflat]  = Accid.Flat;
        expected[NoteScale.Csharp] = Accid.Sharp;
        expected[NoteScale.Dsharp] = Accid.Sharp;
        expected[NoteScale.Fsharp] = Accid.Sharp;
        expected[NoteScale.Gsharp] = Accid.Sharp;

        /* Test C Major */
        k = new KeySignature(0, 0);
        measure = 1;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test G major, F# */
        k = new KeySignature(1, 0);
        measure = 1;
        expected[NoteScale.Fsharp] = Accid.None;
        expected[NoteScale.F] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test D major, F#, C# */
        k = new KeySignature(2, 0);
        measure = 1;
        expected[NoteScale.Csharp] = Accid.None;
        expected[NoteScale.C] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test A major, F#, C#, G# */
        k = new KeySignature(3, 0);
        measure = 1;
        expected[NoteScale.Gsharp] = Accid.None;
        expected[NoteScale.G] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test E major, F#, C#, G#, D# */
        k = new KeySignature(4, 0);
        measure = 1;
        expected[NoteScale.Dsharp] = Accid.None;
        expected[NoteScale.D] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test B major, F#, C#, G#, D#, A# */
        k = new KeySignature(5, 0);
        measure = 1;
        expected[NoteScale.Asharp] = Accid.None;
        expected[NoteScale.A] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        for (int i = 0; i < 12; i++) {
            expected[i] = Accid.None;
        }
        expected[NoteScale.Aflat]  = Accid.Flat;
        expected[NoteScale.Bflat]  = Accid.Flat;
        expected[NoteScale.Csharp] = Accid.Sharp;
        expected[NoteScale.Eflat]  = Accid.Flat;
        expected[NoteScale.Fsharp] = Accid.Sharp;

        /* Test F major, Bflat */
        k = new KeySignature(0, 1);
        measure = 1;
        expected[NoteScale.Bflat] = Accid.None;
        expected[NoteScale.B] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test Bflat major, Bflat, Eflat */
        k = new KeySignature(0, 2);
        measure = 1;
        expected[NoteScale.Eflat] = Accid.None;
        expected[NoteScale.E] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test Eflat major, Bflat, Eflat, Afat */
        k = new KeySignature(0, 3);
        measure = 1;
        expected[NoteScale.Aflat] = Accid.None;
        expected[NoteScale.A] = Accid.Natural;
        expected[NoteScale.Dflat] = Accid.Flat;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test Aflat major, Bflat, Eflat, Aflat, Dflat */
        k = new KeySignature(0, 4);
        measure = 1;
        expected[NoteScale.Dflat] = Accid.None;
        expected[NoteScale.D] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }

        /* Test Dflat major, Bflat, Eflat, Aflat, Dflat, Gflat */
        k = new KeySignature(0, 5);
        measure = 1;
        expected[NoteScale.Gflat] = Accid.None;
        expected[NoteScale.G] = Accid.Natural;
        for (int note = 1; note < 128; note++) {
            int notescale = NoteScale.FromNumber(note);
            Assert.AreEqual(expected[notescale],
                          k.GetAccidental(note, measure));
            measure++;
        }
    }
Пример #15
0
 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 ");
 }
Пример #16
0
 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 ");
 }
Пример #17
0
 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);
 }
Пример #18
0
        /** Given MusicSymbols for a track, create the staffs for that track.
         *  Each Staff has a maxmimum width of PageWidth (800 pixels).
         *  Also, measures should not span multiple Staffs.
         */
        private List<Staff> CreateStaffsForTrack(List<MusicSymbol> symbols, int measurelen, 
            KeySignature key, MidiOptions options,
            int track, int totaltracks)
        {
            int keysigWidth = KeySignatureWidth(key);
            int startindex = 0;
            List<Staff> thestaffs = new List<Staff>(symbols.Count / 50);

            while (startindex < symbols.Count) {
            /* startindex is the index of the first symbol in the staff.
             * endindex is the index of the last symbol in the staff.
             */
            int endindex = startindex;
            int width = keysigWidth;
            int maxwidth;

            /* If we're scrolling vertically, the maximum width is PageWidth. */
            if (scrollVert) {
                maxwidth = SheetMusic.PageWidth;
            }
            else {
                maxwidth = 2000000;
            }

            while (endindex < symbols.Count &&
                   width + symbols[endindex].Width < maxwidth) {

                width += symbols[endindex].Width;
                endindex++;
            }
            endindex--;

            /* There's 3 possibilities at this point:
             * 1. We have all the symbols in the track.
             *    The endindex stays the same.
             *
             * 2. We have symbols for less than one measure.
             *    The endindex stays the same.
             *
             * 3. We have symbols for 1 or more measures.
             *    Since measures cannot span multiple staffs, we must
             *    make sure endindex does not occur in the middle of a
             *    measure.  We count backwards until we come to the end
             *    of a measure.
             */

            if (endindex == symbols.Count - 1) {
                /* endindex stays the same */
            }
            else if (symbols[startindex].StartTime / measurelen ==
                     symbols[endindex].StartTime / measurelen) {
                /* endindex stays the same */
            }
            else {
                int endmeasure = symbols[endindex+1].StartTime/measurelen;
                while (symbols[endindex].StartTime / measurelen ==
                       endmeasure) {
                    endindex--;
                }
            }
            int range = endindex + 1 - startindex;
            if (scrollVert) {
                width = SheetMusic.PageWidth;
            }
            Staff staff = new Staff(symbols.GetRange(startindex, range),
                                    key, options, track, totaltracks);
            thestaffs.Add(staff);
            startindex = endindex + 1;
            }
            return thestaffs;
        }
Пример #19
0
    public void TestGetSymbols()
    {
        KeySignature k;
        AccidSymbol[] symbols1, symbols2;

        k = new KeySignature(0, 0);
        symbols1 = k.GetSymbols(Clef.Treble);
        symbols2 = k.GetSymbols(Clef.Bass);
        Assert.AreEqual(symbols1.Length, 0);
        Assert.AreEqual(symbols2.Length, 0);

        int[] sharps = new int[] {
            WhiteNote.F, WhiteNote.C, WhiteNote.G, WhiteNote.D,
            WhiteNote.A, WhiteNote.E
        };

        for (int sharp = 1; sharp < 7; sharp++) {
            k = new KeySignature(sharp, 0);
            symbols1 = k.GetSymbols(Clef.Treble);
            symbols2 = k.GetSymbols(Clef.Bass);
            for (int i = 0; i < sharp; i++) {
                Assert.AreEqual(symbols1[i].Note.Letter, sharps[i]);
                Assert.AreEqual(symbols2[i].Note.Letter, sharps[i]);
            }
        }

        int[] flats = new int[] {
            WhiteNote.B, WhiteNote.E, WhiteNote.A, WhiteNote.D,
            WhiteNote.G
        };

        for (int flat = 1; flat < 6; flat++) {
            k = new KeySignature(0, flat);
            symbols1 = k.GetSymbols(Clef.Treble);
            symbols2 = k.GetSymbols(Clef.Bass);
            for (int i = 0; i < flat; i++) {
                Assert.AreEqual(symbols1[i].Note.Letter, flats[i]);
                Assert.AreEqual(symbols2[i].Note.Letter, flats[i]);
            }
        }
    }
Пример #20
0
        /** Create a new SheetMusic control, using the given midi filename.
         *  The options can be null.
         */
        //public SheetMusic(string filename, MidiOptions options) {
        // MidiFile file = new MidiFile(filename);
        // init(file, options);
        //}
        /** Create a new SheetMusic control, using the given raw midi byte[] data.
         *  The options can be null.
         */
        //public SheetMusic(byte[] data, string title, MidiOptions options) {
        //    MidiFile file = new MidiFile(data, title);
        //     init(file, options);
        // }
        /** 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 Load(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();
            }

            braces = CreateBraceSymbols(staffs);

            BackColor = Color.White;

            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // ��ֹ��������.
            SetStyle(ControlStyles.DoubleBuffer, true);
        }
Пример #21
0
        /** 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);
        }
Пример #22
0
        /** Given all the MusicSymbols for every track, create the staffs
         * for the sheet music.  There are two parts to this:
         *
         * - Get the list of staffs for each track.
         *   The staffs will be stored in trackstaffs as:
         *
         *   trackstaffs[0] = { Staff0, Staff1, Staff2, ... } for track 0
         *   trackstaffs[1] = { Staff0, Staff1, Staff2, ... } for track 1
         *   trackstaffs[2] = { Staff0, Staff1, Staff2, ... } for track 2
         *
         * - Store the Staffs in the staffs list, but interleave the
         *   tracks as follows:
         *
         *   staffs = { Staff0 for track 0, Staff0 for track1, Staff0 for track2,
         *              Staff1 for track 0, Staff1 for track1, Staff1 for track2,
         *              Staff2 for track 0, Staff2 for track1, Staff2 for track2,
         *              ... }
         */
        private List<Staff> CreateStaffs(List<MusicSymbol>[] allsymbols, KeySignature key, 
            MidiOptions options, int measurelen)
        {
            List<Staff>[] trackstaffs = new List<Staff>[ allsymbols.Length ];
            int totaltracks = trackstaffs.Length;

            for (int track = 0; track < totaltracks; track++) {
            List<MusicSymbol> symbols = allsymbols[ track ];
            trackstaffs[track] = CreateStaffsForTrack(symbols, measurelen, key, options, track, totaltracks);
            }

            /* Update the EndTime of each Staff. EndTime is used for playback */
            foreach (List<Staff> list in trackstaffs) {
            for (int i = 0; i < list.Count-1; i++) {
                list[i].EndTime = list[i+1].StartTime;
            }
            }

            /* Interleave the staffs of each track into the result array. */
            int maxstaffs = 0;
            for (int i = 0; i < trackstaffs.Length; i++) {
            if (maxstaffs < trackstaffs[i].Count) {
                maxstaffs = trackstaffs[i].Count;
            }
            }
            List<Staff> result = new List<Staff>(maxstaffs * trackstaffs.Length);
            for (int i = 0; i < maxstaffs; i++) {
            foreach (List<Staff> list in trackstaffs) {
                if (i < list.Count) {
                    result.Add(list[i]);
                }
            }
            }
            return result;
        }
Пример #23
0
        /** Create the "Key Signature" sub-menu.
         * Create the sub-menus for changing the key signature.
         * The Menu.Tag contains the number of sharps (if positive)
         * or the number of flats (if negative) in the key.
         */
        void CreateKeySignatureMenu()
        {
            MenuItem menu;
            KeySignature key;

            changeKeyMenu = new MenuItem("&Key Signature");

            /* Add the default key signature */
            menu = new MenuItem("Default", new EventHandler(ChangeKeySignature));
            menu.Checked = true;
            menu.RadioCheck = true;
            menu.Tag = 0;
            changeKeyMenu.MenuItems.Add(menu);

            /* Add the sharp key signatures */
            for (int sharps = 0; sharps <=5; sharps++) {
            key = new KeySignature (sharps, 0);
            menu = new MenuItem(key.ToString(), new EventHandler(ChangeKeySignature));
            menu.Checked = false;
            menu.RadioCheck = true;
            menu.Tag = sharps;
            changeKeyMenu.MenuItems.Add(menu);
            }

            /* Add the flat key signatures */
            for (int flats = 1; flats <=6; flats++) {
            key = new KeySignature (0, flats);
            menu = new MenuItem(key.ToString(), new EventHandler(ChangeKeySignature));
            menu.Checked = false;
            menu.RadioCheck = true;
            menu.Tag = -flats;
            changeKeyMenu.MenuItems.Add(menu);
            }
            notesMenu.MenuItems.Add(changeKeyMenu);
        }