Do not add line before first line
Calculate start beat automatically More stable note loading with better warnings
This commit is contained in:
1 parent
ee6aaebfbc
commit
bbe8cfbe08
3 files changed
+100
-77
No files matched your search
@@ -22,7 +22,7 @@ namespace VocaluxeLib.Songs
|
|||||||
{
|
{
|
||||||
public class CSongLine : CLineBase<CSongNote>
|
public class CSongLine : CLineBase<CSongNote>
|
||||||
{
|
{
|
||||||
private int _StartBeat = int.MinValue;
|
private int _StartBeat = int.MaxValue;
|
||||||
private int _EndBeat = int.MinValue;
|
private int _EndBeat = int.MinValue;
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
@@ -46,7 +46,7 @@ namespace VocaluxeLib.Songs
|
|||||||
|
|
||||||
public int StartBeat
|
public int StartBeat
|
||||||
{
|
{
|
||||||
get { return _StartBeat; }
|
get { return Math.Min(_StartBeat, FirstNoteBeat); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value <= FirstNoteBeat)
|
if (value <= FirstNoteBeat)
|
||||||
@@ -56,7 +56,7 @@ namespace VocaluxeLib.Songs
|
|||||||
|
|
||||||
public int EndBeat
|
public int EndBeat
|
||||||
{
|
{
|
||||||
get { return _EndBeat; }
|
get { return Math.Min(_EndBeat, LastNoteBeat); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value >= LastNoteBeat)
|
if (value >= LastNoteBeat)
|
||||||
|
|||||||
@@ -127,9 +127,18 @@ namespace VocaluxeLib.Songs
|
|||||||
if (lineIndex < 0)
|
if (lineIndex < 0)
|
||||||
{
|
{
|
||||||
//Note is before ALL lines
|
//Note is before ALL lines
|
||||||
var line = new CSongLine {StartBeat = note.StartBeat};
|
if (_Lines.Count > 0)
|
||||||
line.AddNote(note);
|
{
|
||||||
_Lines.Insert(0, line);
|
//Add to first line
|
||||||
|
if (!_Lines[0].AddNote(note))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var line = new CSongLine();
|
||||||
|
line.AddNote(note);
|
||||||
|
_Lines.Add(line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -157,8 +166,9 @@ namespace VocaluxeLib.Songs
|
|||||||
{
|
{
|
||||||
CSongNote lastNote;
|
CSongNote lastNote;
|
||||||
|
|
||||||
if (_Lines.Count > 0)
|
if (_Lines.Count == 0)
|
||||||
_Lines[0].StartBeat = -10000;
|
return;
|
||||||
|
_Lines[0].StartBeat = -10000;
|
||||||
|
|
||||||
for (int i = 1; i < _Lines.Count; i++)
|
for (int i = 1; i < _Lines.Count; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -340,12 +340,15 @@ namespace VocaluxeLib.Songs
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char tempC = char.MinValue;
|
int currentBeat = 0; //Used for relative songs
|
||||||
int currentPos = 0;
|
|
||||||
bool isNewSentence = false;
|
bool isNewSentence = false;
|
||||||
|
bool endFound = false;
|
||||||
|
|
||||||
int player = 1;
|
int player = 1;
|
||||||
int fileLineNo = 0;
|
int lineNr = 0;
|
||||||
|
|
||||||
|
char[] trimChars = {' ', ':'};
|
||||||
|
char[] splitChars = {' '};
|
||||||
|
|
||||||
StreamReader sr = null;
|
StreamReader sr = null;
|
||||||
try
|
try
|
||||||
@@ -355,40 +358,32 @@ namespace VocaluxeLib.Songs
|
|||||||
Notes.Reset();
|
Notes.Reset();
|
||||||
|
|
||||||
//Search for Note Beginning
|
//Search for Note Beginning
|
||||||
while (!sr.EndOfStream)
|
while (!sr.EndOfStream && !endFound)
|
||||||
{
|
{
|
||||||
sr.ReadLine();
|
string line = sr.ReadLine();
|
||||||
fileLineNo++;
|
lineNr++;
|
||||||
|
|
||||||
tempC = (char)sr.Peek();
|
if (String.IsNullOrEmpty(line))
|
||||||
if ((tempC == '#') || (tempC == '\r') || (tempC == '\n'))
|
|
||||||
continue;
|
continue;
|
||||||
if ((tempC == ':') || (tempC == 'F') || (tempC == '*') || (tempC == 'P'))
|
|
||||||
{
|
|
||||||
tempC = (char)sr.Read();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sr.EndOfStream)
|
char tag = line[0];
|
||||||
{
|
//Remove tag and potential space
|
||||||
CBase.Log.LogError("Error loading song. Line No.: " + fileLineNo + ". No lyrics/notes found: " + filePath);
|
line = (line.Length >= 2 && line[1] == ' ') ? line.Substring(2) : line.Substring(1);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
int beat, length;
|
||||||
{
|
switch (tag)
|
||||||
int param2;
|
|
||||||
int param1;
|
|
||||||
switch (tempC)
|
|
||||||
{
|
{
|
||||||
|
case '#':
|
||||||
|
continue;
|
||||||
|
case 'E':
|
||||||
|
endFound = true;
|
||||||
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
char chr;
|
line = line.Trim(trimChars);
|
||||||
while ((chr = (char)sr.Read()) == ' ') {}
|
|
||||||
|
|
||||||
if (!int.TryParse(chr.ToString(), out player))
|
if (!int.TryParse(line, out player))
|
||||||
{
|
{
|
||||||
CBase.Log.LogError("Error loading song. Line No.: " + fileLineNo + ". Wrong or missing number after \"P\": " + filePath);
|
_LogReadError("Error: Wrong or missing number after \"P\"", lineNr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sr.ReadLine();
|
sr.ReadLine();
|
||||||
@@ -396,33 +391,46 @@ namespace VocaluxeLib.Songs
|
|||||||
case ':':
|
case ':':
|
||||||
case '*':
|
case '*':
|
||||||
case 'F':
|
case 'F':
|
||||||
sr.Read();
|
string[] noteData = line.Split(splitChars, 4);
|
||||||
param1 = CHelper.TryReadInt(sr);
|
if (noteData.Length < 4)
|
||||||
|
{
|
||||||
sr.Read();
|
if (noteData.Length == 3)
|
||||||
param2 = CHelper.TryReadInt(sr);
|
{
|
||||||
|
_LogReadError("Warning: Ignored note without text", lineNr);
|
||||||
sr.Read();
|
continue;
|
||||||
int param3 = CHelper.TryReadInt(sr);
|
}
|
||||||
|
_LogReadError("Error: Invalid note found", lineNr);
|
||||||
sr.Read();
|
sr.Dispose();
|
||||||
string paramS = sr.ReadLine();
|
return false;
|
||||||
|
}
|
||||||
if (param2 < 1)
|
int tone;
|
||||||
CBase.Log.LogError("Warning! Ignored note in song because length is < 1. Line No.: " + fileLineNo + ": " + filePath);
|
if (!int.TryParse(noteData[0], out beat) || !int.TryParse(noteData[1], out length) || !int.TryParse(noteData[2], out tone))
|
||||||
|
{
|
||||||
|
_LogReadError("Error: Invalid note found (non-numeric values)", lineNr);
|
||||||
|
sr.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
string text = noteData[3];
|
||||||
|
if (text.Trim() == "")
|
||||||
|
{
|
||||||
|
_LogReadError("Warning: Ignored note without text", lineNr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (length < 1)
|
||||||
|
_LogReadError("Warning: Ignored note with length < 1", lineNr);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ENoteType noteType;
|
ENoteType noteType;
|
||||||
|
|
||||||
if (tempC.CompareTo('*') == 0)
|
if (tag.Equals('*'))
|
||||||
noteType = ENoteType.Golden;
|
noteType = ENoteType.Golden;
|
||||||
else if (tempC.CompareTo('F') == 0)
|
else if (tag.Equals('F'))
|
||||||
noteType = ENoteType.Freestyle;
|
noteType = ENoteType.Freestyle;
|
||||||
else
|
else
|
||||||
noteType = ENoteType.Normal;
|
noteType = ENoteType.Normal;
|
||||||
|
|
||||||
if (Relative == EOffOn.TR_CONFIG_ON)
|
if (Relative == EOffOn.TR_CONFIG_ON)
|
||||||
param1 += currentPos;
|
beat += currentBeat;
|
||||||
|
|
||||||
int curPlayer = 0;
|
int curPlayer = 0;
|
||||||
int tmpPlayer = player;
|
int tmpPlayer = player;
|
||||||
@@ -431,10 +439,10 @@ namespace VocaluxeLib.Songs
|
|||||||
{
|
{
|
||||||
if ((tmpPlayer & 1) != 0)
|
if ((tmpPlayer & 1) != 0)
|
||||||
{
|
{
|
||||||
if (!_ParseNote(curPlayer, noteType, param1, param2, param3, paramS))
|
if (!_ParseNote(curPlayer, noteType, beat, length, tone, text))
|
||||||
{
|
{
|
||||||
CBase.Log.LogError("Warning! Ignored note for player " + (curPlayer + 1) + " in song because it overlaps with other note. Line No.: " +
|
CBase.Log.LogError("Warning! Ignored note for player " + (curPlayer + 1) + " because it overlaps with other note. Line No.: " +
|
||||||
fileLineNo + ": " + filePath);
|
lineNr + ": " + filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmpPlayer >>= 1;
|
tmpPlayer >>= 1;
|
||||||
@@ -446,22 +454,35 @@ namespace VocaluxeLib.Songs
|
|||||||
case '-':
|
case '-':
|
||||||
if (isNewSentence)
|
if (isNewSentence)
|
||||||
{
|
{
|
||||||
CBase.Log.LogError("Error loading song. Line No.: " + fileLineNo + ". Double sentence break: " + filePath);
|
_LogReadError("Error: Double sentence break", lineNr);
|
||||||
|
sr.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
string[] lineBreakData = line.Split(splitChars);
|
||||||
|
if (lineBreakData.Length < 1)
|
||||||
|
{
|
||||||
|
_LogReadError("Error: Invalid line break found (No beat)", lineNr);
|
||||||
|
sr.Dispose();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!int.TryParse(lineBreakData[0], out beat))
|
||||||
|
{
|
||||||
|
_LogReadError("Error: Invalid line break found (Non-numeric value)", lineNr);
|
||||||
|
sr.Dispose();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sr.Read();
|
|
||||||
param1 = CHelper.TryReadInt(sr);
|
|
||||||
|
|
||||||
if (Relative == EOffOn.TR_CONFIG_ON)
|
if (Relative == EOffOn.TR_CONFIG_ON)
|
||||||
{
|
{
|
||||||
param1 += currentPos;
|
beat += currentBeat;
|
||||||
sr.Read();
|
if (lineBreakData.Length < 2 || !int.TryParse(lineBreakData[1], out length))
|
||||||
param2 = CHelper.TryReadInt(sr);
|
_LogReadError("Warning: Missing line break length", lineNr);
|
||||||
currentPos += param2;
|
else
|
||||||
|
currentBeat += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param1 < 1)
|
if (beat < 1)
|
||||||
CBase.Log.LogError("Warning! Ignored line break in song because position is < 1. Line No.: " + fileLineNo + ": " + filePath);
|
_LogReadError("Warning: Ignored line break because position is < 1", lineNr);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int curPlayer = 0;
|
int curPlayer = 0;
|
||||||
@@ -470,34 +491,26 @@ namespace VocaluxeLib.Songs
|
|||||||
while (tmpPlayer > 0)
|
while (tmpPlayer > 0)
|
||||||
{
|
{
|
||||||
if ((tmpPlayer & 1) != 0)
|
if ((tmpPlayer & 1) != 0)
|
||||||
_NewSentence(curPlayer, param1);
|
_NewSentence(curPlayer, beat);
|
||||||
tmpPlayer >>= 1;
|
tmpPlayer >>= 1;
|
||||||
curPlayer++;
|
curPlayer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
isNewSentence = true;
|
isNewSentence = true;
|
||||||
}
|
}
|
||||||
sr.ReadLine();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CBase.Log.LogError("Error loading song. Line No.: " + fileLineNo + ". Unexpected or missing character (" + tempC + "): " + filePath);
|
_LogReadError("Error loading song. Unexpected or missing character (" + tag + ")", lineNr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int c;
|
}
|
||||||
do
|
|
||||||
{
|
|
||||||
c = sr.Read();
|
|
||||||
} while (!sr.EndOfStream && (c == 19 || c == 16 || c == 13 || c == 10));
|
|
||||||
tempC = (char)c;
|
|
||||||
fileLineNo++;
|
|
||||||
} while (!sr.EndOfStream && (tempC != 'E'));
|
|
||||||
|
|
||||||
foreach (CVoice voice in Notes.Voices)
|
foreach (CVoice voice in Notes.Voices)
|
||||||
voice.UpdateTimings();
|
voice.UpdateTimings();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
CBase.Log.LogError("Error loading song. Line No.: " + fileLineNo + ". An unhandled exception occured (" + e.Message + "): " + filePath);
|
_LogReadError("Error: An unhandled exception occured (" + e.Message + ")", lineNr);
|
||||||
if (sr != null)
|
if (sr != null)
|
||||||
sr.Dispose();
|
sr.Dispose();
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in new issue
Block a user