diff --git a/Output/Languages/Spanish.xml b/Output/Languages/Spanish.xml index f9f92cff..d304e24c 100644 --- a/Output/Languages/Spanish.xml +++ b/Output/Languages/Spanish.xml @@ -55,7 +55,7 @@ Lista Dreidel - TileBoard + CuadrĂ­cula Libro SegĂșn Sean Necesarias diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs index 1aad119c..74c13ce6 100644 --- a/Vocaluxe/Base/CConfig.cs +++ b/Vocaluxe/Base/CConfig.cs @@ -66,6 +66,19 @@ namespace Vocaluxe.Base TR_CONFIG_LEVEL_MAX //all debug infos } + public enum EBufferSize + { + b0 = 0, + b512 = 512, + b1024 = 1024, + b1536 = 1536, + b2048 = 2048, + b2560 = 2560, + b3072 = 3072, + b3584 = 3584, + b4096 = 4096 + } + public enum EPlaybackLib { PortAudio, @@ -177,7 +190,8 @@ namespace Vocaluxe.Base // Sound public static EPlaybackLib PlayBackLib = EPlaybackLib.PortAudio; public static ERecordLib RecordLib = ERecordLib.PortAudio; - public static uint PortAudioBufferSize = 1024; + public static EBufferSize AudioBufferSize = EBufferSize.b2048; + public static int AudioLatency = 100; public static int BackgroundMusicVolume = 50; public static EOffOn BackgroundMusic = EOffOn.TR_CONFIG_ON; public static EBackgroundMusicSource BackgroundMusicSource = EBackgroundMusicSource.TR_CONFIG_NO_OWN_MUSIC; @@ -286,6 +300,14 @@ namespace Vocaluxe.Base #region Sound CHelper.TryGetEnumValueFromXML("//root/Sound/PlayBackLib", navigator, ref PlayBackLib); CHelper.TryGetEnumValueFromXML("//root/Sound/RecordLib", navigator, ref RecordLib); + CHelper.TryGetEnumValueFromXML("//root/Sound/AudioBufferSize", navigator, ref AudioBufferSize); + + CHelper.TryGetIntValueFromXML("//root/Sound/AudioLatency", navigator, ref AudioLatency); + if (AudioLatency < -500) + AudioLatency = -500; + if (AudioLatency > 500) + AudioLatency = 500; + CHelper.TryGetEnumValueFromXML("//root/Sound/BackgroundMusic", navigator, ref BackgroundMusic); CHelper.TryGetIntValueFromXML("//root/Sound/BackgroundMusicVolume", navigator, ref BackgroundMusicVolume); CHelper.TryGetEnumValueFromXML("//root/Sound/BackgroundMusicSource", navigator, ref BackgroundMusicSource); @@ -480,6 +502,12 @@ namespace Vocaluxe.Base writer.WriteComment("RecordLib: " + ListStrings(Enum.GetNames(typeof(ERecordLib)))); writer.WriteElementString("RecordLib", Enum.GetName(typeof(ERecordLib), RecordLib)); + writer.WriteComment("AudioBufferSize: " + ListStrings(Enum.GetNames(typeof(EBufferSize)))); + writer.WriteElementString("AudioBufferSize", Enum.GetName(typeof(EBufferSize), AudioBufferSize)); + + writer.WriteComment("AudioLatency from -500 to 500 ms"); + writer.WriteElementString("AudioLatency", AudioLatency.ToString()); + writer.WriteComment("Background Music"); writer.WriteElementString("BackgroundMusicEnabled", Enum.GetName(typeof(EOffOn), BackgroundMusic)); diff --git a/Vocaluxe/Base/CSettings.cs b/Vocaluxe/Base/CSettings.cs index a1aa2db7..b7d0ed09 100644 --- a/Vocaluxe/Base/CSettings.cs +++ b/Vocaluxe/Base/CSettings.cs @@ -47,7 +47,7 @@ namespace Vocaluxe.Base public const int iVersionSub = 0; // steps public const ERevision VersionRevision = ERevision.Beta; - public const int iBuild = 53; // Increase on every published version! Never Reset! + public const int iBuild = 54; // Increase on every published version! Never Reset! public const int iDatabaseHighscoreVersion = 1; public const int iDatabaseCoverVersion = 1; diff --git a/Vocaluxe/Base/CSound.cs b/Vocaluxe/Base/CSound.cs index b201e6fb..2a2f9d0f 100644 --- a/Vocaluxe/Base/CSound.cs +++ b/Vocaluxe/Base/CSound.cs @@ -501,7 +501,7 @@ namespace Vocaluxe.Base long ticks = _Timer.ElapsedTicks; float dt = _Timer.ElapsedMilliseconds / 1000f; - if (nanosecPerTick > 0L) + if (Stopwatch.IsHighResolution) dt = (float)(ticks * nanosecPerTick / 1000000000.0); return _SetValue + dt; @@ -581,7 +581,7 @@ namespace Vocaluxe.Base long ticks = _STimer.ElapsedTicks; float dt = _STimer.ElapsedMilliseconds / 1000f; - if (nanosecPerTick > 0L) + if (Stopwatch.IsHighResolution) dt = (float)(ticks * nanosecPerTick / 1000000000.0); return _CurrentTime + dt; @@ -617,9 +617,9 @@ namespace Vocaluxe.Base long ticks = _STimer.ElapsedTicks; float dt = _STimer.ElapsedMilliseconds / 1000f; - if (nanosecPerTick > 0L) + if (Stopwatch.IsHighResolution) dt = (float)(ticks * nanosecPerTick / 1000000000.0); - + float Ts = 0f; if (dt > 0) Ts = 1 / (_T / dt + 1); diff --git a/Vocaluxe/Lib/Sound/CPortAudioPlay.cs b/Vocaluxe/Lib/Sound/CPortAudioPlay.cs index d39c6942..43623c5c 100644 --- a/Vocaluxe/Lib/Sound/CPortAudioPlay.cs +++ b/Vocaluxe/Lib/Sound/CPortAudioPlay.cs @@ -620,7 +620,7 @@ namespace Vocaluxe.Lib.Sound IntPtr.Zero, ref outputParams, format.SamplesPerSecond, - 0,//CConfig.PortAudioBufferSize, + (uint)CConfig.AudioBufferSize, PortAudio.PaStreamFlags.paNoFlag, _paStreamCallback, data)); @@ -844,10 +844,10 @@ namespace Vocaluxe.Lib.Sound else _waiting = true; - float latency = buf.Length / _BytesPerSecond; + float latency = buf.Length / _BytesPerSecond + CConfig.AudioLatency/1000f; float time = _TimeCode - _data.BytesNotRead / _BytesPerSecond - latency; - _CurrentTime = _SyncTimer.Update(time); + _CurrentTime = time; // _SyncTimer.Update(time); } try @@ -856,7 +856,7 @@ namespace Vocaluxe.Lib.Sound } catch (Exception e) { - Console.WriteLine(e.ToString()); + CLog.LogError("Error PortAudio.StreamCallback: " + e.Message); } return PortAudio.PaStreamCallbackResult.paContinue; diff --git a/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs b/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs index e6031786..6b566e39 100644 --- a/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs +++ b/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs @@ -260,7 +260,6 @@ namespace Vocaluxe.Lib.Video AutoResetEvent EventDecode = new AutoResetEvent(false); SFrameBuffer[] _FrameBuffer = new SFrameBuffer[5]; Object MutexFramebuffer = new Object(); - Object MutexFrame = new Object(); Object MutexSyncSignals = new Object(); public Decoder() @@ -595,17 +594,13 @@ namespace Vocaluxe.Lib.Video if (!_BeforeLoop && (!DropFrame || FrameFinished != 0)) { - lock (MutexFrame) + try { - try - { - FrameFinished = CAcinerella.ac_get_frame(_instance, _videodecoder); - } - catch (Exception) - { - CLog.LogError("Error AcGetFrame " + _FileName); - } - + FrameFinished = CAcinerella.ac_get_frame(_instance, _videodecoder); + } + catch (Exception) + { + CLog.LogError("Error AcGetFrame " + _FileName); } } @@ -673,23 +668,18 @@ namespace Vocaluxe.Lib.Video _waiting = true; else { + TAc_decoder Videodecoder = (TAc_decoder)Marshal.PtrToStructure(_videodecoder, typeof(TAc_decoder)); - lock (MutexFrame) + _VideoTime = (float)Videodecoder.timecode; + _FrameBuffer[num].time = _VideoTime; + + if (Videodecoder.buffer != IntPtr.Zero) { - TAc_decoder Videodecoder = (TAc_decoder)Marshal.PtrToStructure(_videodecoder, typeof(TAc_decoder)); - - _FrameBuffer[num].time = _VideoTime; - _VideoTime = (float)Videodecoder.timecode; - - if (Videodecoder.buffer != IntPtr.Zero) - { - Marshal.Copy(Videodecoder.buffer, _FrameBuffer[num].data, 0, _Width * _Height * 4); + Marshal.Copy(Videodecoder.buffer, _FrameBuffer[num].data, 0, _Width * _Height * 4); - _FrameBuffer[num].displayed = false; - } + _FrameBuffer[num].displayed = false; } - - + _waiting = false; } } diff --git a/Vocaluxe/Menu/CLyric.cs b/Vocaluxe/Menu/CLyric.cs index 24651cc3..8a70e0ab 100644 --- a/Vocaluxe/Menu/CLyric.cs +++ b/Vocaluxe/Menu/CLyric.cs @@ -15,7 +15,8 @@ namespace Vocaluxe.Menu { Fill, Jump, - Slide + Slide, + Zoom } struct SNote @@ -23,6 +24,7 @@ namespace Vocaluxe.Menu public string Text; public int StartBeat; public int EndBeat; + public int Duration; public ENoteType Type; } @@ -205,6 +207,7 @@ namespace Vocaluxe.Menu n.Text = note.Text; n.StartBeat = note.StartBeat; n.EndBeat = note.EndBeat; + n.Duration = note.Duration; n.Type = note.NoteType; _Text.Text = note.Text; @@ -229,6 +232,7 @@ namespace Vocaluxe.Menu return _X - _width / 2; } + #region draw public void Draw(float ActualBeat) { if (Visible || CSettings.GameState == EGameState.EditTheme) @@ -236,12 +240,17 @@ namespace Vocaluxe.Menu switch (_Style) { case ELyricStyle.Fill: + DrawFill(ActualBeat); break; case ELyricStyle.Jump: + DrawJump(ActualBeat); break; case ELyricStyle.Slide: DrawSlide(ActualBeat); break; + case ELyricStyle.Zoom: + DrawZoom(ActualBeat); + break; default: DrawSlide(ActualBeat); break; @@ -257,6 +266,8 @@ namespace Vocaluxe.Menu { _Text.X = x; _Text.Style = EStyle.Bold; + _Text.Text = note.Text; + RectangleF rect = CDraw.GetTextBounds(_Text); if (note.Type == ENoteType.Freestyle) _Text.Style = EStyle.BoldItalic; @@ -266,7 +277,7 @@ namespace Vocaluxe.Menu if (CurrentBeat <= note.EndBeat) { _Text.Color = ColorProcessed; - _Text.Text = note.Text; + float diff = note.EndBeat - note.StartBeat; if (diff == 0) @@ -280,23 +291,202 @@ namespace Vocaluxe.Menu } else { - _Text.Color = ColorProcessed; - _Text.Text = note.Text; + _Text.Color = ColorProcessed; _Text.Draw(); } } else { - _Text.Color = Color; - _Text.Text = note.Text; + _Text.Color = Color; _Text.Draw(); } - RectangleF rect = CDraw.GetTextBounds(_Text); + x += rect.Width; } } + private void DrawZoom(float CurrentBeat) + { + float x = _X - _width / 2; // most left position + + //find last active note + int last_note = -1; + for (int i = 0; i < _Notes.Count; i++) + { + if (CurrentBeat >= _Notes[i].StartBeat) + last_note = i; + } + + int zoom_note = -1; + float zoomx = 0f; + + int current_note = -1; + foreach (SNote note in _Notes) + { + current_note++; + + _Text.X = x; + _Text.Style = EStyle.Bold; + _Text.Text = note.Text; + RectangleF rect = CDraw.GetTextBounds(_Text); + + if (note.Type == ENoteType.Freestyle) + _Text.Style = EStyle.BoldItalic; + + if (CurrentBeat >= note.StartBeat) + { + if (CurrentBeat <= note.EndBeat) + { + zoom_note = current_note; + zoomx = _Text.X; + } + else + { + // already passed + if (current_note == last_note) + _Text.Color = ColorProcessed; + else + _Text.Color = Color; + + _Text.Draw(); + } + + } + else + { + // not passed + _Text.Color = Color; + _Text.Draw(); + } + + x += rect.Width; + } + + if (zoom_note > -1) + { + if (_Notes[zoom_note].Duration == 0) + return; + + _Text.X = zoomx; + _Text.Text = _Notes[zoom_note].Text; + _Text.Color = ColorProcessed; + _Text.Style = EStyle.Bold; + + if (_Notes[zoom_note].Type == ENoteType.Freestyle) + _Text.Style = EStyle.BoldItalic; + + RectangleF rect = CDraw.GetTextBounds(_Text); + + float diff = _Notes[zoom_note].EndBeat - _Notes[zoom_note].StartBeat; + + float p = (CurrentBeat - _Notes[zoom_note].StartBeat) / _Notes[zoom_note].Duration; + if (p > 1f) + p = 1f; + + p = 1f - p; + + float ty = _Text.Y; + float tx = _Text.X; + float th = _Text.Height; + float tz = _Text.Z; + + _Text.Height += _Text.Height * p * 0.4f; + RectangleF rectz = CDraw.GetTextBounds(_Text); + _Text.X -= (rectz.Width - rect.Width) / 2f; + _Text.Y -= (rectz.Height - rect.Height) / 2f; + _Text.Z -= 0.1f; + + _Text.Draw(); + + _Text.Y = ty; + _Text.X = tx; + _Text.Height = th; + _Text.Z = tz; + } + } + + private void DrawFill(float CurrentBeat) + { + float x = _X - _width / 2; // most left position + + foreach (SNote note in _Notes) + { + _Text.X = x; + _Text.Style = EStyle.Bold; + _Text.Text = note.Text; + RectangleF rect = CDraw.GetTextBounds(_Text); + + if (note.Type == ENoteType.Freestyle) + _Text.Style = EStyle.BoldItalic; + + if (CurrentBeat >= note.StartBeat) + { + _Text.Color = ColorProcessed; + _Text.Draw(); + } + else + { + // not passed + _Text.Color = Color; + _Text.Draw(); + } + + x += rect.Width; + } + } + + private void DrawJump(float CurrentBeat) + { + float x = _X - _width / 2; // most left position + + foreach (SNote note in _Notes) + { + _Text.X = x; + _Text.Style = EStyle.Bold; + _Text.Text = note.Text; + RectangleF rect = CDraw.GetTextBounds(_Text); + + if (note.Type == ENoteType.Freestyle) + _Text.Style = EStyle.BoldItalic; + + if (CurrentBeat >= note.StartBeat) + { + if (CurrentBeat <= note.EndBeat) + { + _Text.Color = ColorProcessed; + + float diff = note.EndBeat - note.StartBeat; + if (diff == 0) + _Text.Draw(); + else + { + float y = _Text.Y; + _Text.Y -= _Text.Height * 0.1f; + _Text.Draw(); + _Text.Y = y; + } + } + else + { + // already passed + _Text.Color = Color; + _Text.Draw(); + } + + } + else + { + // not passed + _Text.Color = Color; + _Text.Draw(); + } + + x += rect.Width; + } + } + #endregion draw + public void UnloadTextures() { } diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs index 8e947a04..415a7bd9 100644 --- a/Vocaluxe/Screens/CScreenSing.cs +++ b/Vocaluxe/Screens/CScreenSing.cs @@ -382,16 +382,16 @@ namespace Vocaluxe.Screens } break; } - - Lyrics[htLyrics(LyricMain)].Draw(CGame.Beat); Lyrics[htLyrics(LyricSub)].Draw(-100); + Lyrics[htLyrics(LyricMain)].Draw(CGame.Beat); - Lyrics[htLyrics(LyricMainDuet)].Draw(CGame.Beat); Lyrics[htLyrics(LyricSubDuet)].Draw(-100); + Lyrics[htLyrics(LyricMainDuet)].Draw(CGame.Beat); - Lyrics[htLyrics(LyricMainTop)].Draw(CGame.Beat); Lyrics[htLyrics(LyricSubTop)].Draw(-100); + Lyrics[htLyrics(LyricMainTop)].Draw(CGame.Beat); + for (int i = 0; i < CGame.NumPlayer; i++) {