using Microsoft.Xna.Framework.Audio; using SimpleSoundManager.Framework; using StardewModdingAPI; using StardewValley; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleSoundManager { class WavSound : Sound { /// /// Used to actually play the song. /// DynamicSoundEffectInstance dynamicSound; /// /// Used to keep track of where in the song we are. /// int position; /// /// ??? /// int count; /// /// Used to store the info for the song. /// byte[] byteArray; public string path; public string soundName; /// /// Get a raw disk path to the wav file. /// /// public WavSound(string name,string pathToWavFile) { this.path = pathToWavFile; LoadWavFromFileToStream(); this.soundName = name; } /// /// A constructor that takes a mod helper and a relative path to a wav file. /// /// /// public WavSound(IModHelper modHelper,string name, string pathInModDirectory) { string path = Path.Combine(modHelper.DirectoryPath, pathInModDirectory); this.path = path; this.soundName = name; } /// /// Constructor that is more flexible than typing an absolute path. /// /// The mod helper for the mod you wish to use to load the music files from. /// The list of folders and files that make up a complete path. public WavSound(IModHelper modHelper,string soundName, List pathPieces) { string s = modHelper.DirectoryPath; foreach(var str in pathPieces) { s = Path.Combine(s, str); } this.path = s; this.soundName = soundName; } /// /// Loads the .wav file from disk and plays it. /// public void LoadWavFromFileToStream() { // Create a new SpriteBatch, which can be used to draw textures. string file = this.path; System.IO.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(); byteArray = reader.ReadBytes(dataSize); dynamicSound = new DynamicSoundEffectInstance(sampleRate, (AudioChannels)channels); count = dynamicSound.GetSampleSizeInBytes(TimeSpan.FromMilliseconds(10000)); } void DynamicSound_BufferNeeded(object sender, EventArgs e) { try { dynamicSound.SubmitBuffer(byteArray, position, count); } catch (Exception err) { } position += count; if (position + count > byteArray.Length) { position = 0; } } /// /// Used to pause the current song. /// public void pause() { if (dynamicSound != null) dynamicSound.Pause(); } /// /// Used to play a song. /// /// public void play() { if (this.isPlaying() == true) return; dynamicSound.BufferNeeded += new EventHandler(DynamicSound_BufferNeeded); dynamicSound.Play(); } /// /// Used to resume the currently playing song. /// public void resume() { if (dynamicSound == null) return; dynamicSound.Resume(); } /// /// Used to stop the currently playing song. /// public void stop() { if (dynamicSound != null) { dynamicSound.Stop(true); dynamicSound.BufferNeeded -= new EventHandler(DynamicSound_BufferNeeded); position = 0; count = 0; byteArray = new byte[0]; } } /// /// Used to change from one playing song to another; /// /// public void swap(string pathToNewWavFile) { this.stop(); this.path = pathToNewWavFile; this.play(); } /// /// Checks if the song is currently playing. /// /// public bool isPlaying() { if (this.dynamicSound == null) return false; if (this.dynamicSound.State == SoundState.Playing) return true; else return false; } /// /// Checks if the song is currently paused. /// /// public bool isPaused() { if (this.dynamicSound == null) return false; if (this.dynamicSound.State == SoundState.Paused) return true; else return false; } /// /// Checks if the song is currently stopped. /// /// public bool isStopped() { if (this.dynamicSound == null) return false; if (this.dynamicSound.State == SoundState.Stopped) return true; else return false; } public Sound clone() { return new WavSound(this.getSoundName(),this.path); } public string getSoundName() { return this.soundName; } public void restart() { this.stop(); this.play(); } } }