diff --git a/Output/Languages/en.xml b/Output/Languages/en.xml
index e7867944..e3fd4cbe 100644
--- a/Output/Languages/en.xml
+++ b/Output/Languages/en.xml
@@ -22,6 +22,7 @@
Short version
Normal
Instrumental
+ Instrumental/Vocals
Karaoke
Karaoke
Vocal Hero
@@ -148,6 +149,10 @@
Sing medley-songs
New playlist
Song Options
+ Song length
+ Audio mode
+ Playlist
+ Player selection
Show player selection
Skip player selection
Search:
@@ -171,6 +176,7 @@
Skip this song
Restart round
Restart game
+ Vocals track volume
No more songs in playlist!
No webcam available!
Aspect Ratio: %a
diff --git a/Output/Themes/Changelog/Changelog_ScreenSing.txt b/Output/Themes/Changelog/Changelog_ScreenSing.txt
index 3bd4bd87..bf9b04e2 100644
--- a/Output/Themes/Changelog/Changelog_ScreenSing.txt
+++ b/Output/Themes/Changelog/Changelog_ScreenSing.txt
@@ -1,4 +1,11 @@
ScreenSing
++++++++++
+Version 13
+
+Add:
+
+
+
+++++++++
Version 12
@@ -84,4 +91,4 @@ or
, , ,
to Lyric-Elements.
This option set the color of highlighting lyrics.
-++++++++++
\ No newline at end of file
+++++++++++
diff --git a/Output/Themes/Changelog/Changelog_ScreenSong.txt b/Output/Themes/Changelog/Changelog_ScreenSong.txt
index 2f9fa47d..4c4cec95 100644
--- a/Output/Themes/Changelog/Changelog_ScreenSong.txt
+++ b/Output/Themes/Changelog/Changelog_ScreenSong.txt
@@ -1,5 +1,17 @@
ScreenSong
+++++++++++
+Version 13:
+
+Headers for Song Options
+
+Add:
+
+
+
+
+
+
++++++++++
Version 12:
diff --git a/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml b/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml
index 67d44f8a..37bedd77 100644
--- a/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml
+++ b/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml
@@ -2,7 +2,7 @@
ScreenSing
- 11
+ 13
@@ -708,6 +708,20 @@
Normal
+
+ 217.5
+ 818
+ -2.11
+ 40.5
+ 520
+
+
+ Left
+ Center
+
+ Outline
+ TR_SCREENSING_VOCALSVOLUME
+
15
82.5
@@ -1582,7 +1596,50 @@
-
+
+
+
+ SelectSlideArrowLeft
+ SelectSlideArrowRight
+ SelectSlide
+ SelectSlideArrowLeft
+ SelectSlideArrowRight
+
+ 752
+ 820
+ 958
+ 40
+ -2.11
+
+
+ 757.5
+ 822.5
+ 35
+ 35
+ -2.11
+
+
+ 1667.5
+ 822.5
+ 35
+ 35
+ -2.11
+
+
+
+
+
+
+
+ 40.5
+ 75
+ 0
+ 300
+ Outline
+ Bold
+ 5
+
+
NoteLeft
diff --git a/Output/Themes/Vocaluxe 2024/Screens/ScreenSong.xml b/Output/Themes/Vocaluxe 2024/Screens/ScreenSong.xml
index 91ea24bd..2f180605 100644
--- a/Output/Themes/Vocaluxe 2024/Screens/ScreenSong.xml
+++ b/Output/Themes/Vocaluxe 2024/Screens/ScreenSong.xml
@@ -2,7 +2,7 @@
ScreenSong
- 12
+ 13
@@ -253,7 +253,7 @@
330
60
-2.11
- 45
+ 40
525
@@ -263,6 +263,62 @@
Outline
TR_SCREENSONG_SONGOPTIONS
+
+ 330
+ 155
+ -2.11
+ 30
+ 525
+
+
+ Center
+ Center
+
+ Outline
+ TR_SCREENSONG_LENGTH
+
+
+ 330
+ 230
+ -2.11
+ 30
+ 525
+
+
+ Center
+ Center
+
+ Outline
+ TR_SCREENSONG_AUDIOMODE
+
+
+ 330
+ 305
+ -2.11
+ 30
+ 525
+
+
+ Center
+ Center
+
+ Outline
+ TR_SCREENSONG_PLAYERSELECT
+
+
+ 330
+ 380
+ -2.11
+ 30
+ 525
+
+
+ Center
+ Center
+
+ Outline
+ TR_SCREENSONG_PLAYLIST
+
60
1050
@@ -486,16 +542,16 @@
SongSelectButton
60
- 546
+ 554
540
- 53
+ 45
-2.11
270
- 10.5
+ 2
0
37.5
525
@@ -513,18 +569,18 @@
SongSelectButton
60
- 415
+ 451
540
- 53
+ 35
-2.11
270
- 10.5
+ 2
0
- 37.5
+ 35
525
@@ -542,14 +598,14 @@
60
104
540
- 57
+ 45
-2.11
270
- 10.5
+ 3
0
37.5
525
@@ -818,16 +874,16 @@
SongSelectButton
60
- 486.5
+ 497.5
540
- 53
+ 45
-2.11
270
- 10.5
+ 2
0
37.5
525
@@ -907,7 +963,7 @@
586.5
- 735
+ 743
-11
42
150
@@ -1176,23 +1232,23 @@
SelectSlideArrowRight
60
- 167.5
+ 186
540
- 53
+ 35
-2.11
67.5
- 172.5
- 45
- 45
+ 188,5
+ 30
+ 30
-2.12
- 547.5
- 172.5
- 45
- 45
+ 560
+ 188,5
+ 30
+ 30
-2.12
@@ -1201,7 +1257,7 @@
- 37.5
+ 35
75
0
420
@@ -1218,23 +1274,23 @@
SelectSlideArrowRight
60
- 286
+ 336
540
- 53
+ 35
-2.11
67.5
- 291
- 45
- 45
+ 338.5
+ 30
+ 30
-2.12
- 547.5
- 291
- 45
- 45
+ 560
+ 338.5
+ 30
+ 30
-2.12
@@ -1243,7 +1299,7 @@
- 37.5
+ 35
175
0
420
@@ -1260,23 +1316,23 @@
SelectSlideArrowRight
60
- 227
+ 261
540
- 53
+ 35
-2.11
67.5
- 232
- 45
- 45
+ 263.5
+ 30
+ 30
-2.12
- 547.5
- 232
- 45
- 45
+ 560
+ 263.5
+ 30
+ 30
-2.12
@@ -1285,7 +1341,7 @@
- 37.5
+ 35
75
0
420
@@ -1302,23 +1358,23 @@
SelectSlideArrowRight
60
- 355.5
+ 411
540
- 53
+ 35
-2.11
67.5
- 360.5
- 45
- 45
+ 413.5
+ 30
+ 30
-2.12
- 547.5
- 360.5
- 45
- 45
+ 560
+ 413.5
+ 30
+ 30
-2.12
@@ -1327,7 +1383,7 @@
- 37.5
+ 35
75
0
420
diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs
index 6776c58f..91683de0 100644
--- a/Vocaluxe/Base/CConfig.cs
+++ b/Vocaluxe/Base/CConfig.cs
@@ -153,6 +153,8 @@ namespace Vocaluxe.Base
public int GameMusicVolume;
[XmlRanged(0, 100), DefaultValue(80)]
public int SoundEffectVolume;
+ [XmlRanged(0, 100), DefaultValue(50)]
+ public int VocalsVolume;
[DefaultValue(EOffOn.TR_CONFIG_OFF)]
public EOffOn KaraokeEffect;
[XmlRanged(0, 1), DefaultValue(1.0f)]
@@ -338,6 +340,16 @@ namespace Vocaluxe.Base
}
}
+ public static int VocalsVolume
+ {
+ get { return Config.Sound.VocalsVolume; }
+ set
+ {
+ Config.Sound.VocalsVolume = value.Clamp(0, 100);
+ SaveConfig();
+ }
+ }
+
public static int PreviewMusicVolume
{
get { return Config.Sound.PreviewMusicVolume; }
@@ -511,6 +523,8 @@ namespace Vocaluxe.Base
return "Game Volume from 0 to 100";
case "SoundEffectVolume":
return "Sound Effect Volume from 0 to 100";
+ case "VocalsVolume":
+ return "Vocals Volume from 0 to 100";
case "KaraokeEffect":
return "Apply a karaoke effect to song playback (EPlaybackLib.GstreamerSharp only)";
case "KaraokeEffectLevel":
diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs
index b9c2231a..929dd37b 100644
--- a/Vocaluxe/Screens/CScreenSing.cs
+++ b/Vocaluxe/Screens/CScreenSing.cs
@@ -41,7 +41,7 @@ namespace Vocaluxe.Screens
// Version number for theme files. Increment it, if you've changed something on the theme files!
protected override int _ScreenVersion
{
- get { return 12; }
+ get { return 13; }
}
private struct STimeRect
@@ -58,6 +58,7 @@ namespace Vocaluxe.Screens
private const string _TextDuetName2 = "TextDuetName2";
private const string _TextMedleyCountdown = "TextMedleyCountdown";
private const string _TextPauseSongName = "TextPauseSongName";
+ private const string _TextPauseVocalsVolume = "TextPauseVocalsVolume";
private string[,,] _TextScores;
private string[,,] _TextNames;
private List _TextsPause;
@@ -89,6 +90,9 @@ namespace Vocaluxe.Screens
private const string _ButtonRestartGame = "ButtonRestartGame";
private const string _ButtonSkip = "ButtonSkip";
+ private const string _SelectSlidePauseVocalsVolume = "SelectSlidePauseVocalsVolume";
+ private List _SelectSlidesPause;
+
private const string _LyricMain = "LyricMain";
private const string _LyricSub = "LyricSub";
private const string _LyricMainDuet = "LyricMainDuet";
@@ -116,6 +120,7 @@ namespace Vocaluxe.Screens
private int _CurrentBeat;
private int _CurrentStream = -1;
+ private int _CurrentStreamVocals = -1;
private float _Length = -1f;
private CVideoStream _CurrentVideo;
@@ -125,6 +130,8 @@ namespace Vocaluxe.Screens
private float _CurrentTime;
private float _FinishTime;
+
+ private float _PausePosition;
private float _TimeToFirstNote;
private float _RemainingTimeToFirstNote;
@@ -193,6 +200,7 @@ namespace Vocaluxe.Screens
_ThemeButtons = new string[] { _ButtonCancel, _ButtonContinue, _ButtonRestartGame, _ButtonRestartRound, _ButtonSkip };
_ThemeLyrics = new string[] { _LyricMain, _LyricSub, _LyricMainDuet, _LyricSubDuet, _LyricMainTop, _LyricSubTop };
_ThemeSingNotes = new string[] { _SingBars };
+ _ThemeSelectSlides = new string[] { _SelectSlidePauseVocalsVolume };
_TimeRects = new List();
_TimerSongText = new Stopwatch();
@@ -225,6 +233,11 @@ namespace Vocaluxe.Screens
_StaticsPause = new List();
_TextsPause = new List();
+ _SelectSlidesPause = new List();
+
+ _SelectSlides[_SelectSlidePauseVocalsVolume].AddValues(new string[]
+ {"0", "5", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "60", "65", "70", "75", "80", "85", "90", "95", "100"});
+ _SelectSlides[_SelectSlidePauseVocalsVolume].Selection = CConfig.VocalsVolume / 5;
//Automatically find statics and texts with pause prefix
foreach (CStatic s in _Statics.Where(s => s.ThemeLoaded && s.GetThemeName().StartsWith("StaticPause")))
@@ -232,6 +245,9 @@ namespace Vocaluxe.Screens
foreach (CText t in _Texts.Where(s => s.ThemeLoaded && s.GetThemeName().StartsWith("TextPause")))
_TextsPause.Add(t.GetThemeName());
+
+ foreach (CText t in _Texts.Where(s => s.ThemeLoaded && s.GetThemeName().StartsWith("SelectSlidePause")))
+ _SelectSlidesPause.Add(t.GetThemeName());
}
public override bool HandleInput(SKeyEvent keyEvent)
@@ -365,6 +381,11 @@ namespace Vocaluxe.Screens
if (CSound.GetLength(_CurrentStream) < newTime)
newTime = CSound.GetLength(_CurrentStream) - 1f;
CSound.SetPosition(_CurrentStream, newTime);
+
+ if (CScreenSong.GetAudioMode() == EAudioMode.TR_AUDIOMODE_VOCALS)
+ {
+ CSound.SetPosition(_CurrentStreamVocals, newTime);
+ }
_ShowInfoText(CBase.Language.Translate("TR_SCREENSING_SKIPPEDSECONDS").Replace("%s", (keyEvent.Mod == EModifier.Shift ? "10" : "30")));
}
@@ -1070,6 +1091,12 @@ namespace Vocaluxe.Screens
{
_PrepareTimeLine();
CSound.Play(_CurrentStream);
+
+ if (CScreenSong.GetAudioMode() == EAudioMode.TR_AUDIOMODE_VOCALS)
+ {
+ CSound.Play(_CurrentStreamVocals);
+ }
+
CRecord.Start();
if (_Webcam)
CWebcam.Start();
@@ -1175,11 +1202,17 @@ namespace Vocaluxe.Screens
foreach (String s in _TextsPause)
_Texts[s].Visible = _Pause;
+ foreach (String s in _SelectSlidesPause)
+ _SelectSlides[s].Visible = _Pause;
+
_Buttons[_ButtonCancel].Visible = _Pause;
_Buttons[_ButtonContinue].Visible = _Pause;
_Buttons[_ButtonSkip].Visible = _Pause && CGame.NumRounds > CGame.RoundNr && CGame.NumRounds > 1;
_Buttons[_ButtonRestartGame].Visible = _Pause;
_Buttons[_ButtonRestartRound].Visible = _Pause && CGame.NumRounds > 1;
+
+ _SelectSlides[_SelectSlidePauseVocalsVolume].Visible = _Pause && (CScreenSong.GetAudioMode() == EAudioMode.TR_AUDIOMODE_VOCALS);
+ _Texts[_TextPauseVocalsVolume].Visible = _Pause && (CScreenSong.GetAudioMode() == EAudioMode.TR_AUDIOMODE_VOCALS);
if (_Pause && _TimerSongText.IsRunning)
_TimerSongText.Stop();
@@ -1188,10 +1221,35 @@ namespace Vocaluxe.Screens
_Texts[_TextSongName].Visible = !_Pause;
- if (_Pause)
- CSound.Pause(_CurrentStream);
+ if (CScreenSong.GetAudioMode() == EAudioMode.TR_AUDIOMODE_VOCALS)
+ {
+ if (_Pause)
+ {
+ // Store current position before pausing
+ _PausePosition = CSound.GetPosition(_CurrentStream);
+ CSound.Pause(_CurrentStream);
+ CSound.Pause(_CurrentStreamVocals);
+ }
+ else
+ {
+ // Reset both streams to stored position to keep them in sync and update vocals volume
+ CConfig.VocalsVolume = _SelectSlides[_SelectSlidePauseVocalsVolume].Selection * 5;
+ CConfig.SaveConfig();
+ CSound.SetStreamVolume(_CurrentStreamVocals, CConfig.VocalsVolume);
+ CSound.SetPosition(_CurrentStream, _PausePosition);
+ CSound.SetPosition(_CurrentStreamVocals, _PausePosition);
+ // Start both streams simultaneously
+ CSound.Play(_CurrentStream);
+ CSound.Play(_CurrentStreamVocals);
+ }
+ }
else
- CSound.Play(_CurrentStream);
+ {
+ if (_Pause)
+ CSound.Pause(_CurrentStream);
+ else
+ CSound.Play(_CurrentStream);
+ }
}
#endregion
@@ -1229,6 +1287,13 @@ namespace Vocaluxe.Screens
{
_CurrentStream = CSound.Load(song.GetInstrumental(), false, true, EAudioEffect.None);
}
+ else if (CScreenSong.GetAudioMode() == EAudioMode.TR_AUDIOMODE_VOCALS)
+ {
+ _CurrentStream = CSound.Load(song.GetInstrumental(), false, true, EAudioEffect.None);
+ _CurrentStreamVocals = CSound.Load(song.GetVocals(), false, true, EAudioEffect.None);
+ CSound.SetStreamVolume(_CurrentStreamVocals, CConfig.VocalsVolume);
+ CSound.SetPosition(_CurrentStreamVocals, song.Start);
+ }
else
{
_CurrentStream = CSound.Load(song.GetMP3(), false, true, CConfig.Config.Sound.KaraokeEffect == EOffOn.TR_CONFIG_ON ? EAudioEffect.Karaoke : EAudioEffect.None);
@@ -1341,7 +1406,9 @@ namespace Vocaluxe.Screens
if (_CurrentStream > -1)
{
CSound.FadeAndClose(_CurrentStream, 0, 0.5f);
+ CSound.FadeAndClose(_CurrentStreamVocals, 0, 0.5f);
_CurrentStream = -1;
+ _CurrentStreamVocals = -1;
}
CRecord.Stop();
if (_CurrentVideo != null)
diff --git a/Vocaluxe/Screens/CScreenSong.cs b/Vocaluxe/Screens/CScreenSong.cs
index e34f2a03..36854a72 100644
--- a/Vocaluxe/Screens/CScreenSong.cs
+++ b/Vocaluxe/Screens/CScreenSong.cs
@@ -43,7 +43,7 @@ namespace Vocaluxe.Screens
// Version number for theme files. Increment it, if you've changed something on the theme files!
protected override int _ScreenVersion
{
- get { return 12; }
+ get { return 13; }
}
private const string _TextCategory = "TextCategory";
@@ -54,6 +54,10 @@ namespace Vocaluxe.Screens
private const string _TextHelpBarSearch = "TextHelpBarSearch";
private const string _TextHelpBarParty = "TextHelpBarParty";
private const string _TextOptionsTitle = "TextOptionsTitle";
+ private const string _TextOptionsLength = "TextOptionsLength";
+ private const string _TextOptionsAudioMode = "TextOptionsAudioMode";
+ private const string _TextOptionsPlayerSelect = "TextOptionsPlayerSelect";
+ private const string _TextOptionsPlaylist = "TextOptionsPlaylist";
private const string _TextShortInfoTop = "TextShortInfoTop";
private const string _ButtonOpenOptions = "ButtonOpenOptions";
@@ -179,6 +183,11 @@ namespace Vocaluxe.Screens
tlist.Add(_TextHelpBarSearch);
tlist.Add(_TextHelpBarParty);
tlist.Add(_TextOptionsTitle);
+ tlist.Add(_TextOptionsLength);
+ tlist.Add(_TextOptionsAudioMode);
+ tlist.Add(_TextOptionsPlayerSelect);
+ tlist.Add(_TextOptionsPlaylist);
+
tlist.Add(_TextShortInfoTop);
_ThemeStatics = new string[] {_StaticSearchBar, _StaticOptionsBG, _StaticShortInfoTop};
@@ -1030,7 +1039,7 @@ namespace Vocaluxe.Screens
else
gm = CSongs.VisibleSongs[songNr].IsDuet ? EGameMode.TR_GAMEMODE_DUET : EGameMode.TR_GAMEMODE_NORMAL;
- _AudioMode = (EAudioMode)_SelectSlides[_SelectSlideOptionsAudioMode].Selection;
+ _AudioMode = (EAudioMode)_SelectSlides[_SelectSlideOptionsAudioMode].SelectedTag;
_PlayerSelect = (EPlayerSelect)_SelectSlides[_SelectSlideOptionsPlayerSelect].Selection;
CGame.Reset();
@@ -1409,6 +1418,10 @@ namespace Vocaluxe.Screens
_Buttons[_ButtonOptionsStartMedley].Visible = false;
_Buttons[_ButtonOptionsHighscore].Visible = false;
_Texts[_TextOptionsTitle].Visible = false;
+ _Texts[_TextOptionsLength].Visible = false;
+ _Texts[_TextOptionsAudioMode].Visible = false;
+ _Texts[_TextOptionsPlayerSelect].Visible = false;
+ _Texts[_TextOptionsPlaylist].Visible = false;
_Statics[_StaticOptionsBG].Visible = false;
_Buttons[_ButtonOpenOptions].Visible = true;
@@ -1426,6 +1439,9 @@ namespace Vocaluxe.Screens
_UpdatePlaylistNames();
_Texts[_TextOptionsTitle].Visible = true;
+ _Texts[_TextOptionsLength].Visible = true;
+ _Texts[_TextOptionsPlayerSelect].Visible = true;
+ _Texts[_TextOptionsPlaylist].Visible = true;
_Buttons[_ButtonOptionsClose].Visible = true;
_Statics[_StaticOptionsBG].Visible = true;
_Buttons[_ButtonOpenOptions].Visible = false;
@@ -1463,17 +1479,27 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlideOptionsAudioMode].Clear();
CSong currentSong = CSongs.VisibleSongs[_SongMenu.GetPreviewSongNr()];
+
if (currentSong.HasInstrumental())
{
- _SelectSlides[_SelectSlideOptionsAudioMode].AddValue("TR_AUDIOMODE_NORMAL");
- _SelectSlides[_SelectSlideOptionsAudioMode].AddValue("TR_AUDIOMODE_INSTRUMENTAL");
- _SelectSlides[_SelectSlideOptionsAudioMode].AddValue("TR_AUDIOMODE_KARAOKE");
- _SelectSlides[_SelectSlideOptionsAudioMode].Visible = true;
+ _SelectSlides[_SelectSlideOptionsAudioMode].AddValue("TR_AUDIOMODE_NORMAL", tag: (int)EAudioMode.TR_AUDIOMODE_NORMAL);
+ _SelectSlides[_SelectSlideOptionsAudioMode].AddValue("TR_AUDIOMODE_INSTRUMENTAL", tag: (int)EAudioMode.TR_AUDIOMODE_INSTRUMENTAL);
+
+ if (currentSong.HasVocals())
+ {
+ _SelectSlides[_SelectSlideOptionsAudioMode].AddValue("TR_AUDIOMODE_VOCALS", tag: (int)EAudioMode.TR_AUDIOMODE_VOCALS);
+ }
+
+ _SelectSlides[_SelectSlideOptionsAudioMode].AddValue("TR_AUDIOMODE_KARAOKE", tag: (int)EAudioMode.TR_AUDIOMODE_KARAOKE);
+ _SelectSlides[_SelectSlideOptionsAudioMode].Visible = true;
+ _Texts[_TextOptionsAudioMode].Visible = true;
}
else
{
_SelectSlides[_SelectSlideOptionsAudioMode].Visible = false;
+ _Texts[_TextOptionsAudioMode].Visible = false;
}
+
_SelectSlides[_SelectSlideOptionsAudioMode].Selection = (int)_AudioMode;
_SelectSlides[_SelectSlideOptionsPlayerSelect].Clear();
diff --git a/VocaluxeLib/Enums.cs b/VocaluxeLib/Enums.cs
index 378137aa..8f9c3409 100644
--- a/VocaluxeLib/Enums.cs
+++ b/VocaluxeLib/Enums.cs
@@ -368,6 +368,7 @@ namespace VocaluxeLib
{
TR_AUDIOMODE_NORMAL,
TR_AUDIOMODE_INSTRUMENTAL,
+ TR_AUDIOMODE_VOCALS,
TR_AUDIOMODE_KARAOKE
}
diff --git a/VocaluxeLib/Songs/CSong.cs b/VocaluxeLib/Songs/CSong.cs
index 1c49c13b..66fe5061 100644
--- a/VocaluxeLib/Songs/CSong.cs
+++ b/VocaluxeLib/Songs/CSong.cs
@@ -1,4 +1,4 @@
-#region license
+#region license
// This file is part of Vocaluxe.
//
// Vocaluxe is free software: you can redistribute it and/or modify
@@ -339,6 +339,11 @@ namespace VocaluxeLib.Songs
return Path.Combine(Folder, VocalsFileName);
}
+ public bool HasVocals()
+ {
+ return !string.IsNullOrEmpty(VocalsFileName);
+ }
+
public string GetVideo()
{
return Path.Combine(Folder, VideoFileName);