Difference between revisions of "Modding talk:Audio"

From Stardew Valley Wiki
Jump to navigation Jump to search
(+ code for track list export)
 
Line 18: Line 18:
 
             {
 
             {
 
                 output.AppendLine($"==={categoryGroup.Key}===");
 
                 output.AppendLine($"==={categoryGroup.Key}===");
                 output.AppendLine("{| class=\"wikitable\"");
+
                 output.AppendLine("{| class=\"wikitable sortable\"");
 
                 output.AppendLine("|-\n! name\n! soundbank ID\n! description");
 
                 output.AppendLine("|-\n! name\n! soundbank ID\n! description");
  

Revision as of 02:20, 17 October 2021

Track list export

The initial track list was exported with this quick code, which can be run as a C# mod:

source code 
/// <summary>The main entry point for the mod.</summary>
public class ModEntry : Mod
{
    /*********
    ** Public methods
    *********/
    /// <inheritdoc />
    public override void Entry(IModHelper helper)
    {
        helper.Events.GameLoop.GameLaunched += (_, _) =>
        {
            StringBuilder output = new();

            foreach (var categoryGroup in this.GetTracks().GroupBy(p => p.Category).OrderBy(p => p.Key))
            {
                output.AppendLine($"==={categoryGroup.Key}===");
                output.AppendLine("{| class=\"wikitable sortable\"");
                output.AppendLine("|-\n! name\n! soundbank ID\n! description");

                foreach (SoundInfo sound in categoryGroup.OrderBy(p => p.Name).ThenBy(p => p.Id))
                {
                    string soundIdLabel = sound.Id.ToString("X").ToLower().PadLeft(8, '0');
                    output.AppendLine($"|-\n| <tt>{sound.Name}</tt>\n| <tt>{soundIdLabel}</tt>\n| ");
                }

                output.AppendLine("|}");
                output.AppendLine();
            }

            string result = output.ToString();
            this.Monitor.Log(result, LogLevel.Info);
        };
    }


    /*********
    ** Private methods
    *********/
    /// <summary>Extract the music/sound tracks from the game's soundbank.</summary>
    private IEnumerable<SoundInfo> GetTracks()
    {
        SoundBank soundBank = this.Helper.Reflection.GetField<SoundBank>(Game1.soundBank, "soundBank").GetValue();
        Dictionary<string, CueDefinition> cues = this.Helper.Reflection.GetField<Dictionary<string, CueDefinition>>(soundBank, "_cues").GetValue();

        foreach (var entry in cues)
        {
            foreach (XactSoundBankSound sound in entry.Value.sounds)
            {
                HashSet<int> ids = new();

                // from main sound info
                string name = entry.Key;
                string category = this.GetCategoryName(sound.categoryID);
                if (sound.trackIndex != 0)
                    ids.Add(sound.trackIndex);

                // from variants
                if (sound.soundClips != null)
                {
                    foreach (XactClip clip in sound.soundClips)
                    {
                        foreach (var rawClipEvent in clip.clipEvents)
                        {
                            if (rawClipEvent is not PlayWaveEvent clipEvent)
                            {
                                this.Monitor.Log($"Unexpected clip event type '{rawClipEvent.GetType().FullName}'.", LogLevel.Error);
                                continue;
                            }

                            foreach (var variant in clipEvent.GetVariants())
                            {
                                if (variant.track != 0)
                                    ids.Add(variant.track);
                            }
                        }
                    }
                }

                // export tracks
                foreach (int id in ids)
                {
                    yield return new SoundInfo
                    {
                        Category = category,
                        Name = name,
                        Id = id
                    };
                }
            }
        }
    }

    /// <summary>Get a human-readable name for a raw audio category ID.</summary>
    /// <param name="categoryId">The raw category ID.</param>
    private string GetCategoryName(uint categoryId)
    {
        // the categories seem to be arbitrarily defined for Stardew Valley;
        // these are approximate labels based on the tracks in each group.
        return categoryId switch
        {
            2 => "Music",
            3 => "Sound",
            4 => "Music (ambient)",
            5 => "Footsteps",
            _ => categoryId.ToString()
        };
    }
}

public class SoundInfo
{
    public string Category { get; set; }
    public string Name { get; set; }
    public int Id { get; set; }
}

Pathoschild (talk) 02:18, 17 October 2021 (UTC)