예제 #1
0
 /// <summary>
 /// Checks whether the current beat is timewise before the given beat.
 /// </summary>
 /// <param name="beat"></param>
 /// <returns></returns>
 internal bool IsBefore(Beat beat)
 {
     return(Voice.Bar.Index < beat.Voice.Bar.Index ||
            beat.Voice.Bar.Index == Voice.Bar.Index && Index < beat.Index);
 }
예제 #2
0
 /// <summary>
 /// Checks whether the current beat is timewise after the given beat.
 /// </summary>
 /// <param name="beat"></param>
 /// <returns></returns>
 internal bool IsAfter(Beat beat)
 {
     return(Voice.Bar.Index > beat.Voice.Bar.Index ||
            beat.Voice.Bar.Index == Voice.Bar.Index && Index > beat.Index);
 }
예제 #3
0
        internal void Finish()
        {
            var needCopyBeatForBend = false;

            MinNote       = null;
            MaxNote       = null;
            MinStringNote = null;
            MaxStringNote = null;

            var visibleNotes     = 0;
            var isEffectSlurBeat = false;

            for (int i = 0, j = Notes.Count; i < j; i++)
            {
                var note = Notes[i];
                note.Finish();
                if (note.IsLetRing)
                {
                    IsLetRing = true;
                }

                if (note.IsPalmMute)
                {
                    IsPalmMute = true;
                }



                if (note.IsVisible)
                {
                    visibleNotes++;
                    if (MinNote == null || note.RealValue < MinNote.RealValue)
                    {
                        MinNote = note;
                    }

                    if (MaxNote == null || note.RealValue > MaxNote.RealValue)
                    {
                        MaxNote = note;
                    }

                    if (MinStringNote == null || note.String < MinStringNote.String)
                    {
                        MinStringNote = note;
                    }

                    if (MaxStringNote == null || note.String > MaxStringNote.String)
                    {
                        MaxStringNote = note;
                    }

                    if (note.HasEffectSlur)
                    {
                        isEffectSlurBeat = true;
                    }
                }
            }

            if (isEffectSlurBeat)
            {
                if (EffectSlurOrigin != null)
                {
                    EffectSlurOrigin.EffectSlurDestination = NextBeat;
                    EffectSlurOrigin.EffectSlurDestination.EffectSlurOrigin = EffectSlurOrigin;
                    EffectSlurOrigin = null;
                }
                else
                {
                    IsEffectSlurOrigin    = true;
                    EffectSlurDestination = NextBeat;
                    EffectSlurDestination.EffectSlurOrigin = this;
                }
            }

            if (Notes.Count > 0 && visibleNotes == 0)
            {
                IsEmpty = true;
            }

            // we need to clean al letring/palmmute flags for rests
            // in case the effect is not continued on this beat
            if (!IsRest && (!IsLetRing || !IsPalmMute))
            {
                var currentBeat = PreviousBeat;
                while (currentBeat != null && currentBeat.IsRest)
                {
                    if (!IsLetRing)
                    {
                        currentBeat.IsLetRing = false;
                    }

                    if (!IsPalmMute)
                    {
                        currentBeat.IsPalmMute = false;
                    }

                    currentBeat = currentBeat.PreviousBeat;
                }
            }


            // try to detect what kind of bend was used and cleans unneeded points if required
            // Guitar Pro 6 and above (gpif.xml) uses exactly 4 points to define all whammys
            if (WhammyBarPoints.Count > 0 && WhammyBarType == WhammyType.Custom)
            {
                var isContinuedWhammy = IsContinuedWhammy = PreviousBeat != null && PreviousBeat.HasWhammyBar;
                if (WhammyBarPoints.Count == 4)
                {
                    var origin      = WhammyBarPoints[0];
                    var middle1     = WhammyBarPoints[1];
                    var middle2     = WhammyBarPoints[2];
                    var destination = WhammyBarPoints[3];

                    // the middle points are used for holds, anything else is a new feature we do not support yet
                    if (middle1.Value == middle2.Value)
                    {
                        // constant decrease or increase
                        if (origin.Value < middle1.Value && middle1.Value < destination.Value ||
                            origin.Value > middle1.Value && middle1.Value > destination.Value)
                        {
                            if (origin.Value != 0 && !isContinuedWhammy)
                            {
                                WhammyBarType = WhammyType.PrediveDive;
                            }
                            else
                            {
                                WhammyBarType = WhammyType.Dive;
                            }

                            WhammyBarPoints.RemoveAt(2);
                            WhammyBarPoints.RemoveAt(1);
                        }
                        // down-up or up-down
                        else if (origin.Value > middle1.Value && middle1.Value < destination.Value ||
                                 origin.Value < middle1.Value && middle1.Value > destination.Value)
                        {
                            WhammyBarType = WhammyType.Dip;
                        }
                        else if (origin.Value == middle1.Value && middle1.Value == destination.Value)
                        {
                            if (origin.Value != 0 && !isContinuedWhammy)
                            {
                                WhammyBarType = WhammyType.Predive;
                            }
                            else
                            {
                                WhammyBarType = WhammyType.Hold;
                            }

                            WhammyBarPoints.RemoveAt(2);
                            WhammyBarPoints.RemoveAt(1);
                        }
                        else
                        {
                            Logger.Warning("Model", "Unsupported whammy type detected, fallback to custom");
                        }
                    }
                    else
                    {
                        Logger.Warning("Model", "Unsupported whammy type detected, fallback to custom");
                    }
                }
            }

            UpdateDurations();

            if (needCopyBeatForBend)
            {
                // if this beat is a simple bend convert it to a grace beat
                // and generate a placeholder beat with tied notes

                var cloneBeat = Clone();
                cloneBeat.Id = _globalBeatId++;
                for (int i = 0, j = cloneBeat.Notes.Count; i < j; i++)
                {
                    var cloneNote = cloneBeat.Notes[i];
                    // remove bend on cloned note
                    cloneNote.BendType     = BendType.None;
                    cloneNote.MaxBendPoint = null;
                    cloneNote.BendPoints   = new FastList <BendPoint>();
                    cloneNote.BendStyle    = BendStyle.Default;
                    cloneNote.Id           = Note.GlobalNoteId++;

                    // if the note has a bend which is continued on the next note
                    // we need to convert this note into a hold bend
                    var note = Notes[i];
                    if (note.HasBend && note.IsTieOrigin)
                    {
                        var tieDestination = Note.NextNoteOnSameLine(note);
                        if (tieDestination != null && tieDestination.HasBend)
                        {
                            cloneNote.BendType = BendType.Hold;
                            var lastPoint = note.BendPoints[note.BendPoints.Count - 1];
                            cloneNote.AddBendPoint(new BendPoint(0, lastPoint.Value));
                            cloneNote.AddBendPoint(new BendPoint(BendPoint.MaxPosition, lastPoint.Value));
                        }
                    }

                    // mark as tied note
                    cloneNote.IsTieDestination = true;
                }

                GraceType = GraceType.BendGrace;
                UpdateDurations();

                Voice.InsertBeat(this, cloneBeat);
            }

            Fermata = Voice.Bar.MasterBar.GetFermata(this);
        }