Fix overlapping notes

More consistent CLyric
Some renaming for clearer meaning
This commit is contained in:
Flamefire committed 2013-10-11 14:50:27 +02:00
1 parent bf1c00b5d1
commit 55d5c61a66
11 files changed
+177 -201

No files matched your search

+3 -3
View File
@@ -290,7 +290,7 @@ namespace Vocaluxe.Base
//CSound.RecordSetTone(p, Tone);
double points = (CSettings.MaxScore - CSettings.LinebonusScore) * (double)notes[note].PointsForBeat /
song.Notes.GetVoice(Players[p].VoiceNr).Points;
if (notes[note].NoteType == ENoteType.Golden)
if (notes[note].Type == ENoteType.Golden)
Players[p].PointsGoldenNotes += points;
Players[p].Points += points;
@@ -384,7 +384,7 @@ namespace Vocaluxe.Base
{
if (note.StartBeat < nextStart)
{
if (note.Hit && note.HitNote.NoteType==ENoteType.Golden)
if (note.Hit && note.HitNote.Type == ENoteType.Golden)
Players[p].PointsGoldenNotes += note.Points;
Players[p].Points += note.Points;
}
@@ -394,7 +394,7 @@ namespace Vocaluxe.Base
}
while (line.NoteCount > n && n >= 0)
{
if (line.Notes[n].Hit && line.Notes[n].HitNote.NoteType == ENoteType.Golden)
if (line.Notes[n].Hit && line.Notes[n].HitNote.Type == ENoteType.Golden)
Players[p].PointsGoldenNotes -= line.Notes[n].Points;
Players[p].Points -= line.Notes[n].Points;
line.DeleteNote(n);
+59 -62
View File
@@ -327,7 +327,7 @@ namespace Vocaluxe.Screens
_LoadNextSong();
_UpdateSongText();
_UpdateDuetText();
_UpdateDuetNames();
if (_FadeOut)
return true;
@@ -387,12 +387,8 @@ namespace Vocaluxe.Screens
for (int p = 0; p < CGame.NumPlayer; p++)
{
// ReSharper disable ConvertIfStatementToConditionalTernaryExpression
if (CGame.Players[p].Points < 10000)
// ReSharper restore ConvertIfStatementToConditionalTernaryExpression
_Texts[_TextScores[p, CGame.NumPlayer - 1]].Text = CGame.Players[p].Points.ToString("0000");
else
_Texts[_TextScores[p, CGame.NumPlayer - 1]].Text = CGame.Players[p].Points.ToString("00000");
string fmtString = (CGame.Players[p].Points < 10000) ? "0000" : "00000";
_Texts[_TextScores[p, CGame.NumPlayer - 1]].Text = CGame.Players[p].Points.ToString(fmtString);
}
if (_CurrentVideo != -1 && !_FadeOut && CConfig.VideosInSongs == EOffOn.TR_CONFIG_ON)
@@ -607,12 +603,12 @@ namespace Vocaluxe.Screens
_FinishTime = song.Finish;
_TimeToFirstNote = 0f;
_TimeToFirstNoteDuet = 0f;
var duetPlayer = new int[CGame.NumPlayer];
var voiceAssignments = new int[CGame.NumPlayer];
if (song.IsDuet)
{
//Save duet-assignment before resetting
for (int i = 0; i < duetPlayer.Length; i++)
duetPlayer[i] = CGame.Players[i].VoiceNr;
for (int i = 0; i < voiceAssignments.Length; i++)
voiceAssignments[i] = CGame.Players[i].VoiceNr;
}
CGame.ResetPlayer();
@@ -647,7 +643,7 @@ namespace Vocaluxe.Screens
else
{
for (int i = 0; i < CGame.NumPlayer; i++)
CGame.Players[i].VoiceNr = duetPlayer[i];
CGame.Players[i].VoiceNr = voiceAssignments[i];
}
}
@@ -673,14 +669,11 @@ namespace Vocaluxe.Screens
NoteLines[3] = SingNotes[SingBars].AddPlayer(new SRectF(640f, 350f, 590f, 200f, -0.5f), CTheme.ThemeColors.Player[3]);
break;
*/
_TimerSongText.Stop();
_TimerSongText.Reset();
_TimerDuetText1.Stop();
_TimerDuetText1.Reset();
_TimerDuetText2.Stop();
_TimerDuetText2.Reset();
if (song.Notes.Voices.Length != 2)
if (!song.IsDuet)
_TimerSongText.Start();
_StartSong();
@@ -1198,8 +1191,8 @@ namespace Vocaluxe.Screens
}
else
{
_Statics[_StaticSongText].Color.A = (3f - (t - 7f)) / 3f;
_Texts[_TextSongName].Color.A = (3f - (t - 7f)) / 3f;
_Statics[_StaticSongText].Color.A = 10f - t / 3f;
_Texts[_TextSongName].Color.A = 10f - t / 3f;
}
}
else
@@ -1216,61 +1209,65 @@ namespace Vocaluxe.Screens
}
}
private void _UpdateDuetText()
private void _UpdateDuetNames(CText textName, Stopwatch timer)
{
if (CGame.GetSong() != null)
if (timer.IsRunning)
{
//Timer for first duet-part
if (_TimerDuetText1.IsRunning)
float t = timer.ElapsedMilliseconds / 1000f;
if (t < 10f)
{
float t = _TimerDuetText1.ElapsedMilliseconds / 1000f;
if (t < 10f)
{
_Texts[_TextDuetName1].Visible = true;
textName.Visible = true;
if (t < 3f)
_Texts[_TextDuetName1].Color.A = (3f - (3f - t)) / 3f;
else if (t < 7f)
_Texts[_TextDuetName1].Color.A = 1f;
else
_Texts[_TextDuetName1].Color.A = (3f - (t - 7f)) / 3f;
}
if (t < 3f)
textName.Color.A = t / 3f;
else if (t < 7f)
textName.Color.A = 1f;
else
{
_Texts[_TextDuetName1].Visible = false;
_TimerDuetText1.Stop();
}
textName.Color.A = (10f - t) / 3f;
}
else if (!_TimerDuetText1.IsRunning && _TimerDuetText1.ElapsedMilliseconds == 0 && _Lyrics[_LyricMainDuet].Alpha > 0 && CGame.GetSong().IsDuet)
_TimerDuetText1.Start();
else
_Texts[_TextDuetName1].Visible = false;
//Timer for second duet-part
if (_TimerDuetText2.IsRunning)
{
float t = _TimerDuetText2.ElapsedMilliseconds / 1000f;
if (t < 10f)
{
_Texts[_TextDuetName2].Visible = true;
if (t < 3f)
_Texts[_TextDuetName2].Color.A = (3f - (3f - t)) / 3f;
else if (t < 7f)
_Texts[_TextDuetName2].Color.A = 1f;
else
_Texts[_TextDuetName2].Color.A = (3f - (t - 7f)) / 3f;
}
else
{
_Texts[_TextDuetName2].Visible = false;
_TimerDuetText2.Stop();
}
textName.Visible = false;
timer.Stop();
}
else if (!_TimerDuetText2.IsRunning && _TimerDuetText2.ElapsedMilliseconds == 0 && _Lyrics[_LyricMain].Alpha > 0 && CGame.GetSong().IsDuet)
_TimerDuetText2.Start();
else
_Texts[_TextDuetName2].Visible = false;
}
else if (!timer.IsRunning && timer.ElapsedMilliseconds == 0 && _Lyrics[_LyricMainDuet].Alpha > 0 && CGame.GetSong().IsDuet)
timer.Start();
else
textName.Visible = false;
}
private void _UpdateDuetNames()
{
if (CGame.GetSong() == null)
return;
//Timer for first duet-part
_UpdateDuetNames(_Texts[_TextDuetName1], _TimerDuetText1);
//Timer for second duet-part
if (_TimerDuetText2.IsRunning)
{
float t = _TimerDuetText2.ElapsedMilliseconds / 1000f;
if (t < 10f)
{
_Texts[_TextDuetName2].Visible = true;
if (t < 3f)
_Texts[_TextDuetName2].Color.A = (3f - (3f - t)) / 3f;
else if (t < 7f)
_Texts[_TextDuetName2].Color.A = 1f;
else
_Texts[_TextDuetName2].Color.A = (3f - (t - 7f)) / 3f;
}
else
{
_Texts[_TextDuetName2].Visible = false;
_TimerDuetText2.Stop();
}
}
else if (!_TimerDuetText2.IsRunning && _TimerDuetText2.ElapsedMilliseconds == 0 && _Lyrics[_LyricMain].Alpha > 0 && CGame.GetSong().IsDuet)
_TimerDuetText2.Start();
else
_Texts[_TextDuetName2].Visible = false;
}
private void _UpdateTimeLine()
+55 -100
View File
@@ -28,7 +28,6 @@ namespace VocaluxeLib.Menu
public string Text;
public int StartBeat;
public int EndBeat;
public int Duration;
public ENoteType Type;
}
@@ -46,7 +45,10 @@ namespace VocaluxeLib.Menu
private SThemeLyrics _Theme;
private bool _ThemeLoaded;
private readonly List<SNote> _Notes;
/// <summary>
/// Holds a reference to Songline. DO NOT MODIFY
/// </summary>
private CSongLine _Line;
private CText _Text;
private float _X;
@@ -109,7 +111,7 @@ namespace VocaluxeLib.Menu
_MaxW = 1f;
_H = 1f;
_Width = 1f;
_Notes = new List<SNote>();
_Line = new CSongLine();
_Text = new CText(_PartyModeID);
LyricStyle = ELyricStyle.Fill;
@@ -201,28 +203,27 @@ namespace VocaluxeLib.Menu
public void SetLine(CSongLine line)
{
_Notes.Clear();
_Line = line;
_Width = 0f;
foreach (CSongNote note in line.Notes)
{
var n = new SNote {Text = note.Text, StartBeat = note.StartBeat, EndBeat = note.EndBeat, Duration = note.Duration, Type = note.NoteType};
_Text.Text = note.Text;
_Text.Style = EStyle.Bold;
if (n.Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
RectangleF rect = CBase.Fonts.GetTextBounds(_Text);
_Width += rect.Width;
_Notes.Add(n);
_SetText(note);
_Width += _Text.Rect.W;
}
}
private void _SetText(CSongNote note)
{
_Text.Text = note.Text;
_Text.Style = EStyle.Bold;
if (note.Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
}
public void Clear()
{
_Notes.Clear();
_Line = new CSongLine();
}
public float GetCurrentLyricPosX()
@@ -260,15 +261,10 @@ namespace VocaluxeLib.Menu
{
float x = _X - _Width / 2;
foreach (SNote note in _Notes)
foreach (CSongNote note in _Line.Notes)
{
_Text.X = x;
_Text.Style = EStyle.Bold;
_Text.Text = note.Text;
RectangleF rect = CBase.Fonts.GetTextBounds(_Text);
if (note.Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
_SetText(note);
if (currentBeat >= note.StartBeat)
{
@@ -276,9 +272,8 @@ namespace VocaluxeLib.Menu
{
_Text.Color = _ColorProcessed;
float diff = note.EndBeat - note.StartBeat;
if (Math.Abs(diff) < float.Epsilon)
int diff = note.EndBeat - note.StartBeat;
if (diff <= 0)
_Text.Draw(0f, 1f);
else
{
@@ -299,7 +294,7 @@ namespace VocaluxeLib.Menu
_Text.Draw();
}
x += rect.Width;
x += _Text.Rect.W;
}
}
@@ -308,37 +303,27 @@ namespace VocaluxeLib.Menu
float x = _X - _Width / 2; // most left position
//find last active note
int lastNote = -1;
for (int i = 0; i < _Notes.Count; i++)
{
if (currentBeat >= _Notes[i].StartBeat)
lastNote = i;
}
int lastNote = _Line.FindPreviousNote((int)currentBeat);
int zoomNote = -1;
int endBeat = -1;
float zoomx = 0f;
for (int note = 0; note < _Notes.Count; note++)
for (int note = 0; note < _Line.Notes.Length; note++)
{
_Text.X = x;
_Text.Style = EStyle.Bold;
_Text.Text = _Notes[note].Text;
RectangleF rect = CBase.Fonts.GetTextBounds(_Text);
_SetText(_Line.Notes[note]);
if (_Notes[note].Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
if (currentBeat >= _Notes[note].StartBeat)
if (currentBeat >= _Line.Notes[note].StartBeat)
{
int endbeat = _Notes[note].EndBeat;
if (note < _Notes.Count - 1)
endbeat = _Notes[note + 1].StartBeat - 1;
int curEndBeat = _Line.Notes[note].EndBeat;
if (note < _Line.Notes.Length - 1)
curEndBeat = _Line.Notes[note + 1].StartBeat - 1;
if (currentBeat <= endbeat)
if (currentBeat <= curEndBeat)
{
zoomNote = note;
endBeat = endbeat;
endBeat = curEndBeat;
zoomx = _Text.X;
}
else
@@ -356,49 +341,37 @@ namespace VocaluxeLib.Menu
_Text.Draw();
}
x += rect.Width;
x += _Text.Rect.W;
}
if (zoomNote > -1)
{
if (_Notes[zoomNote].Duration == 0)
return;
_Text.X = zoomx;
_Text.Text = _Notes[zoomNote].Text;
_Text.Color = _ColorProcessed;
_Text.Style = EStyle.Bold;
_SetText(_Line.Notes[zoomNote]);
if (_Notes[zoomNote].Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
RectangleF rect = CBase.Fonts.GetTextBounds(_Text);
float diff = endBeat - _Notes[zoomNote].StartBeat;
float diff = endBeat - _Line.Notes[zoomNote].StartBeat;
if (diff <= 0f)
diff = 1f;
float p = (currentBeat - _Notes[zoomNote].StartBeat) / diff;
float p = (currentBeat - _Line.Notes[zoomNote].StartBeat) / diff;
if (p > 1f)
p = 1f;
p = 1f - p;
float ty = _Text.Y;
float tx = _Text.X;
float th = _Text.Height;
float tz = _Text.Z;
SRectF normalRect = _Text.Rect;
_Text.Height += _Text.Height * p * 0.4f;
RectangleF rectz = CBase.Fonts.GetTextBounds(_Text);
_Text.X -= (rectz.Width - rect.Width) / 2f;
_Text.Y -= (rectz.Height - rect.Height) / 2f;
_Text.X -= (_Text.Rect.W - normalRect.W) / 2f;
_Text.Y -= (_Text.Rect.W - normalRect.H) / 2f;
_Text.Z -= 0.1f;
_Text.Draw();
_Text.Y = ty;
_Text.X = tx;
_Text.Height = th;
_Text.Z = tz;
}
@@ -408,15 +381,10 @@ namespace VocaluxeLib.Menu
{
float x = _X - _Width / 2; // most left position
foreach (SNote note in _Notes)
foreach (CSongNote note in _Line.Notes)
{
_Text.X = x;
_Text.Style = EStyle.Bold;
_Text.Text = note.Text;
RectangleF rect = CBase.Fonts.GetTextBounds(_Text);
if (note.Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
_SetText(note);
if (currentBeat >= note.StartBeat)
{
@@ -430,7 +398,7 @@ namespace VocaluxeLib.Menu
_Text.Draw();
}
x += rect.Width;
x += _Text.Rect.W;
}
}
@@ -439,29 +407,23 @@ namespace VocaluxeLib.Menu
float x = _X - _Width / 2; // most left position
//find last active note
int lastNote = -1;
for (int i = 0; i < _Notes.Count; i++)
{
if (currentBeat >= _Notes[i].StartBeat)
lastNote = i;
}
int lastNote = _Line.FindPreviousNote((int)currentBeat);
int jumpNote = -1;
float jumpx = 0f;
for (int note = 0; note < _Notes.Count; note++)
for (int note = 0; note < _Line.Notes.Length; note++)
{
_Text.X = x;
_Text.Style = EStyle.Bold;
_Text.Text = _Notes[note].Text;
RectangleF rect = CBase.Fonts.GetTextBounds(_Text);
_SetText(_Line.Notes[note]);
if (_Notes[note].Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
if (currentBeat >= _Notes[note].StartBeat)
if (currentBeat >= _Line.Notes[note].StartBeat)
{
if (currentBeat <= _Notes[note].EndBeat)
int curEndBeat = _Line.Notes[note].EndBeat;
if (note < _Line.Notes.Length - 1)
curEndBeat = _Line.Notes[note + 1].StartBeat - 1;
if (currentBeat <= curEndBeat)
{
jumpNote = note;
jumpx = _Text.X;
@@ -481,27 +443,20 @@ namespace VocaluxeLib.Menu
_Text.Draw();
}
x += rect.Width;
x += _Text.Rect.W;
}
if (jumpNote < 0)
return;
if (_Notes[jumpNote].Duration == 0)
return;
_Text.X = jumpx;
_Text.Text = _Notes[jumpNote].Text;
_Text.Color = _ColorProcessed;
_Text.Style = EStyle.Bold;
_SetText(_Line.Notes[jumpNote]);
if (_Notes[jumpNote].Type == ENoteType.Freestyle)
_Text.Style = EStyle.BoldItalic;
int diff = _Notes[jumpNote].EndBeat - _Notes[jumpNote].StartBeat;
int diff = _Line.Notes[jumpNote].EndBeat - _Line.Notes[jumpNote].StartBeat;
if (diff <= 0)
diff = 1;
float p = 1f - (currentBeat - _Notes[jumpNote].StartBeat) / diff;
float p = 1f - (currentBeat - _Line.Notes[jumpNote].StartBeat) / diff;
if (Math.Abs(p) < float.Epsilon)
_Text.Draw();
+1 -1
View File
@@ -561,7 +561,7 @@ namespace VocaluxeLib.Menu
float y = Y;
RectangleF bounds = CBase.Fonts.GetTextBounds(this);
if (bounds.Width > MaxWidth && MaxWidth > 0f && bounds.Width > 0f)
if (MaxWidth > 0f && bounds.Width > MaxWidth && bounds.Width > 0f)
{
float factor = MaxWidth / bounds.Width;
float step = h * (1 - factor);
+3 -3
View File
@@ -319,7 +319,7 @@ namespace VocaluxeLib.Menu.SingNotes
int nr = 1;
foreach (CSongNote note in line.Notes)
{
if (note.NoteType != ENoteType.Freestyle)
if (note.Type != ENoteType.Freestyle)
{
float width = note.Duration / beats * w;
@@ -334,7 +334,7 @@ namespace VocaluxeLib.Menu.SingNotes
_DrawNoteBG(rect, color, 1f, _PlayerNotes[n].Timer);
_DrawNote(rect, new SColorF(5f, 5f, 5f, 0.7f * _PlayerNotes[n].Alpha), 0.7f);
if (note.NoteType == ENoteType.Golden)
if (note.Type == ENoteType.Golden)
{
_AddGoldenNote(rect, n, nr);
nr++;
@@ -386,7 +386,7 @@ namespace VocaluxeLib.Menu.SingNotes
_DrawNote(rect, color, f);
if (note.EndBeat >= CBase.Game.GetRecordedBeat() && note.Hit && note.HitNote.NoteType == ENoteType.Golden)
if (note.EndBeat >= CBase.Game.GetRecordedBeat() && note.Hit && note.HitNote.Type == ENoteType.Golden)
{
var re = new SRectF(rect) {W = (CBase.Game.GetMidRecordedBeat() - note.StartBeat) / beats * w};
_AddFlare(re, n);
+4
View File
@@ -15,6 +15,8 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
namespace VocaluxeLib.Songs
{
/// <summary>
@@ -38,6 +40,8 @@ namespace VocaluxeLib.Songs
StartBeat = startBeat;
Duration = duration;
Tone = tone;
if (Duration < 1)
throw new Exception("Note to short. All notes should be at least 1 beat long!");
}
#endregion Constructors
+5 -1
View File
@@ -79,7 +79,11 @@ namespace VocaluxeLib.Songs
#endregion Properties
#region Methods
//Find last note with StartBeat<=Beat
/// <summary>
/// Find last note with StartBeat<=Beat
/// </summary>
/// <param name="beat"></param>
/// <returns>Note index of last note with StartBeat<=Beat or -1 if all notes start after beat</returns>
public int FindPreviousNote(int beat)
{
//If no notes -> No previous note
+29 -22
View File
@@ -628,33 +628,40 @@ namespace VocaluxeLib.Songs
sr.Read();
string paramS = sr.ReadLine();
ENoteType noteType;
if (tempC.CompareTo('*') == 0)
noteType = ENoteType.Golden;
else if (tempC.CompareTo('F') == 0)
noteType = ENoteType.Freestyle;
if (param2 < 1)
CBase.Log.LogError("Warning! Ignored note in song because length is < 1. Line No.: " + fileLineNo + ": " + filePath);
else
noteType = ENoteType.Normal;
if (Relative == EOffOn.TR_CONFIG_ON)
param1 += currentPos;
int curPlayer = 0;
int tmpPlayer = player;
//Evaluate as bitset
while (tmpPlayer > 0)
{
if ((tmpPlayer & 1) != 0)
ENoteType noteType;
if (tempC.CompareTo('*') == 0)
noteType = ENoteType.Golden;
else if (tempC.CompareTo('F') == 0)
noteType = ENoteType.Freestyle;
else
noteType = ENoteType.Normal;
if (Relative == EOffOn.TR_CONFIG_ON)
param1 += currentPos;
int curPlayer = 0;
int tmpPlayer = player;
//Evaluate as bitset
while (tmpPlayer > 0)
{
if (!_ParseNote(curPlayer, noteType, param1, param2, param3, paramS))
CBase.Log.LogError("Warning! Ignored note for player " + (curPlayer + 1) + " in song because it overlaps with other note. Line No.: " +
fileLineNo + ": " + filePath);
if ((tmpPlayer & 1) != 0)
{
if (!_ParseNote(curPlayer, noteType, param1, param2, param3, paramS))
{
CBase.Log.LogError("Warning! Ignored note for player " + (curPlayer + 1) + " in song because it overlaps with other note. Line No.: " +
fileLineNo + ": " + filePath);
}
}
tmpPlayer >>= 1;
curPlayer++;
}
tmpPlayer >>= 1;
curPlayer++;
isNewSentence = false;
}
isNewSentence = false;
break;
case '-':
if (isNewSentence)
+12 -5
View File
@@ -77,12 +77,19 @@ namespace VocaluxeLib.Songs
_Notes.Add(note);
else
{
//Insert AFTER this note
int insPos = FindPreviousNote(note.StartBeat);
//Check for overlapping notes
if (insPos >= 0 && _Notes[insPos].EndBeat > note.StartBeat)
return false;
if (insPos < _Notes.Count - 1 && _Notes[insPos + 1].StartBeat > note.EndBeat)
return false;
if (insPos >= 0) //Check note before
{
if (_Notes[insPos].EndBeat > note.StartBeat)
return false;
}
if (insPos < _Notes.Count - 1) //Check note after
{
if (_Notes[insPos + 1].StartBeat < note.EndBeat)
return false;
}
_Notes.Insert(insPos + 1, note);
}
return true;
@@ -91,7 +98,7 @@ namespace VocaluxeLib.Songs
public void SetMedley(int startBeat, int endBeat)
{
foreach (CSongNote note in _Notes.Where(note => note.StartBeat < startBeat || note.EndBeat > endBeat))
note.NoteType = ENoteType.Freestyle;
note.Type = ENoteType.Freestyle;
VisibleInTimeLine = FirstNoteBeat >= startBeat && LastNoteBeat <= endBeat;
}
+4 -4
View File
@@ -25,20 +25,20 @@ namespace VocaluxeLib.Songs
#region Contructors
public CSongNote(CSongNote note) : base(note)
{
NoteType = note.NoteType;
Type = note.Type;
Text = note.Text;
}
public CSongNote(int startBeat, int duration, int tone, string text, ENoteType noteType)
: base(startBeat, duration, tone)
{
NoteType = noteType;
Type = noteType;
Text = text;
}
#endregion Constructors
#region Properties
public ENoteType NoteType { get; set; }
public ENoteType Type { get; set; }
public string Text { get; set; }
@@ -46,7 +46,7 @@ namespace VocaluxeLib.Songs
{
get
{
switch (NoteType)
switch (Type)
{
case ENoteType.Normal:
return 1;
+2
View File
@@ -122,6 +122,8 @@ namespace VocaluxeLib.Songs
public bool AddNote(CSongNote note, bool updateTimings = false)
{
int lineIndex = FindPreviousLine(note.StartBeat);
if (lineIndex + 1 < _Lines.Count && _Lines[lineIndex + 1].FirstNoteBeat < note.EndBeat) //First note in next line starts before this one ends
return false;
if (lineIndex < 0)
{
//Note is before ALL lines