Reworking Simple Sound Manager to be something way better.

This commit is contained in:
JoshuaNavarro 2019-04-04 01:46:26 -07:00
parent 81c0078b78
commit ff612c1bb0
12 changed files with 464 additions and 608 deletions

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SimpleSoundManager.Framework.Music
{
/// <summary>
/// Config class for the mod.
/// </summary>
public class Config
{
public bool EnableDebugLog;
/// <summary>
/// Constructor.
/// </summary>
public Config()
{
EnableDebugLog = false;
}
}
}

View File

@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using Microsoft.Xna.Framework.Audio;
using StardewValley;
namespace SimpleSoundManager.Framework
{
/// <summary>Manages all music for the mod.</summary>
public class MusicManager
{
/*********
** Fields
*********/
/// <summary>The RNG used to select music packs and songs.</summary>
private readonly Random Random = new Random();
/// <summary>The delay timer between songs.</summary>
private readonly Timer Timer = new Timer();
/*********
** Accessors
*********/
/// <summary>The loaded music packs.</summary>
public IDictionary<string, MusicPack> MusicPacks { get; } = new Dictionary<string, MusicPack>();
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
public MusicManager()
{
}
/// <summary>Adds a valid xwb music pack to the list of music packs available.</summary>
/// <param name="musicPack">The music pack to add.</param>
/// <param name="displayLogInformation">Whether or not to display the process to the console. Will include information from the pack's metadata. Default:False</param>
/// <param name="displaySongs">If displayLogInformation is also true this will display the name of all of the songs in the music pack when it is added in.</param>
public void addMusicPack(MusicPack musicPack, bool displayLogInformation = false, bool displaySongs = false)
{
if (displayLogInformation)
{
if (ModCore.Config.EnableDebugLog)
{
ModCore.ModMonitor.Log("Adding music pack:");
ModCore.ModMonitor.Log($" Name: {musicPack.Name}");
ModCore.ModMonitor.Log($" Author: {musicPack.Manifest.Author}");
ModCore.ModMonitor.Log($" Description: {musicPack.Manifest.Description}");
ModCore.ModMonitor.Log($" Version Info: {musicPack.Manifest.Version}");
}
if (displaySongs && ModCore.Config.EnableDebugLog)
{
ModCore.ModMonitor.Log(" Song List:");
foreach (string songName in musicPack.Sounds.Keys)
ModCore.ModMonitor.Log($" {songName}");
}
}
this.MusicPacks.Add(musicPack.Name, musicPack);
}
/// <summary>
/// Plays the specified sound from the music pack.
/// </summary>
/// <param name="packName"></param>
/// <param name="soundName"></param>
public void playSound(string packName, string soundName)
{
if (this.MusicPacks.ContainsKey(packName))
{
this.MusicPacks[packName].PlaySound(soundName);
}
else
{
ModCore.DebugLog("No pack with specified key/name: " + packName);
}
}
/// <summary>
/// Stops a said sound from the music pack.
/// </summary>
/// <param name="packName"></param>
/// <param name="soundName"></param>
public void stopSound(string packName,string soundName)
{
if (this.MusicPacks.ContainsKey(packName))
{
this.MusicPacks[packName].StopSound();
}
else
{
ModCore.DebugLog("No pack with specified key/name: " + packName);
}
}
/// <summary>
/// Updates all music packs every so often.
/// </summary>
public void update()
{
foreach(MusicPack pack in this.MusicPacks.Values)
{
pack.update();
}
}
}
}

View File

@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using NAudio.Vorbis;
using NAudio.Wave;
using StardewModdingAPI;
using StardewValley;
namespace SimpleSoundManager.Framework
{
/// <summary>A content pack which can provide music and sounds.</summary>
public class MusicPack
{
/*********
** Fields
*********/
/// <summary>The name of the folder which contains the saved player settings.</summary>
private readonly string DataFolderName = "data";
/// <summary>The name of the folder which contains available music.</summary>
private readonly string MusicFolderName = "music";
/*********
** Accessors
*********/
/// <summary>The underlying content pack.</summary>
public IContentPack ContentPack { get; }
/// <summary>The current song name being played, if any.</summary>
public string lastPlayedSoundName { get; private set; }
/// <summary>The currently sound being played, if any.</summary>
public SoundEffectInstance lastPlayedSound { get; private set; }
public Dictionary<string, List<SoundEffectInstance>> playingSounds;
/// <summary>The manifest info.</summary>
public IManifest Manifest => this.ContentPack.Manifest;
/// <summary>The name of the music pack.</summary>
public string Name => this.ContentPack.Manifest.Name;
/// <summary>The available sounds.</summary>
public Dictionary<string, SoundEffectInstance> Sounds { get; } = new Dictionary<string, SoundEffectInstance>();
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="contentPack">The underlying content pack.</param>
public MusicPack(IContentPack contentPack)
{
this.ContentPack = contentPack;
this.playingSounds = new Dictionary<string, List<SoundEffectInstance>>();
this.LoadMusicFiles();
}
/// <summary>Play a song.</summary>
/// <param name="name">The song name to play.</param>
public void PlaySound(string name)
{
// get sound
if (!this.Sounds.TryGetValue(name, out SoundEffectInstance sound))
{
ModCore.ModMonitor.Log("An error occured where we can't find the song anymore. Weird. Please contact Omegasis with a SMAPI Log and describe when/how the event occured.");
return;
}
// play sound
this.lastPlayedSoundName = name;
this.lastPlayedSound = sound;
this.lastPlayedSound.Play();
if (this.playingSounds.ContainsKey(name))
{
this.playingSounds[name].Add(sound);
}
else
{
this.playingSounds.Add(name,new List<SoundEffectInstance>());
this.playingSounds[name].Add(sound);
}
}
/// <summary>Stop the currently playing song.</summary>
public void StopSound()
{
this.lastPlayedSound?.Stop(true);
this.lastPlayedSoundName = null;
}
/// <summary>
/// Stops all of the currently playing sounds.
/// </summary>
public void stopAllSounds()
{
foreach (string soundName in playingSounds.Keys)
{
for (int i = 0; i < playingSounds[soundName].Count; i++)
{
if (playingSounds[soundName][i].State == SoundState.Stopped)
{
playingSounds[soundName][i].Stop(true);
continue;
}
}
}
}
/// <summary>
/// Updates the music pack to clean up all sounds that have been stopped.
/// </summary>
public void update()
{
///Clean up the list.
foreach(string soundName in playingSounds.Keys)
{
for(int i = 0; i < playingSounds[soundName].Count; i++)
{
if(playingSounds[soundName][i].State== SoundState.Stopped)
{
playingSounds[soundName].RemoveAt(i);
i--;
continue;
}
}
}
}
/// <summary>Get whether the content pack is currently playing a sound.</summary>
public bool IsPlaying()
{
return this.lastPlayedSound?.State == SoundState.Playing;
}
/// <summary>
/// Checks if there is a sound with said name playing.
/// </summary>
/// <param name="SoundName"></param>
/// <returns></returns>
public bool IsPlaying(string SoundName)
{
return this.playingSounds[SoundName].FindAll(s => s.State== SoundState.Playing).Count>0;
}
/*********
** Private methods
*********/
/// <summary>Load in the music files from the pack's respective Directory/Songs folder. Typically Content/Music/Wav/FolderName/Songs</summary>
private void LoadMusicFiles()
{
DateTime startTime = DateTime.Now;
DirectoryInfo songFolder = new DirectoryInfo(Path.Combine(this.ContentPack.DirectoryPath, this.MusicFolderName));
foreach (FileInfo file in songFolder.GetFiles())
{
// get name
string name = Path.GetFileNameWithoutExtension(file.Name);
if (this.Sounds.ContainsKey(name))
continue;
// load data
SoundEffect effect = null;
using (Stream waveFileStream = File.OpenRead(file.FullName))
{
switch (file.Extension)
{
case ".wav":
effect = SoundEffect.FromStream(waveFileStream);
break;
case ".mp3":
using (Mp3FileReader reader = new Mp3FileReader(waveFileStream))
using (WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(reader))
{
string tempPath = Path.Combine(songFolder.FullName, $"{name}.wav");
ModCore.ModMonitor.Log($"Converting: {tempPath}");
WaveFileWriter.CreateWaveFile(tempPath, pcmStream);
using (Stream tempStream = File.OpenRead(tempPath))
effect = SoundEffect.FromStream(tempStream);
File.Delete(tempPath);
}
break;
case ".ogg":
// Credits: https://social.msdn.microsoft.com/Forums/vstudio/en-US/100a97af-2a1c-4b28-b464-d43611b9b5d6/converting-multichannel-ogg-to-stereo-wav-file?forum=csharpgeneral
using (VorbisWaveReader vorbisStream = new VorbisWaveReader(file.FullName))
{
string tempPath = Path.Combine(songFolder.FullName, $"{name}.wav");
ModCore.DebugLog($"Converting: {tempPath}");
WaveFileWriter.CreateWaveFile(tempPath, vorbisStream.ToWaveProvider16());
using (Stream tempStream = File.OpenRead(tempPath))
effect = SoundEffect.FromStream(tempStream);
File.Delete(tempPath);
}
break;
default:
ModCore.ModMonitor.Log($"Unsupported file extension {file.Extension}.", LogLevel.Warn);
break;
}
}
if (effect == null)
continue;
// add sound
SoundEffectInstance instance = effect.CreateInstance();
this.Sounds.Add(name, instance);
}
// log loading time
if (ModCore.Config.EnableDebugLog)
ModCore.ModMonitor.Log($"Time to load WAV music pack {this.Name}: {startTime.Subtract(DateTime.Now)}");
}
}
}

View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Linq;
namespace SimpleSoundManager.Framework
{
/// <summary>A class that keeps track of the trigger and the list of songs associated with that trigger.</summary>
internal class SongListNode
{
/*********
** Accessors
*********/
/// <summary>The trigger name for the list of songs.</summary>
public string Trigger { get; }
/// <summary>The list of songs associated with a trigger.</summary>
public string[] SongList { get; }
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="trigger">The trigger name for the list of songs.</param>
/// <param name="songList">The list of songs associated with a trigger.</param>
public SongListNode(string trigger, IEnumerable<string> songList)
{
this.Trigger = trigger;
this.SongList = songList.ToArray();
}
}
}

View File

@ -1,27 +0,0 @@
namespace SimpleSoundManager.Framework
{
/// <summary>Interface used for common sound functionality;</summary>
public interface Sound
{
/// <summary>Handles playing a sound.</summary>
void play();
void play(float volume);
/// <summary>Handles pausing a song.</summary>
void pause();
/// <summary>Handles stopping a song.</summary>
void stop();
/// <summary>Handles restarting a song.</summary>
void restart();
/// <summary>Handles getting a clone of the song.</summary>
Sound clone();
string getSoundName();
bool isStopped();
}
}

View File

@ -1,202 +0,0 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework.Audio;
using StardewModdingAPI;
using StardewValley;
namespace SimpleSoundManager.Framework
{
public class SoundManager
{
public Dictionary<string, Sound> sounds;
public Dictionary<string, XACTMusicPair> musicBanks;
public float volume;
public List<Sound> currentlyPlayingSounds = new List<Sound>();
/// <summary>Constructor for this class.</summary>
public SoundManager()
{
this.sounds = new Dictionary<string, Sound>();
this.musicBanks = new Dictionary<string, XACTMusicPair>();
this.currentlyPlayingSounds = new List<Sound>();
this.volume = 1.0f;
}
/// <summary>Constructor for wav files.</summary>
public void loadWavFile(string soundName, string pathToWav)
{
WavSound wav = new WavSound(soundName, pathToWav);
SimpleSoundManagerMod.ModMonitor.Log("Getting sound file:" + soundName);
try
{
this.sounds.Add(soundName, wav);
}
catch { }
}
/// <summary>Constructor for wav files.</summary>
public void loadWavFile(IModHelper helper, string soundName, string relativePath)
{
WavSound wav = new WavSound(helper, soundName, relativePath);
SimpleSoundManagerMod.ModMonitor.Log("Getting sound file:" + soundName);
try
{
this.sounds.Add(soundName, wav);
}
catch
{
//Sound already added so no need to worry?
}
}
/// <summary>Constructor for wav files.</summary>
public void loadWavFile(IModHelper helper, string songName, List<string> pathToWav)
{
WavSound wav = new WavSound(helper, songName, pathToWav);
SimpleSoundManagerMod.ModMonitor.Log("Getting sound file:" + songName);
try
{
this.sounds.Add(songName, wav);
}
catch { }
}
/// <summary>Constructor for XACT files.</summary>
public void loadXACTFile(WaveBank waveBank, ISoundBank soundBank, string songName)
{
XACTSound xactSound = new XACTSound(waveBank, soundBank, songName);
this.sounds.Add(songName, xactSound);
}
/// <summary>Constructor for XACT files based on already added music packs.</summary>
public void loadXACTFile(string pairName, string songName)
{
XACTMusicPair musicPair = this.getMusicPack(pairName);
if (pairName == null)
return;
this.loadXACTFile(musicPair.waveBank, musicPair.soundBank, songName);
}
/// <summary>Creates a music pack pair that holds .xwb and .xsb music files.</summary>
/// <param name="helper">The mod's helper that will handle the path of the files.</param>
/// <param name="pairName">The name of this music pack pair.</param>
/// <param name="wavName">The relative path to the .xwb file</param>
/// <param name="soundName">The relative path to the .xsb file</param>
public void loadXACTMusicBank(IModHelper helper, string pairName, string wavName, string soundName)
{
this.musicBanks.Add(pairName, new XACTMusicPair(helper, wavName, soundName));
}
/// <summary>Gets the music pack pair from the sound pool.</summary>
public XACTMusicPair getMusicPack(string name)
{
foreach (var pack in this.musicBanks)
{
if (name == pack.Key)
return pack.Value;
}
return null;
}
/// <summary>Gets a clone of the loaded sound.</summary>
public Sound getSoundClone(string name)
{
foreach (var sound in this.sounds)
{
if (sound.Key == name)
return sound.Value.clone();
}
return null;
}
/// <summary>Play the sound with the given name.</summary>
public void playSound(string soundName)
{
SimpleSoundManagerMod.ModMonitor.Log("Trying to play sound: " + soundName);
foreach (var sound in this.sounds)
{
if (sound.Key == soundName)
{
SimpleSoundManagerMod.ModMonitor.Log("Time to play sound: " + soundName);
var s = this.getSoundClone(soundName);
s.play(this.volume);
this.currentlyPlayingSounds.Add(s);
break;
}
}
}
/// <summary>Play the sound with the given name and volume.</summary>
public void playSound(string soundName, float volume = 1.0f)
{
SimpleSoundManagerMod.ModMonitor.Log("Trying to play sound: " + soundName);
foreach (var sound in this.sounds)
{
if (sound.Key == soundName)
{
SimpleSoundManagerMod.ModMonitor.Log("Time to play sound: " + soundName);
var s = this.getSoundClone(soundName);
s.play(volume);
this.currentlyPlayingSounds.Add(s);
break;
}
}
}
/// <summary>Stop the sound that is playing.</summary>
public void stopSound(string soundName)
{
List<Sound> removalList = new List<Sound>();
foreach (var sound in this.currentlyPlayingSounds)
{
if (sound.getSoundName() == soundName)
{
sound.stop();
removalList.Add(sound);
}
}
foreach (var v in removalList)
this.currentlyPlayingSounds.Remove(v);
}
/// <summary>Pause the sound with this name?</summary>
public void pauseSound(string soundName)
{
List<Sound> removalList = new List<Sound>();
foreach (var sound in this.currentlyPlayingSounds)
{
if (sound.getSoundName() == soundName)
{
sound.pause();
removalList.Add(sound);
}
}
foreach (var v in removalList)
this.currentlyPlayingSounds.Remove(v);
}
public void swapSounds(string newSong)
{
this.playSound(newSong);
}
public void update()
{
List<Sound> removalList = new List<Sound>();
foreach (Sound song in this.currentlyPlayingSounds)
{
if (song.isStopped())
removalList.Add(song);
}
foreach (var v in removalList)
this.currentlyPlayingSounds.Remove(v);
}
public void stopAllSounds()
{
foreach (var v in this.currentlyPlayingSounds)
v.stop();
}
}
}

View File

@ -1,211 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework.Audio;
using SimpleSoundManager.Framework;
using StardewModdingAPI;
namespace SimpleSoundManager
{
class WavSound : Sound
{
/// <summary>Used to actually play the song.</summary>
DynamicSoundEffectInstance dynamicSound;
/// <summary>Used to keep track of where in the song we are.</summary>
int position;
int count;
/// <summary>Used to store the info for the song.</summary>
byte[] byteArray;
public string path;
public string soundName;
public bool loop;
/// <summary>Get a raw disk path to the wav file.</summary>
public WavSound(string name, string pathToWavFile, bool loop = false)
{
this.path = pathToWavFile;
this.LoadWavFromFileToStream();
this.soundName = name;
this.loop = loop;
}
/// <summary>A constructor that takes a mod helper and a relative path to a wav file.</summary>
public WavSound(IModHelper modHelper, string name, string relativePath, bool loop = false)
{
string path = Path.Combine(modHelper.DirectoryPath, relativePath);
this.path = path;
this.soundName = name;
this.loop = loop;
}
/// <summary>Constructor that is more flexible than typing an absolute path.</summary>
/// <param name="modHelper">The mod helper for the mod you wish to use to load the music files from.</param>
/// <param name="pathPieces">The list of folders and files that make up a complete path.</param>
public WavSound(IModHelper modHelper, string soundName, List<string> pathPieces, bool loop = false)
{
string dirPath = modHelper.DirectoryPath;
foreach (string str in pathPieces)
dirPath = Path.Combine(dirPath, str);
this.path = dirPath;
this.soundName = soundName;
this.loop = loop;
}
/// <summary>Loads the .wav file from disk and plays it.</summary>
public void LoadWavFromFileToStream()
{
// Create a new SpriteBatch, which can be used to draw textures.
string file = this.path;
Stream waveFileStream = File.OpenRead(file); //TitleContainer.OpenStream(file);
BinaryReader reader = new BinaryReader(waveFileStream);
int chunkID = reader.ReadInt32();
int fileSize = reader.ReadInt32();
int riffType = reader.ReadInt32();
int fmtID = reader.ReadInt32();
int fmtSize = reader.ReadInt32();
int fmtCode = reader.ReadInt16();
int channels = reader.ReadInt16();
int sampleRate = reader.ReadInt32();
int fmtAvgBPS = reader.ReadInt32();
int fmtBlockAlign = reader.ReadInt16();
int bitDepth = reader.ReadInt16();
if (fmtSize == 18)
{
// Read any extra values
int fmtExtraSize = reader.ReadInt16();
reader.ReadBytes(fmtExtraSize);
}
int dataID = reader.ReadInt32();
int dataSize = reader.ReadInt32();
this.byteArray = reader.ReadBytes(dataSize);
this.dynamicSound = new DynamicSoundEffectInstance(sampleRate, (AudioChannels)channels);
this.count = this.byteArray.Length;//dynamicSound.GetSampleSizeInBytes(TimeSpan.FromMilliseconds(1000));
this.dynamicSound.BufferNeeded += this.DynamicSound_BufferNeeded;
}
void DynamicSound_BufferNeeded(object sender, EventArgs e)
{
try
{
this.dynamicSound.SubmitBuffer(this.byteArray, this.position, this.count);
}
catch { }
this.position += this.count;
if (this.position + this.count > this.byteArray.Length)
{
if (this.loop)
this.position = 0;
//else
// this.stop();
}
}
/// <summary>Used to pause the current song.</summary>
public void pause()
{
this.dynamicSound?.Pause();
}
/// <summary>Used to play a song.</summary>
public void play()
{
if (this.isPlaying())
return;
this.LoadWavFromFileToStream();
this.dynamicSound.Play();
}
/// <summary>Used to play a song.</summary>
/// <param name="volume">How lound the sound is when playing. 0~1.0f</param>
public void play(float volume)
{
if (this.isPlaying())
return;
this.LoadWavFromFileToStream();
this.dynamicSound.Volume = volume;
this.dynamicSound.Play();
}
/// <summary>Used to resume the currently playing song.</summary>
public void resume()
{
this.dynamicSound?.Resume();
}
/// <summary>Used to stop the currently playing song.</summary>
public void stop()
{
if (this.dynamicSound != null)
{
this.dynamicSound.Stop(true);
this.dynamicSound.BufferNeeded -= this.DynamicSound_BufferNeeded;
this.position = 0;
this.count = 0;
this.byteArray = new byte[0];
}
}
/// <summary>Used to change from one playing song to another;</summary>
public void swap(string pathToNewWavFile)
{
this.stop();
this.path = pathToNewWavFile;
this.play();
}
/// <summary>Checks if the song is currently playing.</summary>
public bool isPlaying()
{
return this.dynamicSound?.State == SoundState.Playing;
}
/// <summary>Checks if the song is currently paused.</summary>
public bool isPaused()
{
return this.dynamicSound?.State == SoundState.Paused;
}
/// <summary>Checks if the song is currently stopped.</summary>
public bool isStopped()
{
return this.dynamicSound?.State == SoundState.Stopped;
}
public Sound clone()
{
return new WavSound(this.getSoundName(), this.path);
}
public string getSoundName()
{
return this.soundName;
}
public void restart()
{
this.stop();
this.play();
}
}
}

View File

@ -1,118 +0,0 @@
using Microsoft.Xna.Framework.Audio;
using StardewValley;
namespace SimpleSoundManager.Framework
{
public class XACTSound : Sound
{
public WaveBank waveBank;
public ISoundBank soundBank;
public string soundName;
readonly WaveBank vanillaWaveBank;
readonly ISoundBank vanillaSoundBank;
readonly Cue song;
/// <summary>Make a new Sound Manager to play and manage sounds in a modded wave bank.</summary>
/// <param name="newWaveBank">The reference to the wave bank in the mod's asset folder.</param>
/// <param name="newSoundBank">The reference to the sound bank in the mod's asset folder.</param>
public XACTSound(WaveBank newWaveBank, ISoundBank newSoundBank, string soundName)
{
this.waveBank = newWaveBank;
this.soundBank = newSoundBank;
this.vanillaSoundBank = Game1.soundBank;
this.vanillaWaveBank = Game1.waveBank;
this.soundName = soundName;
this.song = this.soundBank.GetCue(this.soundName);
}
/// <summary>Play a sound from the mod's wave bank.</summary>
/// <param name="soundName">The name of the sound in the mod's wave bank. This will fail if the sound doesn't exists. This is also case sensitive.</param>
public void play(string soundName)
{
Game1.waveBank = this.waveBank;
Game1.soundBank = this.soundBank;
if (this.song == null) return;
this.song.Play();
Game1.waveBank = this.vanillaWaveBank;
Game1.soundBank = this.vanillaSoundBank;
}
/// <summary>Pauses the first instance of this sound.</summary>
/// <param name="soundName"></param>
public void pause(string soundName)
{
this.song?.Pause();
}
/// <summary>Resume the first instance of the sound that has this name.</summary>
public void resume(string soundName)
{
this.song?.Resume();
}
/// <summary>Stop the first instance of the sound that has this name.</summary>
/// <param name="soundName"></param>
public void stop(string soundName)
{
this.song?.Stop(AudioStopOptions.Immediate);
}
/// <summary>Resumes a paused song.</summary>
public void resume()
{
this.resume(this.soundName);
}
/// <summary>Plays this song.</summary>
public void play()
{
this.play(this.soundName);
}
/// <summary>Plays this song.</summary>
public void play(float volume)
{
this.play(this.soundName);
}
/// <summary>Pauses this song.</summary>
public void pause()
{
this.pause(this.soundName);
}
/// <summary>Stops this somg.</summary>
public void stop()
{
this.stop(this.soundName);
}
/// <summary>Restarts this song.</summary>
public void restart()
{
this.stop();
this.play();
}
/// <summary>Gets a clone of this song.</summary>
public Sound clone()
{
return new XACTSound(this.waveBank, this.soundBank, this.soundName);
}
public string getSoundName()
{
return this.soundName;
}
public bool isStopped()
{
return this.song == null || this.song.IsStopped;
}
}
}

View File

@ -1,26 +0,0 @@
using System.IO;
using Microsoft.Xna.Framework.Audio;
using StardewModdingAPI;
using StardewValley;
namespace SimpleSoundManager
{
public class XACTMusicPair
{
public WaveBank waveBank;
public ISoundBank soundBank;
/// <summary>Create a xwb and xsb music pack pair.</summary>
/// <param name="helper">The mod helper from the mod that will handle loading in the file.</param>
/// <param name="wavBankPath">A relative path to the .xwb file in the mod helper's mod directory.</param>
/// <param name="soundBankPath">A relative path to the .xsb file in the mod helper's mod directory.</param>
public XACTMusicPair(IModHelper helper, string wavBankPath, string soundBankPath)
{
wavBankPath = Path.Combine(helper.DirectoryPath, wavBankPath);
soundBankPath = Path.Combine(helper.DirectoryPath, soundBankPath);
this.waveBank = new WaveBank(Game1.audioEngine, wavBankPath);
this.soundBank = new SoundBankWrapper(new SoundBank(Game1.audioEngine, soundBankPath));
}
}
}

View File

@ -0,0 +1,62 @@
using SimpleSoundManager.Framework;
using SimpleSoundManager.Framework.Music;
using StardewModdingAPI;
namespace SimpleSoundManager
{
public class ModCore : Mod
{
internal static IModHelper ModHelper;
internal static IMonitor ModMonitor;
internal static Config Config;
public static MusicManager MusicManager;
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper)
{
ModHelper = helper;
ModMonitor = this.Monitor;
Config = helper.ReadConfig<Config>();
this.loadContentPacks();
this.Helper.Events.GameLoop.OneSecondUpdateTicked += this.GameLoop_OneSecondUpdateTicked;
}
/// <summary>
/// Update all music packs every second.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void GameLoop_OneSecondUpdateTicked(object sender, StardewModdingAPI.Events.OneSecondUpdateTickedEventArgs e)
{
foreach(MusicPack pack in MusicManager.MusicPacks.Values)
{
pack.update();
}
}
/// <summary>
/// Loads all content packs for SimpleSoundManager
/// </summary>
private void loadContentPacks()
{
MusicManager = new MusicManager();
foreach (IContentPack contentPack in this.Helper.ContentPacks.GetOwned())
{
this.Monitor.Log($"Reading content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}");
MusicPack musicPack = new MusicPack(contentPack);
MusicManager.addMusicPack(musicPack, true, true);
}
}
/// <summary>
/// Easy way to display debug logs when allowing for a check to see if they are enabled.
/// </summary>
/// <param name="s">The message to display.</param>
public static void DebugLog(string s)
{
if (Config.EnableDebugLog)
ModMonitor.Log(s);
}
}
}

View File

@ -66,6 +66,12 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NAudio">
<Version>1.8.5</Version>
</PackageReference>
<PackageReference Include="NAudio.Vorbis">
<Version>1.0.0</Version>
</PackageReference>
<PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
@ -73,12 +79,11 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Framework\Sound.cs" />
<Compile Include="Framework\SoundManager.cs" />
<Compile Include="Framework\WavSound.cs" />
<Compile Include="Framework\XactMusicPair.cs" />
<Compile Include="Framework\XACTSound.cs" />
<Compile Include="SimpleSoundManagerMod.cs" />
<Compile Include="Framework\Music\Config.cs" />
<Compile Include="Framework\Music\MusicManager.cs" />
<Compile Include="Framework\Music\MusicPack.cs" />
<Compile Include="Framework\Music\SongListNode.cs" />
<Compile Include="ModCore.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -1,18 +0,0 @@
using StardewModdingAPI;
namespace SimpleSoundManager
{
public class SimpleSoundManagerMod : Mod
{
internal static IModHelper ModHelper;
internal static IMonitor ModMonitor;
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper)
{
ModHelper = helper;
ModMonitor = this.Monitor;
}
}
}