Finished writing functionality for WAV music packs. fixed issue when loading in songs, made sure initial sound keys are propperly loaded, and have implemented support for custom title screen music.

This commit is contained in:
2018-02-05 17:31:59 -08:00
parent aed71ac4db
commit 45bfa5731f
7 changed files with 374 additions and 17 deletions

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework.Graphics;
namespace StardewSymphonyRemastered.Framework.Menus
{
class MusicManagerMenu : StardewValley.Menus.IClickableMenu
{
public override void receiveRightClick(int x, int y, bool playSound = true)
{
throw new NotImplementedException();
}
public override void drawBackground(SpriteBatch b)
{
base.drawBackground(b);
}
}
}

View File

@ -174,10 +174,17 @@ namespace StardewSymphonyRemastered.Framework
Dictionary<MusicPack, List<Song>> listOfValidDictionaries = new Dictionary<MusicPack, List<Song>>();
foreach(var v in this.musicPacks)
{
var songList= v.Value.songInformation.getSongList(songListKey).Value;
if (songList.Count > 0)
try
{
listOfValidDictionaries.Add(v.Value, songList);
var songList = v.Value.songInformation.getSongList(songListKey).Value;
if (songList.Count > 0)
{
listOfValidDictionaries.Add(v.Value, songList);
}
}
catch(Exception err)
{
}
}
return listOfValidDictionaries;
@ -189,14 +196,101 @@ namespace StardewSymphonyRemastered.Framework
/// <param name="songListKey"></param>
public void selectMusic(string songListKey)
{
var listOfValidMusicPacks = getListOfApplicableMusicPacks(songListKey);
string subKey = songListKey;
//Try to get more specific.
//This chunk is to determine song specifics for location.
while (listOfValidMusicPacks.Count == 0)
{
if (subKey.Length == 0) break;
string[] subList= subKey.Split(SongSpecifics.seperator);
if (subList.Length == 0) break; //Because things would go bad otherwise.
subKey = "";
for(int i = 0; i < subList.Length-1; i++)
{
subKey += subList[i];
if (i != subList.Length - 2)
{
subKey += SongSpecifics.seperator;
}
}
if (subKey == "") break;
StardewSymphony.ModMonitor.Log(subKey,StardewModdingAPI.LogLevel.Alert);
listOfValidMusicPacks = getListOfApplicableMusicPacks(subKey);
if (listOfValidMusicPacks.Count == 0)
{
//No valid songs to play at this time.
StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + subKey + ". Are you sure you did this properly?");
//return;
}
}
if (listOfValidMusicPacks.Count == 0)
{
//This chunk is used to determine more general seasonal specifics if song specifics couldn't be found.
subKey = songListKey;
string[] season = subKey.Split(SongSpecifics.seperator);
subKey = "";
for (int i = 1; i < season.Length; i++)
{
subKey += season[i];
if (i != season.Length - 1)
{
subKey += SongSpecifics.seperator;
}
}
if (string.IsNullOrEmpty(subKey))
{
StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + songListKey + ". Are you sure you did this properly?");
return;
}
StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert);
listOfValidMusicPacks = getListOfApplicableMusicPacks(subKey);
if (listOfValidMusicPacks.Count == 0)
{
//No valid songs to play at this time.
StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + subKey + ". Are you sure you did this properly?");
//return;
}
//Try to get more specific.
while (listOfValidMusicPacks.Count == 0)
{
if (subKey.Length == 0) break;
string[] subList = subKey.Split(SongSpecifics.seperator);
if (subList.Length == 0) break; //Because things would go bad otherwise.
subKey = "";
for (int i = 0; i < subList.Length - 1; i++)
{
subKey += subList[i];
if (i != subList.Length - 2)
{
subKey += SongSpecifics.seperator;
}
}
if (subKey == "") break;
StardewSymphony.ModMonitor.Log(subKey, StardewModdingAPI.LogLevel.Alert);
listOfValidMusicPacks = getListOfApplicableMusicPacks(subKey);
if (listOfValidMusicPacks.Count == 0)
{
//No valid songs to play at this time.
StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + subKey + ". Are you sure you did this properly?");
//return;
}
}
}
if (listOfValidMusicPacks.Count == 0)
{
//No valid songs to play at this time.
StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack. Are you sure you did this properly?");
StardewSymphony.ModMonitor.Log("Error: There are no songs to play across any music pack for the song key: " + songListKey + ". Are you sure you did this properly?");
return;
}
int randInt = packSelector.Next(0, listOfValidMusicPacks.Count-1);
var musicPackPair = listOfValidMusicPacks.ElementAt(randInt);
@ -240,7 +334,25 @@ namespace StardewSymphonyRemastered.Framework
}
}
}
/*
if(musicPack.GetType()==typeof(WavMusicPack)){
foreach (var song in musicPack.songInformation.listOfSongsWithoutTriggers)
{
(musicPack as WavMusicPack).LoadWavFromFileToStream(song.pathToSong);
}
}
*/
this.musicPacks.Add(musicPack.musicPackInformation.name,musicPack);
}
public void initializeSeasonalMusic()
{
foreach(var pack in this.musicPacks)
{
pack.Value.songInformation.initializeSeasonalMusic();
}
}
}
}

View File

@ -9,6 +9,10 @@ namespace StardewSymphonyRemastered.Framework
{
/// <summary>
/// The class to be used to manage individual songs.
///
///
///
/// TODO: MAKE SMALL RELATIVE PATH TO SONG. /CONTENT/MUSIC/SONG
/// </summary>
public class Song
{
@ -22,6 +26,11 @@ namespace StardewSymphonyRemastered.Framework
/// </summary>
public string name;
/// <summary>
/// The relative path to the song.
/// </summary>
public string relativePath;
/// <summary>
/// Blank Constructor;
/// </summary>
@ -38,6 +47,7 @@ namespace StardewSymphonyRemastered.Framework
{
this.pathToSong=PathToSong;
this.name = getNameFromPath(this.pathToSong);
this.relativePath = this.getRelativePathFromFullPath();
}
/// <summary>
@ -49,6 +59,7 @@ namespace StardewSymphonyRemastered.Framework
{
this.pathToSong = PathToSong;
this.name = Name;
this.relativePath = this.getRelativePathFromFullPath();
}
/// <summary>
@ -61,6 +72,31 @@ namespace StardewSymphonyRemastered.Framework
return Path.GetFileNameWithoutExtension(path);
}
public string getRelativePathFromFullPath()
{
string[] spliter = this.pathToSong.Split(Path.DirectorySeparatorChar);
string relative = "";
int index = 0;
foreach(var str in spliter) //iterate across all of the strings until Content is found.
{
if (str == "Content")
{
//Once content is found add it to the relative string and append a newline character.
for(int i = index; i < spliter.Length; i++)
{
relative += spliter[i];
if (i != spliter.Length - 1)
{
relative += Path.DirectorySeparatorChar;
}
}
}
index++;
}
return relative; //Return the relative path string
}
/// <summary>
/// Read the info from a .json file.
/// </summary>

View File

@ -30,6 +30,7 @@ namespace StardewSymphonyRemastered.Framework
string[] weather;
string[] daysOfWeek;
string[] timesOfDay;
List<string> menus;
public static char seperator = '_';
/// <summary>
@ -70,15 +71,16 @@ namespace StardewSymphonyRemastered.Framework
"day",
"night"
};
menus = new List<string>();
menus.Add(typeof(StardewValley.Menus.TitleMenu).ToString());
listOfSongsWithTriggers = new Dictionary<string, List<Song>>();
eventSongs = new Dictionary<string, List<Song>>();
festivalSongs = new Dictionary<string, List<Song>>();
this.listOfSongsWithoutTriggers = new List<Song>();
this.addSongLists();
this.addMenuMusic();
}
@ -96,6 +98,7 @@ namespace StardewSymphonyRemastered.Framework
public static string getCurrentConditionalString()
{
string key = "";
bool foundMenuString = false;
if (Game1.eventUp == true)
{
//Get the event id an hijack it with some different music
@ -106,10 +109,25 @@ namespace StardewSymphonyRemastered.Framework
//hijack the name of the festival and load some different songs
// string s="Festival_FestivalName";
}
else if (Game1.activeClickableMenu!=null)
{
if (Game1.activeClickableMenu.GetType() == typeof(StardewValley.Menus.TitleMenu))
{
key = Game1.activeClickableMenu.GetType().ToString();
foundMenuString = true;
}
}
else
{
key = getLocationString() + seperator + getSeasonNameString() + seperator + getWeatherString() + seperator + getDayOfWeekString() + seperator + getTimeOfDayString();
}
if(foundMenuString==false && key == "")
{
key = getLocationString() + seperator + getSeasonNameString() + seperator + getWeatherString() + seperator + getDayOfWeekString() + seperator + getTimeOfDayString();
}
return key;
}
@ -123,6 +141,7 @@ namespace StardewSymphonyRemastered.Framework
foreach (var v in Game1.locations)
{
locations.Add(v.name);
StardewSymphony.ModMonitor.Log("Adding in song triggers for location: " + v.name);
}
}
@ -252,6 +271,12 @@ namespace StardewSymphonyRemastered.Framework
{
return Game1.currentLocation.name;
}
public static string getCurrentMenuString()
{
if (Game1.activeClickableMenu == null) return "";
else return Game1.activeClickableMenu.GetType().ToString();
}
#endregion
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
@ -268,6 +293,14 @@ namespace StardewSymphonyRemastered.Framework
this.listOfSongsWithoutTriggers.Add(song);
}
public void addMenuMusic()
{
foreach(var v in menus)
{
this.listOfSongsWithTriggers.Add(v, new List<Song>());
}
}
/// <summary>
/// Checks if the song exists at all in this music pack.
/// </summary>
@ -282,7 +315,7 @@ namespace StardewSymphonyRemastered.Framework
/// <summary>
/// A pretty big function to add in all of the specific songs that play at certain locations_seasons_weather_dayOfWeek_times.
/// </summary>
public void addSongLists()
public void initializeSeasonalMusic()
{
foreach (var loc in locations)
{
@ -331,8 +364,15 @@ namespace StardewSymphonyRemastered.Framework
/// <returns></returns>
public KeyValuePair<string,List<Song>>getSongList(string key)
{
string keyPhrase = key.Split(seperator).ElementAt(0);
string keyPhrase = "";
try
{
keyPhrase= key.Split(seperator).ElementAt(0);
}
catch(Exception err)
{
keyPhrase = key;
}
if (keyPhrase == "event")
{
@ -358,6 +398,7 @@ namespace StardewSymphonyRemastered.Framework
foreach(KeyValuePair<string,List<Song>> pair in listOfSongsWithTriggers)
{
//StardewSymphony.ModMonitor.Log(pair.Key);
if (pair.Key == key) return pair;
}

View File

@ -1,4 +1,6 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -15,6 +17,23 @@ namespace StardewSymphonyRemastered.Framework
public Song currentSong;
public string songsDirectory;
/// <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;
/// <summary>
/// ???
/// </summary>
int count;
/// <summary>
/// Used to store the info for the song.
/// </summary>
byte[] byteArray;
/// <summary>
/// Constructor.
/// </summary>
@ -55,12 +74,69 @@ namespace StardewSymphonyRemastered.Framework
this.shortenedDirectory = directoryLocation;
}
/// <summary>
/// Load a wav file into the stream to be played.
/// </summary>
public void LoadWavFromFileToStream(string p)
{
// Create a new SpriteBatch, which can be used to draw textures.
string file =p;
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(100));
dynamicSound.BufferNeeded += new EventHandler<EventArgs>(DynamicSound_BufferNeeded);
this.currentSong = new Song(p);
}
void DynamicSound_BufferNeeded(object sender, EventArgs e)
{
dynamicSound.SubmitBuffer(byteArray, position, count / 2);
dynamicSound.SubmitBuffer(byteArray, position + count / 2, count / 2);
position += count;
if (position + count > byteArray.Length)
{
position = 0;
}
}
/// <summary>
/// Returns the name of the currently playing song.
/// </summary>
/// <returns></returns>
public override string getNameOfCurrentSong()
{
if (this.currentSong == null) return "";
return this.currentSong.name;
}
@ -79,30 +155,86 @@ namespace StardewSymphonyRemastered.Framework
this.songInformation.listOfSongsWithoutTriggers = listOfSongs;
}
/// <summary>
/// Used to pause the current song.
/// </summary>
public override void pauseSong()
{
throw new NotImplementedException();
if (dynamicSound != null) dynamicSound.Pause();
}
/// <summary>
/// Used to play a song.
/// </summary>
/// <param name="name"></param>
public override void playSong(string name)
{
throw new NotImplementedException();
string pathToSong = getSongPathFromName(name);
LoadWavFromFileToStream(pathToSong);
dynamicSound.Play();
}
/// <summary>
/// Used to resume the currently playing song.
/// </summary>
public override void resumeSong()
{
throw new NotImplementedException();
if (dynamicSound == null) return;
dynamicSound.Resume();
}
/// <summary>
/// Used to stop the currently playing song.
/// </summary>
public override void stopSong()
{
throw new NotImplementedException();
if (dynamicSound != null)
{
dynamicSound.Stop();
dynamicSound = null;
this.currentSong = null;
}
}
/// <summary>
/// Used to change from one playing song to another;
/// </summary>
/// <param name="songName"></param>
public override void swapSong(string songName)
{
throw new NotImplementedException();
this.stopSong();
this.playSong(songName);
}
/// <summary>
/// Get the son's name from the path.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public string getSongNameFromPath(string path)
{
foreach(var song in this.songInformation.listOfSongsWithoutTriggers)
{
if (song.pathToSong == path) return song.name;
}
return "";
}
/// <summary>
/// Gets the song's path that shares the same name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string getSongPathFromName(string name)
{
foreach (var song in this.songInformation.listOfSongsWithoutTriggers)
{
if (song.name == name) return song.pathToSong;
}
return "";
}
}
}

View File

@ -56,6 +56,7 @@ namespace StardewSymphonyRemastered
StardewModdingAPI.Events.SaveEvents.AfterLoad += SaveEvents_AfterLoad;
StardewModdingAPI.Events.LocationEvents.CurrentLocationChanged += LocationEvents_CurrentLocationChanged;
StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
StardewModdingAPI.Events.ControlEvents.KeyPressed += ControlEvents_KeyPressed;
musicManager = new MusicManager();
MusicPath = Path.Combine(ModHelper.DirectoryPath, "Content", "Music");
@ -66,9 +67,19 @@ namespace StardewSymphonyRemastered
this.createDirectories();
this.createBlankXACTTemplate();
this.createBlankWAVTemplate();
musicPacksInitialized = false;
}
private void ControlEvents_KeyPressed(object sender, StardewModdingAPI.Events.EventArgsKeyPressed e)
{
if (e.KeyPressed == Microsoft.Xna.Framework.Input.Keys.O)
{
Game1.activeClickableMenu = new StardewSymphonyRemastered.Framework.Menus.MusicManagerMenu();
}
}
/// <summary>
/// Raised every frame. Mainly used just to initiate the music packs. Probably not needed.
/// </summary>
@ -80,6 +91,7 @@ namespace StardewSymphonyRemastered
{
initializeMusicPacks();
musicPacksInitialized = true;
musicManager.selectMusic(SongSpecifics.getCurrentConditionalString());
}
}
@ -241,6 +253,7 @@ namespace StardewSymphonyRemastered
StardewSymphonyRemastered.Framework.SongSpecifics.addLocations();
StardewSymphonyRemastered.Framework.SongSpecifics.addFestivals();
StardewSymphonyRemastered.Framework.SongSpecifics.addEvents();
musicManager.initializeSeasonalMusic();
}

View File

@ -42,6 +42,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Framework\Menus\MusicManagerMenu.cs" />
<Compile Include="Framework\MusicPackMetaData.cs" />
<Compile Include="Framework\Song.cs" />
<Compile Include="StaticExtentions.cs" />