Skip to content

Commit 1fd0df8

Browse files
Add button to compare audio analysis to another MSU
1 parent cb1776b commit 1fd0df8

9 files changed

+341
-222
lines changed

MSUScripter/Services/AudioAnalysisService.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ public class AudioAnalysisService(
2020
ConverterService converterService,
2121
ILogger<AudioAnalysisService> logger)
2222
{
23-
public async Task AnalyzePcmFiles(MsuProjectViewModel projectViewModel, AudioAnalysisViewModel audioAnalysis, CancellationToken ct = new())
23+
public async Task AnalyzePcmFiles(AudioAnalysisViewModel audioAnalysis, CancellationToken ct = new())
2424
{
25-
var project = converterService.ConvertProject(projectViewModel);
25+
var project = audioAnalysis.Project == null ? null : converterService.ConvertProject(audioAnalysis.Project);
2626

2727
await Parallel.ForEachAsync(audioAnalysis.Rows,
2828
new ParallelOptions { MaxDegreeOfParallelism = 10, CancellationToken = ct },
@@ -39,26 +39,26 @@ public async Task AnalyzePcmFile(MsuProjectViewModel projectViewModel, AudioAnal
3939
await AnalyzePcmFile(project, song);
4040
}
4141

42-
public async Task AnalyzePcmFile(MsuProject project, AudioAnalysisSongViewModel song)
42+
public async Task AnalyzePcmFile(MsuProject? project, AudioAnalysisSongViewModel song)
4343
{
4444
if (string.IsNullOrEmpty(song.Path))
4545
{
4646
song.WarningMessage = "No output path for the song";
4747
return;
4848
}
49-
else if (!project.BasicInfo.IsMsuPcmProject && !File.Exists(song.Path))
49+
else if (project?.BasicInfo.IsMsuPcmProject != true && !File.Exists(song.Path))
5050
{
5151
song.WarningMessage = "PCM file missing";
5252
return;
5353
}
54-
else if (project.BasicInfo.IsMsuPcmProject && song.OriginalViewModel?.HasFiles() != true && !File.Exists(song.Path))
54+
else if (project?.BasicInfo.IsMsuPcmProject == true && song.OriginalViewModel?.HasFiles() != true && !File.Exists(song.Path))
5555
{
5656
song.WarningMessage = "No input files specified for PCM file";
5757
return;
5858
}
5959

6060
// Regenerate the pcm file if it has updates that have been made to it
61-
if (project.BasicInfo.IsMsuPcmProject && song.OriginalViewModel != null && song.OriginalViewModel.HasFiles() && (song.OriginalViewModel.HasChangesSince(song.OriginalViewModel.LastGeneratedDate) || !File.Exists(song.Path)))
61+
if (project?.BasicInfo.IsMsuPcmProject == true && song.OriginalViewModel != null && song.OriginalViewModel.HasFiles() && (song.OriginalViewModel.HasChangesSince(song.OriginalViewModel.LastGeneratedDate) || !File.Exists(song.Path)))
6262
{
6363
logger.LogInformation("PCM file {File} out of date, regenerating", song.Path);
6464
if (!await GeneratePcmFile(project, song.OriginalViewModel))

MSUScripter/Services/ControlServices/AudioAnalysisWindowService.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
using System.Threading;
55
using AvaloniaControls.ControlServices;
66
using AvaloniaControls.Services;
7+
using MSURandomizerLibrary.Services;
78
using MSUScripter.ViewModels;
89

910
namespace MSUScripter.Services.ControlServices;
1011

11-
public class AudioAnalysisWindowService(AudioAnalysisService audioAnalysisService) : ControlService
12+
public class AudioAnalysisWindowService(AudioAnalysisService audioAnalysisService, IMsuLookupService msuLookupService) : ControlService
1213
{
1314
private readonly AudioAnalysisViewModel _model = new();
1415
private readonly CancellationTokenSource _cts = new();
@@ -39,13 +40,49 @@ public AudioAnalysisViewModel InitializeModel(MsuProjectViewModel project)
3940
return _model;
4041
}
4142

43+
public AudioAnalysisViewModel InitializeModel(string msuPath)
44+
{
45+
_model.ShowCompareButton = false;
46+
47+
var msuDirectory = new FileInfo(msuPath).DirectoryName;
48+
if (string.IsNullOrEmpty(msuDirectory))
49+
{
50+
_model.LoadError = "Could not load MSU";
51+
return _model;
52+
}
53+
54+
var msu = msuLookupService.LoadMsu(msuPath, null, false, true, true);
55+
56+
if (msu == null)
57+
{
58+
_model.LoadError = "Could not load MSU";
59+
return _model;
60+
}
61+
62+
var songs = msu.Tracks
63+
.OrderBy(x => x.Number)
64+
.Select(x => new AudioAnalysisSongViewModel()
65+
{
66+
SongName = Path.GetRelativePath(msuDirectory, new FileInfo(x.Path).FullName),
67+
TrackName = x.TrackName,
68+
TrackNumber = x.Number,
69+
Path = x.Path ?? "",
70+
OriginalViewModel = null,
71+
CanRefresh = false
72+
})
73+
.ToList();
74+
75+
_model.Rows = songs;
76+
return _model;
77+
}
78+
4279
public void Run()
4380
{
4481
_ = ITaskService.Run(async () =>
4582
{
4683
var start = DateTime.Now;
4784

48-
await audioAnalysisService.AnalyzePcmFiles(_model.Project, _model, _cts.Token);
85+
await audioAnalysisService.AnalyzePcmFiles(_model, _cts.Token);
4986

5087
var avg = GetAverageRms();
5188
var max = GetAveragePeak();

MSUScripter/ViewModels/AudioAnalysisSongViewModel.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public class AudioAnalysisSongViewModel : ViewModelBase
2424

2525
[Reactive, ReactiveLinkedProperties(nameof(HasWarning))]
2626
public string WarningMessage { get; set; } = "";
27-
27+
28+
public bool CanRefresh { get; set; } = true;
2829
public bool HasWarning => !string.IsNullOrEmpty(WarningMessage);
2930

3031
public void ApplyAudioAnalysis(AnalysisDataOutput data)

MSUScripter/ViewModels/AudioAnalysisViewModel.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,22 @@ namespace MSUScripter.ViewModels;
77

88
public class AudioAnalysisViewModel : ViewModelBase
99
{
10-
public MsuProjectViewModel Project { get; set; } = new();
10+
public MsuProjectViewModel? Project { get; set; }
1111

1212
[Reactive] public int SongsCompleted { get; set; }
1313

1414
[Reactive] public string BottomBar { get; set; } = "";
1515

1616
[Reactive, ReactiveLinkedProperties(nameof(TotalSongs))]
1717
public List<AudioAnalysisSongViewModel> Rows { get; set; } = [];
18-
18+
19+
[Reactive] public bool CompareEnabled { get; set; } = true;
20+
21+
1922
public double Duration { get; set; }
2023
public int TotalSongs => Rows.Count;
24+
public string? LoadError { get; set; }
25+
public bool ShowCompareButton { get; set; } = true;
2126

2227
public override ViewModelBase DesignerExample()
2328
{

MSUScripter/Views/AudioAnalysisWindow.axaml

Lines changed: 76 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,76 @@
1-
<Window xmlns="https://github.com/avaloniaui"
2-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3-
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4-
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5-
xmlns:viewModels="clr-namespace:MSUScripter.ViewModels"
6-
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
7-
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
8-
Width="768" Height="1024"
9-
x:Class="MSUScripter.Views.AudioAnalysisWindow"
10-
Title="Audio Analysis - MSU Scripter"
11-
x:DataType="viewModels:AudioAnalysisViewModel"
12-
Loaded="Control_OnLoaded"
13-
Unloaded="Control_OnUnloaded"
14-
WindowStartupLocation="CenterOwner"
15-
Icon="/Assets/MSUScripterIcon.ico"
16-
>
17-
<LayoutTransformControl Name="MainLayout">
18-
<DockPanel>
19-
<ProgressBar Name="MsuPcmProgressBar" DockPanel.Dock="Top"
20-
Minimum="0"
21-
Maximum="{Binding TotalSongs}"
22-
Value="{Binding SongsCompleted}"></ProgressBar>
23-
<TextBlock DockPanel.Dock="Bottom" Text="{Binding BottomBar}" TextAlignment="Right" Margin="3" />
24-
<DataGrid Name="AudioDataGrid"
25-
ItemsSource="{Binding Rows}"
26-
AutoGenerateColumns="False"
27-
CanUserReorderColumns="False"
28-
CanUserResizeColumns="True"
29-
IsReadOnly="True"
30-
RowBackground="{DynamicResource CardBackground}"
31-
SelectionMode="Single"
32-
>
33-
<DataGrid.Columns>
34-
<DataGridTemplateColumn Header="">
35-
<DataGridTemplateColumn.CellTemplate>
36-
<DataTemplate>
37-
<Button Name="RefreshSongButton"
38-
Tag="{Binding}"
39-
IsEnabled="{Binding HasLoaded}"
40-
Click="RefreshSongButton_OnClick">
41-
<avalonia:MaterialIcon Kind="Refresh" ></avalonia:MaterialIcon>
42-
</Button>
43-
</DataTemplate>
44-
</DataGridTemplateColumn.CellTemplate>
45-
</DataGridTemplateColumn>
46-
<DataGridTemplateColumn Header="">
47-
<DataGridTemplateColumn.CellTemplate>
48-
<DataTemplate>
49-
<avalonia:MaterialIcon Kind="Alert"
50-
Foreground="Goldenrod"
51-
IsVisible="{Binding HasWarning}"
52-
ToolTip.Tip="{Binding WarningMessage}"
53-
></avalonia:MaterialIcon>
54-
</DataTemplate>
55-
</DataGridTemplateColumn.CellTemplate>
56-
</DataGridTemplateColumn>
57-
<DataGridTextColumn Header="Track" Binding="{Binding TrackNumber}"/>
58-
<DataGridTextColumn Header="Track Name" Binding="{Binding TrackName}"/>
59-
<DataGridTextColumn Header="File" Binding="{Binding SongName}"/>
60-
<DataGridTextColumn Header="Average Volume" Binding="{Binding AvgDecibals}"/>
61-
<DataGridTextColumn Header="Peak Volume" Binding="{Binding MaxDecibals}"/>
62-
</DataGrid.Columns>
63-
</DataGrid>
64-
</DockPanel>
65-
</LayoutTransformControl>
66-
</Window>
1+
<Window xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:viewModels="clr-namespace:MSUScripter.ViewModels"
6+
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"xmlns:controls="using:AvaloniaControls.Controls"
7+
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
8+
Width="768" Height="1024"
9+
x:Class="MSUScripter.Views.AudioAnalysisWindow"
10+
Title="Audio Analysis - MSU Scripter"
11+
x:DataType="viewModels:AudioAnalysisViewModel"
12+
Loaded="Control_OnLoaded"
13+
Unloaded="Control_OnUnloaded"
14+
WindowStartupLocation="CenterOwner"
15+
Icon="/Assets/MSUScripterIcon.ico"
16+
>
17+
<LayoutTransformControl Name="MainLayout">
18+
<DockPanel>
19+
<ProgressBar Name="MsuPcmProgressBar" DockPanel.Dock="Top"
20+
Minimum="0"
21+
Maximum="{Binding TotalSongs}"
22+
Value="{Binding SongsCompleted}"></ProgressBar>
23+
<controls:HeaderFooter DockPanel.Dock="Bottom">
24+
<Grid ColumnDefinitions="Auto, *">
25+
<Button Margin="5" Click="CompareButton_OnClick" IsVisible="{Binding ShowCompareButton}" IsEnabled="{Binding CompareEnabled}">
26+
Compare to Other MSU
27+
</Button>
28+
<TextBlock Grid.Column="2" Text="{Binding BottomBar}" TextAlignment="Right" VerticalAlignment="Center" Margin="5" />
29+
</Grid>
30+
</controls:HeaderFooter>
31+
32+
<DataGrid Name="AudioDataGrid"
33+
ItemsSource="{Binding Rows}"
34+
AutoGenerateColumns="False"
35+
CanUserReorderColumns="False"
36+
CanUserResizeColumns="True"
37+
IsReadOnly="True"
38+
RowBackground="{DynamicResource CardBackground}"
39+
SelectionMode="Single"
40+
BorderThickness="0"
41+
>
42+
<DataGrid.Columns>
43+
<DataGridTemplateColumn Header="">
44+
<DataGridTemplateColumn.CellTemplate>
45+
<DataTemplate>
46+
<Button Name="RefreshSongButton"
47+
Tag="{Binding}"
48+
IsEnabled="{Binding HasLoaded}"
49+
IsVisible="{Binding CanRefresh}"
50+
Click="RefreshSongButton_OnClick">
51+
<avalonia:MaterialIcon Kind="Refresh" ></avalonia:MaterialIcon>
52+
</Button>
53+
</DataTemplate>
54+
</DataGridTemplateColumn.CellTemplate>
55+
</DataGridTemplateColumn>
56+
<DataGridTemplateColumn Header="">
57+
<DataGridTemplateColumn.CellTemplate>
58+
<DataTemplate>
59+
<avalonia:MaterialIcon Kind="Alert"
60+
Foreground="Goldenrod"
61+
IsVisible="{Binding HasWarning}"
62+
ToolTip.Tip="{Binding WarningMessage}"
63+
></avalonia:MaterialIcon>
64+
</DataTemplate>
65+
</DataGridTemplateColumn.CellTemplate>
66+
</DataGridTemplateColumn>
67+
<DataGridTextColumn Header="Track" Binding="{Binding TrackNumber}"/>
68+
<DataGridTextColumn Header="Track Name" Binding="{Binding TrackName}"/>
69+
<DataGridTextColumn Header="File" Binding="{Binding SongName}"/>
70+
<DataGridTextColumn Header="Average Volume" Binding="{Binding AvgDecibals}"/>
71+
<DataGridTextColumn Header="Peak Volume" Binding="{Binding MaxDecibals}"/>
72+
</DataGrid.Columns>
73+
</DataGrid>
74+
</DockPanel>
75+
</LayoutTransformControl>
76+
</Window>

0 commit comments

Comments
 (0)