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);
}