6public static class AudioDefinitionValidator
13 public static IReadOnlyList<string> Validate(AudioDefinition definition)
15 ArgumentNullException.ThrowIfNull(definition);
17 var errors =
new List<string>();
18 var keys =
new HashSet<string>(StringComparer.Ordinal);
20 definition.Resources ??= [];
22 for (
int i = 0; i < definition.Resources.Count; i++)
24 var resource = definition.Resources[i];
25 var label = $
"Resource {i}";
29 errors.Add($
"{label}: resource definition is null.");
33 if (
string.IsNullOrWhiteSpace(resource.Key))
34 errors.Add($
"{label}: key is empty.");
35 else if (!keys.Add(resource.Key))
36 errors.Add($
"{label}: duplicate key '{resource.Key}'.");
38 if (!Enum.IsDefined(resource.SourceKind))
40 errors.Add($
"{label}: unknown source kind '{resource.SourceKind}'.");
44 if (!
float.IsFinite(resource.Volume) || resource.Volume < 0f || resource.Volume > 1f)
45 errors.Add($
"{label}: Volume must be between 0 and 1.");
47 if (!
float.IsFinite(resource.Pan) || resource.Pan < -1f || resource.Pan > 1f)
48 errors.Add($
"{label}: Pan must be between -1 and 1.");
50 if (!
float.IsFinite(resource.PlaybackSpeed) ||
51 resource.PlaybackSpeed < AudioResource.MinimumPlaybackSpeed ||
52 resource.PlaybackSpeed > AudioResource.MaximumPlaybackSpeed)
55 $
"{label}: PlaybackSpeed must be between {AudioResource.MinimumPlaybackSpeed} and {AudioResource.MaximumPlaybackSpeed}.");
58 switch (resource.SourceKind)
61 if (
string.IsNullOrWhiteSpace(resource.FilePath))
62 errors.Add($
"{label}: loose FilePath is empty.");
66 if (
string.IsNullOrWhiteSpace(resource.AssetsFilePath))
67 errors.Add($
"{label}: AssetsFilePath is empty.");
68 if (
string.IsNullOrWhiteSpace(resource.AssetEntryName))
69 errors.Add($
"{label}: AssetEntryName is empty.");
70 if (
string.IsNullOrWhiteSpace(resource.SourceExtension) &&
71 string.IsNullOrWhiteSpace(Path.GetExtension(resource.AssetEntryName)))
73 errors.Add($
"{label}: packed audio requires SourceExtension when AssetEntryName has no extension.");
78 if (
string.IsNullOrWhiteSpace(resource.SourceUri))
79 errors.Add($
"{label}: SourceUri is empty.");
80 else if (!
Uri.TryCreate(resource.SourceUri, UriKind.RelativeOrAbsolute, out _))
81 errors.Add($
"{label}: SourceUri is invalid.");
AudioResourceSourceKind
Identifies how a GSND audio resource locates its underlying media.
@ Uri
The resource is loaded from a URI.