Example #1
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();
        }
Example #2
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);
        }
Example #3
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);
        }
Example #4
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);
        }
Example #5
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);
        }
Example #6
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;
        }