update readme and add snow flake effect

This commit is contained in:
Zhe Fang
2025-10-30 21:20:06 -04:00
parent e15699bb11
commit f5bdb3a431
14 changed files with 70 additions and 46 deletions

View File

@@ -12,7 +12,7 @@
<Identity <Identity
Name="37412.BetterLyrics" Name="37412.BetterLyrics"
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9" Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
Version="1.0.89.0" /> Version="1.0.90.0" />
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> <mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

View File

@@ -66,6 +66,7 @@
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" /> <PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
<PackageReference Include="csharp-kana" Version="1.0.2" /> <PackageReference Include="csharp-kana" Version="1.0.2" />
<PackageReference Include="csharp-pinyin" Version="1.0.1" /> <PackageReference Include="csharp-pinyin" Version="1.0.1" />
<PackageReference Include="DevWinUI.Controls" Version="9.4.2" />
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" /> <PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.2" /> <PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.2" />
<PackageReference Include="Hqub.Last.fm" Version="2.5.1" /> <PackageReference Include="Hqub.Last.fm" Version="2.5.1" />

View File

@@ -18,7 +18,7 @@
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" /> <TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
<controls:SettingsCard x:Uid="SettingsPageTheme" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=&#xE790;}"> <controls:SettingsCard x:Uid="SettingsPageTheme">
<ComboBox x:Name="ThemeComboBox" SelectedIndex="{x:Bind LyricsBackgroundSettings.LyricsBackgroundTheme, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}"> <ComboBox x:Name="ThemeComboBox" SelectedIndex="{x:Bind LyricsBackgroundSettings.LyricsBackgroundTheme, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
<ComboBoxItem x:Uid="SettingsPageFollowSystem" /> <ComboBoxItem x:Uid="SettingsPageFollowSystem" />
<ComboBoxItem x:Uid="SettingsPageLight" /> <ComboBoxItem x:Uid="SettingsPageLight" />
@@ -26,11 +26,7 @@
</ComboBox> </ComboBox>
</controls:SettingsCard> </controls:SettingsCard>
<controls:SettingsExpander <controls:SettingsExpander x:Uid="SettingsPagePureLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsPureColorOverlayEnabled, Mode=OneWay}">
x:Uid="SettingsPagePureLayer"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xEB42;}"
IsExpanded="{x:Bind LyricsBackgroundSettings.IsPureColorOverlayEnabled, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsPureColorOverlayEnabled, Mode=TwoWay}" /> <ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsPureColorOverlayEnabled, Mode=TwoWay}" />
<controls:SettingsExpander.Items> <controls:SettingsExpander.Items>
@@ -47,11 +43,7 @@
</controls:SettingsExpander.Items> </controls:SettingsExpander.Items>
</controls:SettingsExpander> </controls:SettingsExpander>
<controls:SettingsExpander <controls:SettingsExpander x:Uid="SettingsPageAlbumArtLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
x:Uid="SettingsPageAlbumArtLayer"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xE93C;}"
IsExpanded="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=TwoWay}" /> <ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=TwoWay}" />
<controls:SettingsExpander.Items> <controls:SettingsExpander.Items>
@@ -96,11 +88,7 @@
</controls:SettingsExpander.Items> </controls:SettingsExpander.Items>
</controls:SettingsExpander> </controls:SettingsExpander>
<controls:SettingsExpander <controls:SettingsExpander x:Uid="SettingsPageFluidLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsFluidOverlayEnabled, Mode=OneWay}">
x:Uid="SettingsPageFluidLayer"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
Glyph=&#xEDA8;}"
IsExpanded="{x:Bind LyricsBackgroundSettings.IsFluidOverlayEnabled, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsFluidOverlayEnabled, Mode=TwoWay}" /> <ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsFluidOverlayEnabled, Mode=TwoWay}" />
<controls:SettingsExpander.Items> <controls:SettingsExpander.Items>
@@ -124,11 +112,21 @@
</controls:SettingsExpander.Items> </controls:SettingsExpander.Items>
</controls:SettingsExpander> </controls:SettingsExpander>
<controls:SettingsExpander <controls:SettingsExpander Header="Snow flake layer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled, Mode=OneWay}">
x:Uid="SettingsPageSpectrumLayer" <ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled, Mode=TwoWay}" />
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, <controls:SettingsExpander.Items>
Glyph=&#xF61F;}" <controls:SettingsCard Header="Flake count">
IsExpanded="{x:Bind LyricsBackgroundSettings.IsSpectrumOverlayEnabled, Mode=OneWay}"> <uc:ExtendedSlider
Frequency="1"
Maximum="100"
Minimum="10"
ResetButtonVisibility="Collapsed"
Value="{x:Bind LyricsBackgroundSettings.SnowFlakeOverlayAmount, Mode=TwoWay}" />
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<controls:SettingsExpander x:Uid="SettingsPageSpectrumLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsSpectrumOverlayEnabled, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsSpectrumOverlayEnabled, Mode=TwoWay}" /> <ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsSpectrumOverlayEnabled, Mode=TwoWay}" />
</controls:SettingsExpander> </controls:SettingsExpander>

View File

@@ -6,30 +6,30 @@ using System.Diagnostics;
namespace BetterLyrics.WinUI3.Helper namespace BetterLyrics.WinUI3.Helper
{ {
public class SpectrumAnalyzer : IDisposable public partial class SpectrumAnalyzer : IDisposable
{ {
private WasapiLoopbackCapture _capture; private WasapiLoopbackCapture? _capture;
private int _sampleRate = 48000; private int _sampleRate = 48000;
private readonly int _fftLength = 2048; private readonly int _fftLength = 2048;
private readonly float[] _fftLeftBuffer; private readonly float[] _fftLeftBuffer;
private readonly float[] _fftRightBuffer; private readonly float[] _fftRightBuffer;
private readonly Complex[] _fftLeftData; private readonly Complex[] _fftLeftData;
private readonly Complex[] _fftRightData; private readonly Complex[] _fftRightData;
private float[] _spectrumLeftData; private float[]? _spectrumLeftData;
private float[] _spectrumRightData; private float[]? _spectrumRightData;
private float[] _spectrumData; private float[]? _spectrumData;
private bool _disposed = false; private bool _disposed = false;
private double[] _hammingWindow; private double[] _hammingWindow;
private float[] _currentSpectrum; private float[]? _currentSpectrum;
public float[] SmoothSpectrum { get; private set; } public float[]? SmoothSpectrum { get; private set; }
public int BarCount { get; set; } = 32; public int BarCount { get; set; } = 32;
public int Sensitivity { get; set; } = 10; public int Sensitivity { get; set; } = 10;
public float SmoothingFactor { get; set; } = 0.95f; public float SmoothingFactor { get; set; } = 0.95f;
@@ -69,6 +69,7 @@ namespace BetterLyrics.WinUI3.Helper
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.WriteLine("+++++++++++++++++++" + ex.ToString());
} }
} }
@@ -100,10 +101,15 @@ namespace BetterLyrics.WinUI3.Helper
_fftRightData[i].Y = 0; _fftRightData[i].Y = 0;
} }
if (_spectrumData == null || _spectrumRightData == null || _currentSpectrum == null)
{
return;
}
// FFT // FFT
FastFourierTransform.FFT(true, (int)Math.Log(_fftLength, 2), _fftLeftData); FastFourierTransform.FFT(true, (int)Math.Log(_fftLength, 2), _fftLeftData);
FastFourierTransform.FFT(true, (int)Math.Log(_fftLength, 2), _fftRightData); FastFourierTransform.FFT(true, (int)Math.Log(_fftLength, 2), _fftRightData);
for (int i = 0; i < _spectrumLeftData.Length; i++) for (int i = 0; i < _spectrumLeftData?.Length; i++)
{ {
float real = (float)_fftLeftData[i].X; float real = (float)_fftLeftData[i].X;
float imaginary = (float)_fftLeftData[i].Y; float imaginary = (float)_fftLeftData[i].Y;
@@ -132,6 +138,11 @@ namespace BetterLyrics.WinUI3.Helper
public void UpdateSmoothSpectrum() public void UpdateSmoothSpectrum()
{ {
if (SmoothSpectrum == null || _currentSpectrum == null)
{
return;
}
for (int i = 0; i < BarCount; i++) for (int i = 0; i < BarCount; i++)
{ {
SmoothSpectrum[i] = SmoothSpectrum[i] * SmoothingFactor + SmoothSpectrum[i] = SmoothSpectrum[i] * SmoothingFactor +

View File

@@ -29,6 +29,9 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsSpectrumOverlayEnabled { get; set; } = false; [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsSpectrumOverlayEnabled { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsSnowFlakeOverlayEnabled { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int SnowFlakeOverlayAmount { get; set; } = 50;
public LyricsBackgroundSettings() { } public LyricsBackgroundSettings() { }

View File

@@ -115,7 +115,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
public void DrawSpectrum(ICanvasAnimatedControl control, CanvasDrawingSession ds) public void DrawSpectrum(ICanvasAnimatedControl control, CanvasDrawingSession ds)
{ {
if (_spectrumAnalyzer != null && _liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSpectrumOverlayEnabled) if (_spectrumAnalyzer != null && _spectrumAnalyzer.SmoothSpectrum != null && _liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSpectrumOverlayEnabled)
{ {
var points = new Vector2[_spectrumAnalyzer.BarCount]; var points = new Vector2[_spectrumAnalyzer.BarCount];
float pointSpacing = 0; float pointSpacing = 0;
@@ -340,7 +340,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
using var combinedDs = combined.CreateDrawingSession(); using var combinedDs = combined.CreateDrawingSession();
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次) // 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor, using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
_liveStatesService.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor); _liveStatesService.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
using var backgroundEffect = CanvasHelper.CreateBackgroundEffect(line, backgroundFontEffect, _lyricsOpacityTransition.Value); using var backgroundEffect = CanvasHelper.CreateBackgroundEffect(line, backgroundFontEffect, _lyricsOpacityTransition.Value);
@@ -356,7 +356,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
_liveStatesService.LiveStates.LyricsWindowStatus.LyricsEffectSettings.IsLyricsLineFadeEnabled); _liveStatesService.LiveStates.LyricsWindowStatus.LyricsEffectSettings.IsLyricsLineFadeEnabled);
using var lineMask = CanvasHelper.CreateLineMask(control, line); using var lineMask = CanvasHelper.CreateLineMask(control, line);
using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor, using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
_liveStatesService.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsFontStrokeWidth, _fgFontColor); _liveStatesService.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsFontStrokeWidth, _fgFontColor);
using var effectLayer = new CanvasCommandList(control); using var effectLayer = new CanvasCommandList(control);

View File

@@ -9,6 +9,7 @@
xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.Converters" xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dev="using:DevWinUI"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:labs="using:CommunityToolkit.Labs.WinUI.MarqueeTextRns" xmlns:labs="using:CommunityToolkit.Labs.WinUI.MarqueeTextRns"
xmlns:local="using:BetterLyrics.WinUI3.Views" xmlns:local="using:BetterLyrics.WinUI3.Views"
@@ -25,7 +26,8 @@
SizeChanged="RootGrid_SizeChanged"> SizeChanged="RootGrid_SizeChanged">
<!-- Lyrics area --> <!-- Lyrics area -->
<renderer:LyricsRenderer /> <renderer:LyricsRenderer />
<!--<Image Source="/Assets/Cover.jpg" />-->
<dev:SnowFlakeEffect FlakeCount="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.SnowFlakeOverlayAmount, Mode=OneWay}" Visibility="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
<!-- No music playing placeholder --> <!-- No music playing placeholder -->
<Grid x:Name="NoMusicPlayingGrid" Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}"> <Grid x:Name="NoMusicPlayingGrid" Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 372 KiB

View File

@@ -81,25 +81,34 @@ Check out the article: [BetterLyrics An immersive and smooth lyrics display
## Screenshots ## Screenshots
> ⚠️ Due to GIF format and frame rate limitations, the displayed effect is for preview only. Please refer to the actual device for the actual effect.
<div style="display: flex; justify-content: space-around; align-items: flex-start;"> <div style="display: flex; justify-content: space-around; align-items: flex-start;">
<img src="Screenshots/std.png" width="49%" > <img src="Screenshots/fs2.png" width="100%">
<img src="Screenshots/std-narrow.png" width="49%">
</div> </div>
<div style="height: 8px;"></div>
<div style="display: flex; justify-content: space-around; align-items: flex-start;"> <div style="display: flex; justify-content: space-around; align-items: flex-start;">
<img src="Screenshots/PixPin_2025-10-24_18-13-44.gif" width="49%" > <img src="Screenshots/std.png" width="49%">
<img src="Screenshots/std-fullscreen.png" width="49%"> <div style="width: 12px;"></div>
<img src="Screenshots/narrow.png" width="49%">
</div> </div>
<div style="height: 8px;"></div>
<div style="display: flex; justify-content: space-around; align-items: flex-start;"> <div style="display: flex; justify-content: space-around; align-items: flex-start;">
<img src="Screenshots/dock.png" width="49%" > <img src="Screenshots/dock.png" width="49%" >
<div style="width: 12px;"></div>
<img src="Screenshots/desktop.png" width="49%"> <img src="Screenshots/desktop.png" width="49%">
</div> </div>
<br>
> ⚠️ Due to GIF format and frame rate limitations, the displayed effect is for preview only. Please refer to the actual device for the actual effect.
<div style="display: flex; justify-content: space-around; align-items: flex-start;"> <div style="display: flex; justify-content: space-around; align-items: flex-start;">
<img src="Screenshots/PixPin_2025-10-24_18-17-17.gif" width="49%" > <img src="Screenshots/PixPin_2025-10-24_18-13-44.gif" width="49%" >
<img src="Screenshots/PixPin_2025-10-24_18-17-17.gif" width="42%" >
</div> </div>
## Demonstration ## Demonstration

View File

Before

Width:  |  Height:  |  Size: 642 KiB

After

Width:  |  Height:  |  Size: 642 KiB

BIN
Screenshots/fs2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 KiB

BIN
Screenshots/narrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 847 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 KiB

After

Width:  |  Height:  |  Size: 578 KiB