Remove empty lines from Songs (causes problems otherwise!)

Compatibility reading mode for songs with 0-based lengths
Give Lines as an enumerable instead of creating an array
This commit is contained in:
Flamefire committed 2013-10-11 19:19:42 +02:00
1 parent a9b3e1d3f8
commit d498e0b935
6 files changed
+125 -25

No files matched your search

+3 -3
View File
@@ -406,9 +406,9 @@ namespace Vocaluxe.Base
}
Players[p].SungLines.RemoveRange(deleteLine, Players[p].SungLines.Count - deleteLine);
}
CSong song = GetSong();
for (int i = 0; i < GetSong().Notes.Voices[0].Lines.Length; i++)
CLog.LogError((i + 1) + ". " + song.Notes.Voices[0].Lines[i].NoteCount + " - " + Players[0].SungLines[i].NoteCount);
//CSong song = GetSong();
//for (int i = 0; i < GetSong().Notes.Voices[0].Lines.Length; i++)
// CLog.LogError((i + 1) + ". " + song.Notes.Voices[0].Lines[i].NoteCount + " - " + Players[0].SungLines[i].NoteCount);
CSound.SetPosition(soundStream, time);
CVideo.Skip(vidStream, time, GetSong().VideoGap);
+1 -1
View File
@@ -1084,7 +1084,7 @@ namespace Vocaluxe.Screens
if (song == null || !song.NotesLoaded)
return null;
var alpha = new float[song.Notes.Voices.Length * 2];
var alpha = new float[song.Notes.VoiceCount * 2];
float currentTime = _CurrentTime - song.Gap;
for (int i = 0; i < song.Notes.VoiceCount; i++)
+2 -2
View File
@@ -70,9 +70,9 @@ namespace VocaluxeLib.Songs
VoiceNames = new CVoiceNames(notes.VoiceNames);
}
public CVoice[] Voices
public IEnumerable<CVoice> Voices
{
get { return _Voices.ToArray(); }
get { return _Voices; }
}
public int VoiceCount
+1 -1
View File
@@ -133,7 +133,7 @@ namespace VocaluxeLib.Songs
private readonly bool _Selected;
public bool IsDuet
{
get { return Notes.Voices.Length > 1; }
get { return Notes.VoiceCount > 1; }
}
public readonly List<string> Edition = new List<string>();
+113 -18
View File
@@ -351,21 +351,63 @@ namespace VocaluxeLib.Songs
CBase.DataBase.GetDataBaseSongInfos(_Song.Artist, _Song.Title, out _Song.NumPlayed, out _Song.DateAdded, out _Song.DataBaseSongID);
//Before saving this tags to .txt: Check, if ArtistSorting and Artist are equal, then don't save this tag.
if (_Song.ArtistSorting == "")
if (String.IsNullOrEmpty(_Song.ArtistSorting))
_Song.ArtistSorting = _Song.Artist;
if (_Song.TitleSorting == "")
if (String.IsNullOrEmpty(_Song.TitleSorting))
_Song.TitleSorting = _Song.Title;
return true;
}
public bool ReadNotes()
private enum ENoteReadMode
{
return _ReadNotes();
Normal,
ZeroBased,
OneBased
}
private bool _ReadNotes(bool forceReload = false)
private class CAutoChanges
{
public int ZeroLengthNoteCt;
public int OverlapNoteCt;
public int NoTextNoteCt;
public int NoLengthBreakCt;
public int AjustedBreakCt;
public int InvalidPosBreakCt;
public bool IsModified
{
get { return ZeroLengthNoteCt + OverlapNoteCt + NoTextNoteCt + NoLengthBreakCt + AjustedBreakCt + InvalidPosBreakCt > 0; }
}
public override string ToString()
{
string result = "";
int skippedNotesCt = ZeroLengthNoteCt + OverlapNoteCt + NoTextNoteCt;
if (skippedNotesCt > 0)
result += "Skipped " + skippedNotesCt + " notes (0-Length: " + ZeroLengthNoteCt + ", Overlapping: " + OverlapNoteCt + ", No text: " + NoTextNoteCt + ")\r\n";
if (InvalidPosBreakCt > 0)
result += "Skipped " + InvalidPosBreakCt + " line breaks (Invalid position)\r\n";
int adjustedBreakCt = AjustedBreakCt + NoLengthBreakCt;
if (adjustedBreakCt > 0)
result += "Adjusted " + adjustedBreakCt + " line breaks (Overlapping previous note: " + AjustedBreakCt + ", No length: " + NoLengthBreakCt + ")\r\n";
return result;
}
}
private ENoteReadMode _CurrentReadMode = ENoteReadMode.Normal;
private const int _MaxZeroNoteCt = 1;
private const int _MaxOverlapNoteCt = 3;
/// <summary>
/// Read notes. First try to read notes normally (assume standard)<br/>
/// If there are more than _MaxZeroNoteCt with length &lt; 1, try to read notes adding 1 to length<br/>
/// Then if there are more than _MaxOverlapNoteCt fallback to first version ignoring notes with length &lt; 1
/// </summary>
/// <param name="forceReload"></param>
/// <returns></returns>
public bool ReadNotes(bool forceReload = false)
{
//Skip loading if already done and no reload is forced
if (_Song.NotesLoaded && !forceReload)
@@ -380,8 +422,8 @@ namespace VocaluxeLib.Songs
}
int currentBeat = 0; //Used for relative songs
int lastNoteEnd = 0;
bool endFound = false;
CSongNote lastNote = null; //Holds last parsed note. Get's reset on player change
bool endFound = false; // True if end tag was found
int player = 1;
_LineNr = 0;
@@ -389,6 +431,8 @@ namespace VocaluxeLib.Songs
char[] trimChars = {' ', ':'};
char[] splitChars = {' '};
var changesMade = new CAutoChanges();
StreamReader sr = null;
try
{
@@ -425,7 +469,7 @@ namespace VocaluxeLib.Songs
_LogError("Wrong or missing number after \"P\"");
return false;
}
sr.ReadLine();
lastNote = null;
break;
case ':':
case '*':
@@ -436,6 +480,7 @@ namespace VocaluxeLib.Songs
if (noteData.Length == 3)
{
_LogWarning("Ignored note without text");
changesMade.NoTextNoteCt++;
continue;
}
_LogError("Invalid note found");
@@ -453,10 +498,23 @@ namespace VocaluxeLib.Songs
if (text.Trim() == "")
{
_LogWarning("Ignored note without text");
changesMade.NoTextNoteCt++;
continue;
}
if (_CurrentReadMode == ENoteReadMode.ZeroBased)
length++;
if (length < 1)
{
changesMade.ZeroLengthNoteCt++;
if (_CurrentReadMode == ENoteReadMode.Normal && changesMade.ZeroLengthNoteCt > _MaxZeroNoteCt && changesMade.OverlapNoteCt <= _MaxOverlapNoteCt)
{
_LogWarning("Found more than " + _MaxZeroNoteCt + " note with length < 1. Trying alternative read mode.");
_CurrentReadMode = ENoteReadMode.ZeroBased;
sr.Dispose();
return ReadNotes(true);
}
_LogWarning("Ignored note with length < 1");
}
else
{
ENoteType noteType;
@@ -471,13 +529,30 @@ namespace VocaluxeLib.Songs
if (_Song.Relative)
beat += currentBeat;
bool ignored = false;
foreach (int curPlayer in player.GetSetBits())
{
if (!_ParseNote(curPlayer, noteType, beat, length, tone, text))
//Create the note here as we want independent instances in the lines. Otherwhise we can't modify them later
lastNote = new CSongNote(beat, length, tone, text, noteType);
if (!_AddNote(curPlayer, lastNote))
{
if (!ignored)
{
ignored = true;
changesMade.OverlapNoteCt++;
if (changesMade.OverlapNoteCt > _MaxOverlapNoteCt && _CurrentReadMode == ENoteReadMode.ZeroBased)
{
_LogWarning("Found more than " + _MaxOverlapNoteCt + " overlapping notes. Using standard mode.");
_CurrentReadMode = ENoteReadMode.OneBased;
sr.Dispose();
return ReadNotes(true);
}
}
_LogWarning("Ignored note for player " + (curPlayer + 1) + " because it overlaps with other note");
}
}
}
lastNoteEnd = beat + length;
break;
case '-':
string[] lineBreakData = line.Split(splitChars);
@@ -498,36 +573,51 @@ namespace VocaluxeLib.Songs
{
beat += currentBeat;
if (lineBreakData.Length < 2 || !int.TryParse(lineBreakData[1], out length))
{
_LogWarning("Missing line break length");
changesMade.NoLengthBreakCt++;
}
else
currentBeat += length;
}
if (beat < lastNoteEnd)
if (lastNote != null && beat < lastNote.EndBeat)
{
_LogWarning("Line break is before previous note end. Adjusted it (might not work for relative songs)");
beat = lastNoteEnd;
_LogWarning("Line break is before previous note end. Adjusted.");
changesMade.AjustedBreakCt++;
if (_Song.Relative)
currentBeat += lastNote.EndBeat - beat;
beat = lastNote.EndBeat;
}
if (beat < 1)
{
_LogWarning("Ignored line break because position is < 1");
changesMade.InvalidPosBreakCt++;
}
else
{
foreach (int curPlayer in player.GetSetBits())
{
if (_NewSentence(curPlayer, beat))
if (!_NewSentence(curPlayer, beat))
_LogWarning("Ignored line break for player " + (curPlayer + 1) + " (Overlapping or duplicate)");
}
}
break;
default:
_LogError("Error loading song. Unexpected or missing character (" + tag + ")");
_LogError("Unexpected or missing character (" + tag + ")");
return false;
}
}
foreach (CVoice voice in _Song.Notes.Voices)
for (int i = 0; i < _Song.Notes.VoiceCount; i++)
{
CVoice voice = _Song.Notes.GetVoice(i);
int emptyLines = voice.RemoveEmptyLines();
if (emptyLines > 0)
_LogWarning("Removed " + emptyLines + " empty lines from P" + ". This often indicates a problem with the line breaks in the file", false);
voice.UpdateTimings();
}
}
catch (Exception e)
{
@@ -550,12 +640,17 @@ namespace VocaluxeLib.Songs
_LogError("An unhandled exception occured (" + e.Message + ")", false);
return false;
}
if (changesMade.IsModified)
{
string msg = "Automatic changes have been made to " + filePath + " Please check result!\r\n" + changesMade;
CBase.Log.LogError("Warning:" + msg);
}
return true;
}
private bool _ParseNote(int player, ENoteType noteType, int start, int length, int tone, string text)
private bool _AddNote(int player, CSongNote note)
{
var note = new CSongNote(start, length, tone, text, noteType);
CVoice voice = _Song.Notes.GetVoice(player);
return voice.AddNote(note, false);
}
+5
View File
@@ -270,5 +270,10 @@ namespace VocaluxeLib.Songs
line.SetMedley(startBeat, endBeat);
}
#endregion Methods
public int RemoveEmptyLines()
{
return _Lines.RemoveAll(line => line.NoteCount == 0);
}
}
}