public void RemoveWhammyBarPoint(int index) { // check index if (index < 0 || index >= WhammyBarPoints.Count) { return; } // remove point WhammyBarPoints.RemoveAt(index); var point = WhammyBarPoints[index]; // update maxWhammy point if required if (point != MaxWhammyPoint) { return; } MaxWhammyPoint = null; foreach (var currentPoint in WhammyBarPoints) { if (MaxWhammyPoint == null || currentPoint.Value > MaxWhammyPoint.Value) { MaxWhammyPoint = currentPoint; } } }
internal void Finish(Settings settings) { var displayMode = settings == null ? DisplayMode.GuitarPro : settings.DisplayMode; var isGradual = Text == "grad" || Text == "grad."; if (isGradual && displayMode == DisplayMode.SongBook) { Text = ""; } var needCopyBeatForBend = false; MinNote = null; MaxNote = null; MinStringNote = null; MaxStringNote = null; var visibleNotes = 0; for (int i = 0, j = Notes.Count; i < j; i++) { var note = Notes[i]; note.Finish(settings); if (note.IsLetRing) { IsLetRing = true; } if (note.IsPalmMute) { IsPalmMute = true; } if (note.IsSlurOrigin) { IsSlurOrigin = true; } if (displayMode == DisplayMode.SongBook && note.HasBend && GraceType != GraceType.BendGrace) { if (!note.IsTieOrigin) { switch (note.BendType) { case BendType.Bend: case BendType.PrebendRelease: case BendType.PrebendBend: needCopyBeatForBend = true; break; } } if (isGradual || note.BendStyle == BendStyle.Gradual) { isGradual = true; note.BendStyle = BendStyle.Gradual; needCopyBeatForBend = false; } else { note.BendStyle = BendStyle.Fast; } } 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 (Notes.Count > 0 && visibleNotes == 0) { IsEmpty = true; } if (IsSlurOrigin) { IsSlurOrigin = true; SlurDestination = NextBeat; if (!IsSlurDestination) { SlurOrigin = this; if (SlurDestination != null) { SlurDestination.SlurOrigin = this; } } else { SlurOrigin.SlurDestination = SlurDestination; if (SlurDestination != null) { SlurDestination.SlurOrigin = SlurOrigin; } } } // 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; } } // if beat is a rest implicitely take over letring/palmmute // from the previous beat gets cleaned later in case we flagged it wrong. else if (IsRest && PreviousBeat != null && settings != null && settings.DisplayMode == DisplayMode.GuitarPro) { if (PreviousBeat.IsLetRing) { IsLetRing = true; } if (PreviousBeat.IsPalmMute) { IsPalmMute = true; } } // 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) { if (displayMode == DisplayMode.SongBook) { WhammyStyle = isGradual ? BendStyle.Gradual : BendStyle.Fast; } 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; if (middle1.Offset == middle2.Offset || displayMode == DisplayMode.SongBook) { WhammyBarPoints.RemoveAt(2); } } 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); }