From 830875d24eb5ef46841e88510c04fd055e787d44 Mon Sep 17 00:00:00 2001 From: Alexander Eckart Date: Sun, 11 Mar 2012 15:22:18 +0100 Subject: [PATCH] added medley calculation --- Vocaluxe/Base/CSettings.cs | 2 + Vocaluxe/Lib/Song/CNotes.cs | 12 ++-- Vocaluxe/Lib/Song/CSong.cs | 92 +++++++++++++++++++++++++++ Vocaluxe/Menu/SingNotes/CSingNotes.cs | 10 +-- Vocaluxe/Screens/CScreenSing.cs | 38 +++++------ 5 files changed, 124 insertions(+), 30 deletions(-) diff --git a/Vocaluxe/Base/CSettings.cs b/Vocaluxe/Base/CSettings.cs index 5de5c61a..e75835b1 100644 --- a/Vocaluxe/Base/CSettings.cs +++ b/Vocaluxe/Base/CSettings.cs @@ -113,6 +113,8 @@ namespace Vocaluxe.Base public const float DefaultMedleyFadeInTime = 8f; public const float DefaultMedleyFadeOutTIme = 2f; + public const int MedleyMinSeriesLength = 3; + public const float MedleyMinDuration = 40f; public static bool TabNavigation = false; diff --git a/Vocaluxe/Lib/Song/CNotes.cs b/Vocaluxe/Lib/Song/CNotes.cs index d5ac4dab..0396c8da 100644 --- a/Vocaluxe/Lib/Song/CNotes.cs +++ b/Vocaluxe/Lib/Song/CNotes.cs @@ -298,7 +298,7 @@ namespace Vocaluxe.Lib.Song set { _PerfectLine = value; } } - public int FirstBeat + public int FirstNoteBeat { get { @@ -312,7 +312,7 @@ namespace Vocaluxe.Lib.Song } } - public int LastBeat + public int LastNoteBeat { get { @@ -509,15 +509,15 @@ namespace Vocaluxe.Lib.Song int startbeat = int.MaxValue; for (int i = 0; i < _Lines.Count; i++) { - if (_Lines[i].FirstBeat < startbeat) - startbeat = _Lines[i].FirstBeat; + if (_Lines[i].FirstNoteBeat < startbeat) + startbeat = _Lines[i].FirstNoteBeat; } int endbeat = int.MinValue; for (int i = 0; i < _Lines.Count; i++) { - if (_Lines[i].LastBeat < endbeat) - endbeat = _Lines[i].LastBeat; + if (_Lines[i].LastNoteBeat < endbeat) + endbeat = _Lines[i].LastNoteBeat; } int result = endbeat - startbeat; diff --git a/Vocaluxe/Lib/Song/CSong.cs b/Vocaluxe/Lib/Song/CSong.cs index 6ad4c2e5..3a728747 100644 --- a/Vocaluxe/Lib/Song/CSong.cs +++ b/Vocaluxe/Lib/Song/CSong.cs @@ -635,6 +635,13 @@ namespace Vocaluxe.Lib.Song } } + private struct Series + { + public int start; + public int end; + public int length; + } + private void FindRefrain() { if (this.Medley.Source == EMedleySource.Tag) @@ -643,10 +650,95 @@ namespace Vocaluxe.Lib.Song if (!this.CalculateMedley) return; + CLines lines = this.Notes.GetLines(0); + if (lines.LineCount == 0) + return; + // build sentences list + List sentences = new List(); + foreach (CLine line in lines.Line) + { + if (line.Points != 0) + sentences.Add(line.Lyrics); + else + sentences.Add(String.Empty); + } + // find equal sentences series + List series = new List(); + for (int i = 0; i < lines.LineCount - 1; i++) + { + for (int j = i + 1; j < lines.LineCount; j++) + { + if (sentences[i] == sentences[j] && sentences[i] != String.Empty) + { + Series tempSeries = new Series(); + tempSeries.start = i; + tempSeries.end = i; + int max = 0; + if (j + j - i - 1 > lines.LineCount - 1) + max = lines.LineCount - 1 - j; + else + max = j - i - 1; + + for (int k = 1; k <= max; k++) + { + if (sentences[i + k] == sentences[j + k] && sentences[i + k] != String.Empty) + tempSeries.end = i + k; + else + break; + } + + tempSeries.length = tempSeries.end - tempSeries.start + 1; + series.Add(tempSeries); + } + } + } + + // search for longest series + int longest = 0; + for (int i = 0; i < series.Count; i++) + { + if (series[i].length > series[longest].length) + longest = i; + } + + // set medley vars + if (series.Count > 0 && series[longest].length > CSettings.MedleyMinSeriesLength) + { + this.Medley.StartBeat = lines.Line[series[longest].start].FirstNoteBeat; + this.Medley.EndBeat = lines.Line[series[longest].end].LastNoteBeat; + + bool foundEnd = false; + + // set end if duration > MedleyMinDuration + if (CGame.GetTimeFromBeats(this.Medley.StartBeat, this.BPM) + CSettings.MedleyMinDuration > + CGame.GetTimeFromBeats(this.Medley.EndBeat, this.BPM)) + foundEnd = true; + + if (!foundEnd) + { + for (int i = series[longest].start + 1; i < lines.LineCount - 1; i++) + { + if (CGame.GetTimeFromBeats(this.Medley.StartBeat, this.BPM) + CSettings.MedleyMinDuration > + CGame.GetTimeFromBeats(lines.Line[i].LastNoteBeat, this.BPM)) + { + foundEnd = true; + this.Medley.EndBeat = lines.Line[i].LastNoteBeat; + } + } + } + + if (foundEnd) + { + this.Medley.Source = EMedleySource.Calculated; + this.Medley.FadeInTime = CSettings.DefaultMedleyFadeInTime; + this.Medley.FadeOutTime = CSettings.DefaultMedleyFadeOutTIme; + } + } + if (this.PreviewStart == 0f) { if (this.Medley.Source == EMedleySource.Calculated) diff --git a/Vocaluxe/Menu/SingNotes/CSingNotes.cs b/Vocaluxe/Menu/SingNotes/CSingNotes.cs index a157e9fa..aff8ca8b 100644 --- a/Vocaluxe/Menu/SingNotes/CSingNotes.cs +++ b/Vocaluxe/Menu/SingNotes/CSingNotes.cs @@ -304,7 +304,7 @@ namespace Vocaluxe.Menu.SingNotes float h = _PlayerNotes[n].Rect.H; float dh = h / CSettings.NumNoteLines * (2f - (int)CGame.Player[_PlayerNotes[n].PlayerNr].Difficulty) / 4f; - float beats = Line.LastBeat - Line.FirstBeat + 1; + float beats = Line.LastNoteBeat - Line.FirstNoteBeat + 1; if (beats == 0) return; @@ -324,7 +324,7 @@ namespace Vocaluxe.Menu.SingNotes float width = note.Duration / beats * w; SRectF rect = new SRectF( - _PlayerNotes[n].Rect.X + (note.StartBeat - Line.FirstBeat) / beats * w, + _PlayerNotes[n].Rect.X + (note.StartBeat - Line.FirstNoteBeat) / beats * w, _PlayerNotes[n].Rect.Y + (CSettings.NumNoteLines - 1 - (note.Tone - BaseLine)/2) / CSettings.NumNoteLines * h - dh, width, h / CSettings.NumNoteLines + 2 * dh, @@ -344,7 +344,7 @@ namespace Vocaluxe.Menu.SingNotes if (CConfig.DrawToneHelper == EOffOn.TR_CONFIG_ON) { - DrawToneHelper(n, (int)BaseLine, (CGame.MidBeatD - Line.FirstBeat) / beats * w); + DrawToneHelper(n, (int)BaseLine, (CGame.MidBeatD - Line.FirstNoteBeat) / beats * w); } int i = 0; @@ -377,7 +377,7 @@ namespace Vocaluxe.Menu.SingNotes foreach (CNote note in SingLine[CGame.Player[Player].CurrentLine].Notes) { - if (note.StartBeat >= Line.FirstBeat && note.EndBeat <= Line.LastBeat) + if (note.StartBeat >= Line.FirstNoteBeat && note.EndBeat <= Line.LastNoteBeat) { float width = note.Duration / beats * w; @@ -385,7 +385,7 @@ namespace Vocaluxe.Menu.SingNotes width -= (1 - (CGame.MidBeatD - CGame.ActBeatD)) / beats * w; SRectF rect = new SRectF( - _PlayerNotes[n].Rect.X + (note.StartBeat - Line.FirstBeat) / beats * w, + _PlayerNotes[n].Rect.X + (note.StartBeat - Line.FirstNoteBeat) / beats * w, _PlayerNotes[n].Rect.Y + (CSettings.NumNoteLines - 1 - (note.Tone - BaseLine)/2) / CSettings.NumNoteLines * h - dh, width, h / CSettings.NumNoteLines + 2 * dh, diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs index 415a7bd9..2577fa6d 100644 --- a/Vocaluxe/Screens/CScreenSing.cs +++ b/Vocaluxe/Screens/CScreenSing.cs @@ -588,7 +588,7 @@ namespace Vocaluxe.Screens { if (line[j].StartBeat <= _CurrentBeat) { - if (CGame.GetTimeFromBeats(line[j].FirstBeat, song.BPM) <= _CurrentTime - song.Gap + 10f) + if (CGame.GetTimeFromBeats(line[j].FirstNoteBeat, song.BPM) <= _CurrentTime - song.Gap + 10f) { nr = j; } @@ -607,8 +607,8 @@ namespace Vocaluxe.Screens { Lyrics[htLyrics(LyricMain)].SetLine(line[nr]); Lyrics[htLyrics(LyricMainTop)].SetLine(line[nr]); - _TimeToFirstNote = CGame.GetTimeFromBeats(line[nr].FirstBeat - line[nr].StartBeat, song.BPM); - _RemainingTimeToFirstNote = CGame.GetTimeFromBeats(line[nr].FirstBeat - CGame.GetBeatFromTime(_CurrentTime, song.BPM, song.Gap), song.BPM); + _TimeToFirstNote = CGame.GetTimeFromBeats(line[nr].FirstNoteBeat - line[nr].StartBeat, song.BPM); + _RemainingTimeToFirstNote = CGame.GetTimeFromBeats(line[nr].FirstNoteBeat - CGame.GetBeatFromTime(_CurrentTime, song.BPM, song.Gap), song.BPM); if (line.Length >= nr + 2) { @@ -624,8 +624,8 @@ namespace Vocaluxe.Screens if (i == 0 && song.IsDuet) { Lyrics[htLyrics(LyricMainDuet)].SetLine(line[nr]); - _TimeToFirstNoteDuet = CGame.GetTimeFromBeats(line[nr].FirstBeat - line[nr].StartBeat, song.BPM); - _RemainingTimeToFirstNoteDuet = CGame.GetTimeFromBeats(line[nr].FirstBeat - CGame.GetBeatFromTime(_CurrentTime, song.BPM, song.Gap), song.BPM); + _TimeToFirstNoteDuet = CGame.GetTimeFromBeats(line[nr].FirstNoteBeat - line[nr].StartBeat, song.BPM); + _RemainingTimeToFirstNoteDuet = CGame.GetTimeFromBeats(line[nr].FirstNoteBeat - CGame.GetBeatFromTime(_CurrentTime, song.BPM, song.Gap), song.BPM); if (line.Length >= nr + 2) Lyrics[htLyrics(LyricSubDuet)].SetLine(line[nr + 1]); @@ -857,7 +857,7 @@ namespace Vocaluxe.Screens { if (line[j].StartBeat <= _CurrentBeat) { - if (CGame.GetTimeFromBeats(line[j].FirstBeat, Song.BPM) <= _CurrentTime - Song.Gap + 10f) + if (CGame.GetTimeFromBeats(line[j].FirstNoteBeat, Song.BPM) <= _CurrentTime - Song.Gap + 10f) { CurrentLineSub = j; } @@ -868,7 +868,7 @@ namespace Vocaluxe.Screens int CurrentLine = 0; for (int j = 0; j < line.Length; j++) { - if (line[j].FirstBeat <= _CurrentBeat) + if (line[j].FirstNoteBeat <= _CurrentBeat) { CurrentLine = j; } @@ -879,33 +879,33 @@ namespace Vocaluxe.Screens Alpha[i * 2 + 1] = 1f; // main line alpha - if (CurrentLine == 0 && CurrentTime < CGame.GetTimeFromBeats(line[CurrentLine].FirstBeat, Song.BPM)) + if (CurrentLine == 0 && CurrentTime < CGame.GetTimeFromBeats(line[CurrentLine].FirstNoteBeat, Song.BPM)) { // first main line and fist note is not reached // => fade in - float diff = CGame.GetTimeFromBeats(line[CurrentLine].FirstBeat, Song.BPM) - CurrentTime; + float diff = CGame.GetTimeFromBeats(line[CurrentLine].FirstNoteBeat, Song.BPM) - CurrentTime; if (diff > dt) { Alpha[i * 2] = 1f - (diff - dt) / rt; } } - else if (CurrentLine < line.Length - 1 && CGame.GetTimeFromBeats(line[CurrentLine].LastBeat, Song.BPM) < CurrentTime && - CGame.GetTimeFromBeats(line[CurrentLine + 1].FirstBeat, Song.BPM) > CurrentTime) + else if (CurrentLine < line.Length - 1 && CGame.GetTimeFromBeats(line[CurrentLine].LastNoteBeat, Song.BPM) < CurrentTime && + CGame.GetTimeFromBeats(line[CurrentLine + 1].FirstNoteBeat, Song.BPM) > CurrentTime) { // current position is between two lines // time between the to lines - float diff = CGame.GetTimeFromBeats(line[CurrentLine + 1].FirstBeat, Song.BPM) - - CGame.GetTimeFromBeats(line[CurrentLine].LastBeat, Song.BPM); + float diff = CGame.GetTimeFromBeats(line[CurrentLine + 1].FirstNoteBeat, Song.BPM) - + CGame.GetTimeFromBeats(line[CurrentLine].LastNoteBeat, Song.BPM); // fade only if there is enough time for fading if (diff > 3.3f * dt) { // time elapsed since last line - float last = CurrentTime - CGame.GetTimeFromBeats(line[CurrentLine].LastBeat, Song.BPM); + float last = CurrentTime - CGame.GetTimeFromBeats(line[CurrentLine].LastNoteBeat, Song.BPM); // time to next line - float next = CGame.GetTimeFromBeats(line[CurrentLine + 1].FirstBeat, Song.BPM) - CurrentTime; + float next = CGame.GetTimeFromBeats(line[CurrentLine + 1].FirstNoteBeat, Song.BPM) - CurrentTime; if (last < next) { @@ -920,11 +920,11 @@ namespace Vocaluxe.Screens } } } - else if (CurrentLine == line.Length - 1 && CGame.GetTimeFromBeats(line[CurrentLine].LastBeat, Song.BPM) < CurrentTime) + else if (CurrentLine == line.Length - 1 && CGame.GetTimeFromBeats(line[CurrentLine].LastNoteBeat, Song.BPM) < CurrentTime) { // last main line and last note was reached // => fade out - float diff = CurrentTime - CGame.GetTimeFromBeats(line[CurrentLine].LastBeat, Song.BPM); + float diff = CurrentTime - CGame.GetTimeFromBeats(line[CurrentLine].LastNoteBeat, Song.BPM); Alpha[i * 2] = 1f - diff / rt; } @@ -932,7 +932,7 @@ namespace Vocaluxe.Screens if (CurrentLineSub < line.Length - 2) { float diff = 0f; - diff = CGame.GetTimeFromBeats(line[CurrentLineSub + 1].FirstBeat, Song.BPM) - CurrentTime; + diff = CGame.GetTimeFromBeats(line[CurrentLineSub + 1].FirstNoteBeat, Song.BPM) - CurrentTime; if (diff > dt) { @@ -1088,7 +1088,7 @@ namespace Vocaluxe.Screens CLine[] Line = Lines[i].Line; for(int j = 0; j