Implement all audio events and loading/unloading functionality for multi-channel BGM support.
This commit is contained in:
parent
72c8796dcb
commit
91d6beeeab
@ -137,8 +137,9 @@ AiL::AiL()
|
||||
std::string ITEM_STATS_CONFIG = CONFIG_PATH + "item_stats_config"_S;
|
||||
utils::datafile::Read(DATA,ITEM_STATS_CONFIG);
|
||||
|
||||
for(auto&[key,value]:DATA.GetProperty("ItemConfiguration").GetKeys()){
|
||||
std::string config = DATA["ItemConfiguration"][key].GetString();
|
||||
auto keys=DATA.GetProperty("ItemConfiguration");
|
||||
for(auto&[key,value]:keys){
|
||||
std::string config=DATA["ItemConfiguration"][key].GetString();
|
||||
utils::datafile::Read(DATA,CONFIG_PATH + "item_directory"_S + config);
|
||||
}
|
||||
|
||||
@ -242,6 +243,8 @@ bool AiL::OnUserCreate(){
|
||||
|
||||
Stats::InitializeDamageReductionTable();
|
||||
|
||||
Audio::Initialize();
|
||||
|
||||
utils::datafile::INITIAL_SETUP_COMPLETE=true;
|
||||
|
||||
ValidateGameStatus(); //Checks to make sure everything has been initialized properly.
|
||||
|
@ -42,42 +42,59 @@ All rights reserved.
|
||||
INCLUDE_game
|
||||
INCLUDE_DATA
|
||||
|
||||
float Audio::defaultFadeTime;
|
||||
|
||||
void Audio::Initialize(){
|
||||
Audio&instance=game->audioEngine;
|
||||
Self().events.insert("Default Volume");
|
||||
for(auto&[key,data]:DATA["Events"]){
|
||||
instance.events.insert(key);
|
||||
Self().events.insert(key);
|
||||
}
|
||||
for(auto&[songName,data]:DATA["BGM"]){
|
||||
int channelCounter=0;
|
||||
for(auto&[songFileName,size]:DATA["BGM"]){
|
||||
auto&data=DATA["BGM"][songFileName];
|
||||
if(songFileName!="Default Fade Time"){
|
||||
int channelCounter=0;
|
||||
|
||||
BGM&bgm=instance.bgm[songName];
|
||||
BGM&bgm=Self().bgm[songFileName];
|
||||
|
||||
bgm.SetName(data["Track Name"].GetString());
|
||||
bgm.SetFileName(songFileName);
|
||||
bgm.SetName(data["Track Name"].GetString());
|
||||
|
||||
while(data.HasProperty(std::format("channel[{}]",channelCounter))){
|
||||
bgm.AddChannel(data[std::format("channel[{}]",channelCounter)].GetString());
|
||||
channelCounter++;
|
||||
}
|
||||
|
||||
if(!data.HasProperty("Default Volume"))ERR(std::format("WARNING! Track {} does not have a Default Volume parameter!",bgm.GetName()));
|
||||
if(data["Default Volume"].GetValueCount()!=bgm.GetChannelCount())ERR(std::format("WARNING! Default Volume parameters do not match channel count. {} != {}",data["Default Volume"].GetValueCount(),bgm.GetChannelCount()));
|
||||
|
||||
VolumeList volumes;
|
||||
for(int i=0;i<data["Default Volume"].GetValueCount();i++){
|
||||
volumes.push_back(data["Default Volume"].GetInt(i));
|
||||
}
|
||||
bgm.AddEventVolumes("Default Volume",volumes);
|
||||
|
||||
if(data.HasProperty("Fade Time"))bgm.SetFadeTime(data["Fade Time"].GetReal());
|
||||
|
||||
if(data.HasProperty("Events")){
|
||||
for(auto&[eventName,data]:DATA["Events"]){
|
||||
VolumeList volumes;
|
||||
for(int i=0;i<data.GetValueCount();i++){
|
||||
volumes.push_back(data.GetInt(i));
|
||||
}
|
||||
bgm.AddEventVolumes(eventName,volumes);
|
||||
while(data.HasProperty(std::format("channel[{}]",channelCounter))){
|
||||
std::string channelName=data[std::format("channel[{}]",channelCounter)].GetString();
|
||||
if(!std::filesystem::exists("bgm_directory"_S+channelName))ERR(std::format("WARNING! Could not load file {} for track {}",channelName,songFileName));
|
||||
bgm.AddChannel(channelName);
|
||||
channelCounter++;
|
||||
}
|
||||
|
||||
if(!data.HasProperty("Default Volume"))ERR(std::format("WARNING! Track {} does not have a Default Volume parameter!",bgm.GetName()));
|
||||
if(data["Default Volume"].GetValueCount()!=bgm.GetChannelCount())ERR(std::format("WARNING! Default Volume parameters do not match channel count. {} != {}",data["Default Volume"].GetValueCount(),bgm.GetChannelCount()));
|
||||
|
||||
VolumeList volumes;
|
||||
for(int i=0;i<data["Default Volume"].GetValueCount();i++){
|
||||
volumes.push_back(data["Default Volume"].GetInt(i)/100.f);
|
||||
}
|
||||
bgm.AddEventVolumes("Default Volume",volumes);
|
||||
|
||||
if(data.HasProperty("Fade Time")){
|
||||
bgm.SetFadeTime(data["Fade Time"].GetReal());
|
||||
}else{
|
||||
bgm.SetFadeTime(defaultFadeTime);
|
||||
}
|
||||
|
||||
|
||||
if(data.HasProperty("Events")){
|
||||
for(auto&[eventName,size]:DATA["Events"]){
|
||||
auto&eventData=data["Events"][eventName];
|
||||
if(eventData.GetValueCount()!=bgm.GetChannelCount())ERR(std::format("WARNING! {} parameters do not match channel count. {} != {}",eventName,eventData.GetValueCount(),bgm.GetChannelCount()));
|
||||
VolumeList volumes;
|
||||
for(int i=0;i<eventData.GetValueCount();i++){
|
||||
volumes.push_back(eventData.GetInt(i)/100.f);
|
||||
}
|
||||
bgm.AddEventVolumes(eventName,volumes);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
defaultFadeTime=data.GetReal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,13 +103,71 @@ MiniAudio&Audio::Engine(){
|
||||
return game->audioEngine.audioEngine;
|
||||
}
|
||||
void Audio::Play(const std::string_view sound){
|
||||
Engine().Play(std::string(sound));
|
||||
Engine().Play(std::string(sound));
|
||||
};
|
||||
void Audio::PlayBGM(const std::string_view sound,const bool loop=true){
|
||||
if(Engine().LoadS)
|
||||
Engine().Play(std::string(sound));
|
||||
void Audio::PlayBGM(const std::string_view sound,const bool loop){
|
||||
BGM&track=Self().bgm[std::string(sound)];
|
||||
StopBGM(); //Stop any currently playing track.
|
||||
track.Load();
|
||||
for(int channelListIndex=0;int trackID:track.GetChannelIDs()){
|
||||
Engine().SetVolume(trackID,track.GetVolume(Self().currentAudioEvent,channelListIndex));
|
||||
Engine().Play(trackID,loop);
|
||||
channelListIndex++;
|
||||
}
|
||||
};
|
||||
|
||||
void Audio::StopBGM(){
|
||||
if(Self().BGMIsPlaying()){
|
||||
BGM¤tTrack=Self().bgm[Self().currentBGM];
|
||||
for(int trackID:currentTrack.GetChannelIDs()){
|
||||
Engine().Stop(trackID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool Audio::BGMIsPlaying(){
|
||||
return Self().currentBGM.length()>0;
|
||||
}
|
||||
|
||||
const Volume&Audio::BGM::GetVolume(const Event&eventName,const ChannelID&id)const{
|
||||
return eventVolumes.GetVolumes(eventName).at(id);
|
||||
}
|
||||
|
||||
void Audio::BGM::Load(){
|
||||
BGM&bgm=Self().bgm[Self().currentBGM];
|
||||
if(Self().BGMIsPlaying()){
|
||||
bgm.Unload();
|
||||
}
|
||||
Self().currentBGM=songFileName;
|
||||
BGM&newBgm=Self().bgm[songFileName];
|
||||
if(newBgm.channels.size()>0)ERR(std::format("WARNING! The size of the channels list is greater than zero! Size: {}",bgm.channels.size()));
|
||||
for(const ChannelName&channel:newBgm.GetChannels()){
|
||||
ChannelID soundID=Engine().LoadSound("bgm_directory"_S+channel);
|
||||
newBgm.channels.push_back(soundID);
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::BGM::Unload(){
|
||||
BGM&bgm=Self().bgm[Self().currentBGM];
|
||||
for(const ChannelID&id:channels){
|
||||
Engine().UnloadSound(id);
|
||||
}
|
||||
channels.clear();
|
||||
Self().currentBGM="";
|
||||
}
|
||||
|
||||
const ChannelID&Audio::BGM::GetChannelID(const int index){
|
||||
return channels[index];
|
||||
}
|
||||
|
||||
const ChannelIDList&Audio::BGM::GetChannelIDs()const{
|
||||
return channels;
|
||||
}
|
||||
|
||||
const std::vector<ChannelName>&Audio::BGM::GetChannels()const{
|
||||
return channelNames;
|
||||
}
|
||||
|
||||
void Audio::BGM::SetFadeTime(const float fadeTime){
|
||||
this->fadeTime=fadeTime;
|
||||
}
|
||||
@ -112,6 +187,11 @@ const SongName&Audio::BGM::GetName()const{
|
||||
void Audio::BGM::SetName(std::string_view name){
|
||||
songName=name;
|
||||
}
|
||||
|
||||
void Audio::BGM::SetFileName(std::string_view name){
|
||||
songFileName=name;
|
||||
}
|
||||
|
||||
void Audio::BGM::AddChannel(const ChannelName&name){
|
||||
channelNames.push_back(name);
|
||||
}
|
||||
@ -125,9 +205,27 @@ void Audio::EventData::AddEventInfo(const Event&eventName,const VolumeList&volum
|
||||
eventInfo[eventName]=volumes;
|
||||
}
|
||||
|
||||
Audio&Audio::Self(){
|
||||
return game->audioEngine;
|
||||
}
|
||||
|
||||
const Event&Audio::GetAudioEvent(){
|
||||
return Self().currentAudioEvent;
|
||||
}
|
||||
void Audio::SetAudioEvent(const Event&eventName){
|
||||
if(Self().events.find(eventName)==Self().events.end())ERR(std::format("WARNING! cannot find event {}",eventName));
|
||||
|
||||
Self().currentAudioEvent=eventName;
|
||||
|
||||
if(Audio::BGMIsPlaying()){
|
||||
BGM¤tBgm=Self().bgm[Self().currentBGM];
|
||||
for(int currentTrackIndex=0;int trackID:currentBgm.GetChannelIDs()){
|
||||
Engine().SetVolume(trackID,currentBgm.GetVolume(eventName,currentTrackIndex));
|
||||
currentTrackIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string operator""_SFX(const char*key,size_t length){
|
||||
return "sfx_directory"_S+std::string(key,length);
|
||||
}
|
||||
std::string operator""_BGM(const char*key,size_t length){
|
||||
return "bgm_directory"_S+std::string(key,length);
|
||||
}
|
@ -38,46 +38,66 @@ All rights reserved.
|
||||
#pragma once
|
||||
#include "olcPGEX_MiniAudio.h"
|
||||
#include "config.h"
|
||||
#include <set>
|
||||
|
||||
using SongName=std::string;
|
||||
using Event=std::string;
|
||||
using ChannelName=std::string;
|
||||
using ChannelIDList=std::vector<int>;
|
||||
using VolumeList=std::vector<int>;
|
||||
using ChannelID=int;
|
||||
using ChannelIDList=std::vector<ChannelID>;
|
||||
using Volume=float;
|
||||
using VolumeList=std::vector<Volume>;
|
||||
|
||||
class Audio{
|
||||
public:
|
||||
static Audio&Self();
|
||||
static MiniAudio&Engine();
|
||||
static void Initialize();
|
||||
static void Play(const std::string_view sound);
|
||||
//Play a BGM given a name found in bgm.txt configuration file.
|
||||
static void PlayBGM(const std::string_view sound,const bool loop=true);
|
||||
static void StopBGM();
|
||||
static const Event&GetAudioEvent();
|
||||
static void SetAudioEvent(const Event&eventName);
|
||||
static const bool BGMIsPlaying();
|
||||
private:
|
||||
class EventData{
|
||||
std::map<Event,VolumeList>eventInfo;
|
||||
public:
|
||||
void AddEventInfo(const Event&eventName,const VolumeList&volumes);
|
||||
const VolumeList&GetVolumes(const Event&event)const;
|
||||
private:
|
||||
std::map<Event,VolumeList>eventInfo;
|
||||
};
|
||||
class BGM{
|
||||
std::string songName;
|
||||
public:
|
||||
void Load();
|
||||
const size_t GetChannelCount()const;
|
||||
const std::vector<ChannelName>&GetChannels()const;
|
||||
const SongName&GetName()const;
|
||||
const Volume&GetVolume(const Event&eventName,const ChannelID&id)const;
|
||||
void SetName(std::string_view name);
|
||||
void SetFileName(std::string_view name);
|
||||
void AddChannel(const ChannelName&name);
|
||||
void AddEventVolumes(const Event&eventName,const VolumeList&volumes);
|
||||
void SetFadeTime(const float fadeTime);
|
||||
const ChannelID&GetChannelID(const int index);
|
||||
const ChannelIDList&GetChannelIDs()const;
|
||||
private:
|
||||
std::string songName; //Name of the track.
|
||||
std::string songFileName; //Name of the key in bgm.
|
||||
ChannelIDList channels;
|
||||
std::vector<ChannelName>channelNames;
|
||||
EventData eventVolumes;
|
||||
float fadeTime="BGM.Default Fade Time"_F;
|
||||
public:
|
||||
void Load();
|
||||
void Unload();
|
||||
const size_t GetChannelCount()const;
|
||||
const SongName&GetName()const;
|
||||
void SetName(std::string_view name);
|
||||
void AddChannel(const ChannelName&name);
|
||||
void AddEventVolumes(const Event&eventName,const VolumeList&volumes);
|
||||
void SetFadeTime(const float fadeTime);
|
||||
};
|
||||
private:
|
||||
MiniAudio audioEngine;
|
||||
SongName currentBGM;
|
||||
SongName currentBGM="";
|
||||
std::map<SongName,BGM>bgm;
|
||||
std::set<Event>events;
|
||||
public:
|
||||
static MiniAudio&Engine();
|
||||
static void Initialize();
|
||||
static void Play(const std::string_view sound);
|
||||
static void PlayBGM(const std::string_view sound,const bool loop=true);
|
||||
static float defaultFadeTime;
|
||||
Event currentAudioEvent="Default Volume";
|
||||
};
|
||||
|
||||
std::string operator""_SFX(const char*key,size_t length);
|
||||
std::string operator""_BGM(const char*key,size_t length);
|
||||
std::string operator""_SFX(const char*key,size_t length);
|
@ -121,7 +121,8 @@ void Merchant::Initialize(){
|
||||
ERR("Could not find item "<<itemNumber<<" in Merchant "<<merchantCount<<" of Chapter "<<chapter<<"!");
|
||||
}
|
||||
itemNumber++;
|
||||
}else{
|
||||
}else
|
||||
{
|
||||
ERR("Unhandled key "<<std::quoted(key)<<" inside of Merchant "<<merchantCount<<" of Chapter "<<chapter<<"!");
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +109,24 @@ void State_OverworldMap::OnUserUpdate(AiL*game){
|
||||
if(game->GetKey(K1).bPressed){
|
||||
Audio::Play("sfx100v2_loop_water_01.mp3"_SFX);
|
||||
}
|
||||
if(game->GetKey(F1).bPressed){
|
||||
Audio::PlayBGM("foresty1_1");
|
||||
}else
|
||||
if(game->GetKey(F2).bPressed){
|
||||
Audio::PlayBGM("foresty0");
|
||||
}
|
||||
if(game->GetKey(K2).bPressed){
|
||||
Audio::SetAudioEvent("Default Volume");
|
||||
}
|
||||
if(game->GetKey(K3).bPressed){
|
||||
Audio::SetAudioEvent("LowHealth");
|
||||
}
|
||||
if(game->GetKey(K4).bPressed){
|
||||
Audio::SetAudioEvent("InCombat");
|
||||
}
|
||||
if(game->GetKey(K5).bPressed){
|
||||
Audio::SetAudioEvent("Underwater");
|
||||
}
|
||||
|
||||
#pragma region Handle Connection Point Clicking and Movement
|
||||
for(ConnectionPoint&cp:connections){
|
||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 1
|
||||
#define VERSION_BUILD 5353
|
||||
#define VERSION_BUILD 5379
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -29,4 +29,23 @@ BGM
|
||||
Underwater = 0%,0%,100%,100%
|
||||
}
|
||||
}
|
||||
foresty0
|
||||
{
|
||||
Track Name = Foresty Preview
|
||||
|
||||
channel[0]=foresty0.mp3
|
||||
channel[1]=foresty0_alt.mp3
|
||||
|
||||
Default Volume = 70%,0%
|
||||
|
||||
# Transition time between one phase to the next.
|
||||
Fade Time = 2.0
|
||||
|
||||
Events
|
||||
{
|
||||
LowHealth = 50%,20%
|
||||
InCombat = 100%,0%
|
||||
Underwater = 0%,100%
|
||||
}
|
||||
}
|
||||
}
|
@ -66,10 +66,10 @@ sfx_directory = assets/sounds/
|
||||
bgm_directory = assets/music/
|
||||
|
||||
# Path to bgm configuration
|
||||
bgm_config = bgm.txt
|
||||
bgm_config = bgm/bgm.txt
|
||||
|
||||
# Path to bgm events configuration
|
||||
event_config = events.txt
|
||||
event_config = bgm/events.txt
|
||||
|
||||
# Path to character images
|
||||
character_image_location = characters/
|
||||
|
BIN
Adventures in Lestoria/assets/music/foresty0.mp3
Normal file
BIN
Adventures in Lestoria/assets/music/foresty0.mp3
Normal file
Binary file not shown.
BIN
Adventures in Lestoria/assets/music/foresty0_alt.mp3
Normal file
BIN
Adventures in Lestoria/assets/music/foresty0_alt.mp3
Normal file
Binary file not shown.
@ -488,10 +488,10 @@ namespace olc::utils
|
||||
}
|
||||
|
||||
inline auto begin(){
|
||||
return GetOrderedKeys().begin();
|
||||
return GetKeys().begin();
|
||||
}
|
||||
inline auto end(){
|
||||
return GetOrderedKeys().end();
|
||||
return GetKeys().end();
|
||||
}
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user