Пример #1
0
        /// <summary>
        /// Adds a barline to the current measure if needed, and breaks the last note of the measure if it
        /// exceeds the allowed beats/measure, inserting the remainder into the next measure. Then recursively calls
        /// itself on subsequent measures until it hits a measure that does not overflow.
        /// </summary>
        /// <param name="m"></param>
        /// <param name="ts"></param>
        internal void fitMeasure(Measure m, TimeSignature ts) // Still need to add support for deletion
        {
            bool  nextMeasureChanged = false;
            Staff staff        = m.Staff;
            int   measureIndex = staff.Measures.IndexOf(m);


            foreach (MusicalSymbol item in m.Elements)
            {
                // If new time signature, update
                if (item.GetType() == typeof(TimeSignature))
                {
                    ts = (TimeSignature)item;
                }

                // Make sure that any cleffs and signatures are at the beginning of the measure, before notes and rests
                if (item.GetType() == typeof(TimeSignature) || item.GetType() == typeof(Key) || item.GetType() == typeof(Clef))
                {
                    NoteOrRest firstBeat = getFirstBeat(m);
                    if (m.Elements.IndexOf(firstBeat) < m.Elements.IndexOf(item))
                    {
                        swapPositions(staff, item, firstBeat);
                    }
                }
            }

            // While the current measure is not full and is not the end of the song, steal the first beat from the next measure
            // ****VERIFY THIS CODE ONCE NOTE DELETION IS IN PLACE****
            while (getDurations(m).Sum() < ts.WholeNoteCapacity &&
                   m.Number < staff.Measures.Count &&
                   getFirstBeat(getNextMeasure(m)) != null)
            {
                Measure    next = getNextMeasure(m);
                NoteOrRest nr   = getFirstBeat(next);
                next.Elements.Remove(nr);
                m.Elements.Add(nr);     // This note might be longer than we have room for, but the next loop will take care of it
                nextMeasureChanged = true;
            }

            // While the current measure has too many beats, push the extra into the next measure
            while (getDurations(m).Sum() > ts.WholeNoteCapacity)
            {
                double     overage           = getOverage(m, ts);                                                              // How much the content of the current measure exceeds its alloted time
                NoteOrRest lastNoteOrRest    = (NoteOrRest)m.Elements.Last(e => e.GetType().IsSubclassOf(typeof(NoteOrRest))); // Last note or rest in measure
                double     lastDurationValue = lastNoteOrRest.Duration.ToDouble();                                             // Value of last note or rest in measure
                int        lastItemIndex     = staff.Elements.IndexOf(lastNoteOrRest);                                         // Index of last note or rest in the measure
                NoteOrRest itemToMove        = null;                                                                           // The last note or portion thereof that doesn't fit in the current measure

                // If the overage is because the last note is too big, break it into two notes
                if (lastDurationValue > overage)
                {
                    NoteOrRest itemInPlace;     // Shortened version of lastNoteOrRest that fits in currrent measure
                    if (lastNoteOrRest.GetType() == typeof(Note))
                    {
                        itemInPlace = new Note(((Note)lastNoteOrRest).Pitch, toRhythmicDuration(lastDurationValue - overage));
                        itemToMove  = new Note(((Note)lastNoteOrRest).Pitch, toRhythmicDuration(overage)); // Remaining note value
                    }
                    else
                    {
                        itemInPlace = new Rest(toRhythmicDuration(lastDurationValue - overage));
                        itemToMove  = new Rest(toRhythmicDuration(overage));
                    }
                    // Have to remove lastNoteOrRest from both the staff and the measure
                    staff.Elements.Remove(lastNoteOrRest);
                    m.Elements.Remove(lastNoteOrRest);
                    // Replace with shortened version, automatically populates to measure when adding
                    staff.Elements.Insert(lastItemIndex, itemInPlace);
                }
                else
                {
                    itemToMove = lastNoteOrRest;
                    staff.Elements.Remove(lastNoteOrRest);
                    m.Elements.Remove(lastNoteOrRest);
                    lastItemIndex--;
                }

                // Refresh the updated measure in the staff.measures collection
                Barline bar = moveOrAddBarlineAfter(staff.Elements[lastItemIndex]);

                // Add itemToMove after the barline
                staff.Elements.Insert(lastItemIndex + 2, itemToMove);

                // Add it to the measure as well if it's not already there
                Measure nextMeasure = getNextMeasure(m);
                if (!nextMeasure.Elements.Contains(itemToMove))
                {
                    nextMeasure.Elements.Insert(0, itemToMove);
                }

                // set the flag to check the next measure
                nextMeasureChanged = true;
            }

            // If there are changes to the next measure, fix it.
            if (nextMeasureChanged)
            {
                fitMeasure(getNextMeasure(m), ts);
            }
        }
Пример #2
0
        ////// IN PROGRESS ////////
        /// <summary>
        /// Adds a barline to the current measure if needed, and breaks the last note of the measure if it
        /// exceeds the allowed beats/measure, inserting the remainder into the next measure, then recursively calls
        /// itself on subsequent measures until it hits a measure that does not overflow.
        /// </summary>
        /// <param name="m"></param>
        /// <param name="ts"></param>
        internal void fitMeasure(Measure m, TimeSignature ts) // Still need to add support for deletion
        {
            bool nextMeasureChanged = false;

            foreach (MusicalSymbol item in m.Elements)
            {
                // If new time signature, update
                if (item.GetType() == typeof(TimeSignature))
                {
                    ts = (TimeSignature)item;
                }

                // Make sure that any cleffs and signatures are at the beginning of the measure, before notes and rests
                if (item.GetType() == typeof(TimeSignature) || item.GetType() == typeof(Key) || item.GetType() == typeof(Clef))
                {
                    NoteOrRest firstBeat = getFirstBeat(m);
                    if (m.Elements.IndexOf(firstBeat) < m.Elements.IndexOf(item))
                    {
                        swapPositions(m.Staff, item, firstBeat);
                    }
                }
            }

            // While the current measure is not full and is not the end of the song, steal the first beat from the next measure
            while (getDurations(m).Sum() < ts.WholeNoteCapacity &&
                   m.Number < m.Staff.Measures.Count &&
                   getFirstBeat(getNextMeasure(m)) != null)
            {
                Measure    next = getNextMeasure(m);
                NoteOrRest nr   = getFirstBeat(next);
                next.Elements.Remove(nr);
                m.Elements.Add(nr);     // This note might be longer than we have room for, but the next loop will take care of it
                nextMeasureChanged = true;
            }

            Staff staff        = m.Staff;
            int   measureIndex = staff.Measures.IndexOf(m);

            // While the current measure has too many beats, push the extra into the next measure
            while (getDurations(m).Sum() > ts.WholeNoteCapacity)
            {
                //double[] d = getDurations(m);
                double     overage           = getOverage(m, ts);// d.Sum() - ts.WholeNoteCapacity;
                NoteOrRest lastNoteOrRest    = (NoteOrRest)m.Elements.Last(e => e.GetType().IsSubclassOf(typeof(NoteOrRest)));
                double     lastDurationValue = lastNoteOrRest.Duration.ToDouble();
                int        lastItemIndex     = staff.Elements.IndexOf(lastNoteOrRest);
                NoteOrRest itemToMove        = null;

                // If the overage is because the last note is too big, break it into two notes
                if (lastDurationValue > overage)
                {
                    // Shorten the duration of the culprit to fit the measure
                    //lastNoteOrRest.Duration = toRhythmicDuration(lastDurationValue - overage);

                    // Instead of shortening in place, try replacing so the viewer notices the change
                    NoteOrRest itemInPlace;

                    // Propagate the change to the staff -- Never mind. It propagates fine here.
                    //m.Staff.Elements[m.Staff.Elements.IndexOf(lastNoteOrRest)] = null;
                    //m.Staff.Elements[m.Staff.Elements.IndexOf(lastNoteOrRest)] = lastNoteOrRest;


                    // Add a copy of the culprit note or rest at the remaining duration
                    if (lastNoteOrRest.GetType() == typeof(Note))
                    {
                        itemInPlace = new Note(((Note)lastNoteOrRest).Pitch, toRhythmicDuration(lastDurationValue - overage));
                        itemToMove  = new Note(((Note)lastNoteOrRest).Pitch, toRhythmicDuration(overage));
                    }
                    else
                    {
                        itemInPlace = new Rest(toRhythmicDuration(lastDurationValue - overage));
                        itemToMove  = new Rest(toRhythmicDuration(overage));
                    }
                    m.Staff.Elements.Remove(lastNoteOrRest);
                    m.Elements.Remove(lastNoteOrRest);
                    m.Staff.Elements.Insert(lastItemIndex, itemInPlace);
                }
                else
                {
                    itemToMove = lastNoteOrRest;
                    m.Staff.Elements.Remove(lastNoteOrRest);
                    m.Elements.Remove(lastNoteOrRest);
                    lastItemIndex--;
                }

                // Grab the next barline and put it after the last note of the adjusted measure
                //Barline bar = moveOrAddBarlineAfter(staff.Elements[lastItemIndex -1 ]);   // This is adding it to the staff elements, which have not been refreshed

                // Refresh the updated measure in the staff.measures collection

                if (m.Elements[m.Elements.Count - 1].GetType() != typeof(Barline))
                {
                    m.Staff.Elements.Insert(lastItemIndex + 1, new Barline());                                                                // may have to use "add"
                }
                //*** May need to remove m from staff.measures and insert updated version***

                // Add the new note/rest or new partial note/rest to the new measure
                // getNextMeasure(m).Elements.Insert(0, itemToMove);
                m.Staff.Elements.Insert(lastItemIndex + 2, itemToMove);

                // m.Staff.Elements.Insert(lastItemIndex + 1, lastElem);
                //staff.Elements.Insert(lastItemIndex + 2, itemToMove);
                updateView();
                //getNextMeasure(m).Elements.Insert(0, itemToMove);
                nextMeasureChanged = true;

                // Refresh measures against the current staff
                //m = null;
                //m = staff.Measures.ElementAt(measureIndex);
                //nextMeasure = null;
                //nextMeasure = staff.Measures.ElementAt(measureIndex + 1);
            }

            // If there are changes to the next measure, fix it.
            if (nextMeasureChanged) //fitMeasure(staff.Measures[staff.Measures.IndexOf(m) + 1], ts);
            {
                fitMeasure(getNextMeasure(m), ts);
            }
        }