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);