Skip to content

Commit

Permalink
Add Transition class and new Daedalus classes for music definition
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrmacha committed May 27, 2024
1 parent 942f0de commit d8f5f37
Show file tree
Hide file tree
Showing 17 changed files with 286 additions and 43 deletions.
61 changes: 54 additions & 7 deletions src/Gothic/BassLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ namespace GOTHIC_NAMESPACE
zSTRING Type;
zSTRING Filename;
zSTRING MidiFile;
float Volume;
int Loop;
int Reverb;
float ReverbMix;
float ReverbTime;
int FadeIn;
int FadeInDuration;
int FadeOut;
int FadeOutDuration;
};

class BassLoader
Expand Down Expand Up @@ -85,25 +94,63 @@ namespace GOTHIC_NAMESPACE
effects.FadeOut.Duration = NH::Bass::Options->TransitionTime;
}
});
theme->AddZone(symbol->name.ToChar());
zSTRING zone = symbol->name;
zone.Upper();
theme->AddZone(zone.ToChar());
NH::Bass::Engine::GetInstance()->GetMusicManager().AddTheme(symbol->name.ToChar(), theme);
});
}

void LoadBass()
{
ForEachClass<BassMusicTheme>(
"C_BassMusic_Theme",
Globals->BassMusicThemeClassName,
[&]() { return m_BassThemeInstances.emplace_back(new BassMusicTheme{}); },
[&](BassMusicTheme* theme, zCPar_Symbol* symbol) {
// @todo:
[&](BassMusicTheme* input, zCPar_Symbol* symbol) {
std::shared_ptr<NH::Bass::MusicTheme> theme = std::make_shared<NH::Bass::MusicTheme>(input->Name.ToChar());
theme->SetAudioEffects(NH::Bass::AudioFile::DEFAULT, [](NH::Bass::AudioEffects& effects){});
auto zones = NH::String(input->Zones.ToChar()).Split(",");
for (auto& zone: zones) { theme->AddZone(zone.MakeUpper()); }
// input->Type ignored for now
NH::Bass::Engine::GetInstance()->GetMusicManager().AddTheme(input->Name.ToChar(), theme);
});

ForEachClass<BassMusicThemeAudio>(
"C_BassMusic_ThemeAudio",
Globals->BassMusicThemeAudioClassName,
[&]() { return m_BassThemeAudioInstances.emplace_back(new BassMusicThemeAudio{}); },
[&](BassMusicThemeAudio* theme, zCPar_Symbol* symbol) {
// @todo:
[&](BassMusicThemeAudio* input, zCPar_Symbol* symbol) {
std::shared_ptr<NH::Bass::MusicTheme> theme = NH::Bass::Engine::GetInstance()->GetMusicManager().GetTheme(input->Theme.ToChar());
NH::String type = NH::String(input->Type.ToChar());
NH::HashString id = type == "DEFAULT" ? NH::Bass::AudioFile::DEFAULT : NH::HashString(type);
theme->SetAudioFile(id, input->Filename.ToChar());
theme->SetAudioEffects(id, [&](NH::Bass::AudioEffects& effects) {
effects.Loop.Active = input->Loop;
effects.Volume.Active = true;
effects.Volume.Volume = input->Volume;
if (!NH::Bass::Options->ForceDisableReverb && input->Reverb)
{
effects.ReverbDX8.Active = true;
effects.ReverbDX8.Mix = input->ReverbMix;
effects.ReverbDX8.Time = input->ReverbTime;
}
bool forceFade = NH::Bass::Options->ForceFadeTransition;
if (forceFade || input->FadeIn)
{
effects.FadeIn.Active = true;
effects.FadeIn.Duration = input->FadeInDuration;
}
if (forceFade || input->FadeOut)
{
effects.FadeOut.Active = true;
effects.FadeOut.Duration = input->FadeOutDuration;
}
});
if (!input->MidiFile.IsEmpty())
{
auto midiFile = std::make_shared<NH::Bass::MidiFile>(theme->GetName(), NH::HashString(NH::String(input->MidiFile.ToChar())));
theme->AddMidiFile(NH::HashString(""), midiFile);
}
NH::Bass::Engine::GetInstance()->GetMusicManager().RefreshTheme(theme->GetName());
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/Gothic/CMusicSys_Bass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ namespace GOTHIC_NAMESPACE
}

identifier.Upper();
m_BassEngine->GetCommandQueue().AddCommand(std::make_shared<NH::Bass::ChangeZoneCommand>(identifier.ToChar()));
m_BassEngine->GetCommandQueue().AddCommand(std::make_shared<NH::Bass::ChangeZoneCommand>(NH::String(identifier.ToChar())));

if (done)
{
Expand Down
5 changes: 5 additions & 0 deletions src/Gothic/Externals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,14 @@ namespace GOTHIC_NAMESPACE

parser->DefineExternal("BassMusic_TransitionRule_OnBeat", BassMusic_TransitionRule_OnBeat, zPAR_TYPE_VOID, zPAR_TYPE_STRING, zPAR_TYPE_STRING, zPAR_TYPE_STRING, zPAR_TYPE_VOID);

parserMusic->AddClassOffset(Globals->BassMusicThemeClassName, sizeof(BassMusicTheme));
parserMusic->AddClassOffset(Globals->BassMusicThemeAudioClassName, sizeof(BassMusicThemeAudio));

if (NH::Bass::Options->CreateMainParserCMusicTheme)
{
zCMusicTheme theme;
parser->AddClassOffset(Globals->BassMusicThemeClassName, sizeof(BassMusicTheme));
parser->AddClassOffset(Globals->BassMusicThemeAudioClassName, sizeof(BassMusicThemeAudio));
parser->AddClassOffset(Globals->CMusicThemeClass, reinterpret_cast<int>(&theme.dScriptEnd) - reinterpret_cast<int>(&theme.fileName));
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/Gothic/Globals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace GOTHIC_NAMESPACE
struct GlobalsDef
{
zSTRING CMusicThemeClass = "C_MUSICTHEME";
zSTRING BassMusicThemeClassName = "C_BassMusic_Theme";
zSTRING BassMusicThemeAudioClassName = "C_BassMusic_ThemeAudio";
zSTRING BassMusic_ActiveThemeFilename = "";
zSTRING BassMusic_ActiveThemeID = "";
zSTRING BassMusic_EventThemeFilename = "";
Expand Down
9 changes: 5 additions & 4 deletions src/Gothic/Hooks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ namespace GOTHIC_NAMESPACE
zmusic->SetVolume(volume);
log->Info("Set music system to CMusicSys_Bass");

BassLoader bassLoaderMusic(parserMusic);
bassLoaderMusic.Load();

if (NH::Bass::Options->CreateMainParserCMusicTheme)
{
BassLoader bassLoader(parser);
bassLoader.Load();
BassLoader bassLoaderMain(parser);
bassLoaderMain.Load();
}
BassLoader bassLoader(parserMusic);
bassLoader.Load();
}
else
{
Expand Down
11 changes: 6 additions & 5 deletions src/NH/Bass/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,17 @@ namespace NH::Bass
{
bool enabled = deviceInfo.flags & BASS_DEVICE_ENABLED;
bool isDefault = deviceInfo.flags & BASS_DEVICE_DEFAULT;

log->Trace("Available device: {0} {1} {2}", deviceInfo.name, enabled ? "enabled" : "disabled", isDefault ? "default" : "");
if (enabled && isDefault)
{
deviceIndex = i;
break;
}
};

BASS_SetDevice(deviceIndex);
BASS_GetDeviceInfo(deviceIndex, &deviceInfo);
log->Info("Device Name: {0}", deviceInfo.name);

m_Initialized = BASS_Init((int32_t) deviceIndex, 44100, 0, nullptr, nullptr);
if (!m_Initialized)
{
Expand All @@ -163,16 +166,14 @@ namespace NH::Bass

BASS_INFO info;
BASS_GetInfo(&info);
log->Trace("Sample Rate: {0} Hz", info.freq);
log->Info("Sample Rate: {0} Hz", info.freq);

static constexpr size_t Channels_Max = 16;
m_Channels.clear();
for (size_t i = 0; i < Channels_Max; i++)
{
m_Channels.emplace_back(std::make_shared<Channel>(i));
}

log->Info("Initialized with device: {0}", deviceIndex);
}

Union::StringUTF8 Engine::ErrorCodeToString(const int code)
Expand Down
4 changes: 2 additions & 2 deletions src/NH/Bass/EngineCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ namespace NH::Bass
class ChangeZoneCommand : public Command
{
static Logger* log;
HashString m_Zone;
String m_Zone;
public:
explicit ChangeZoneCommand(HashString zone) : m_Zone(zone) {};
explicit ChangeZoneCommand(const String& zone) : m_Zone(zone) {};
CommandResult Execute(Engine& engine) override;
};

Expand Down
9 changes: 7 additions & 2 deletions src/NH/Bass/MidiFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ namespace NH::Bass
{
Logger* MidiFile::log = CreateLogger("zBassMusic::MidiFile");

void MidiFile::LoadMidiFile(Executor& executor)
void MidiFile::LoadMidiFile(Executor& executor, const std::function<void(MidiFile&)>& onReady)
{
if (m_LoadingStatus != LoadingStatusType::NOT_LOADED)
{
log->Warning("MidiFile::LoadMidiFile() called on a MidiFile that is not in NOT_LOADED state.");
return;
}
m_LoadingStatus = LoadingStatusType::LOADING;
executor.AddTask([this]()
executor.AddTask([this, onReady]()
{
int systems = VDF_VIRTUAL | VDF_PHYSICAL;
const Union::VDFS::File* file = Union::VDFS::GetDefaultInstance().GetFile(m_Filename, systems);
Expand All @@ -33,6 +33,11 @@ namespace NH::Bass
stream->Close();
m_LoadingStatus = LoadingStatusType::READY;
ParseMidiFile();

if (onReady)
{
onReady(*this);
}
});
}

Expand Down
12 changes: 6 additions & 6 deletions src/NH/Bass/MidiFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ namespace NH::Bass
private:
static Logger* log;
HashString m_ThemeId;
HashString m_AudioId;
String m_Filename;
String m_TargetFilter;
std::vector<char> m_Buffer{};
StatusType m_Status = StatusType::NOT_LOADED;
LoadingStatusType m_LoadingStatus = LoadingStatusType::NOT_LOADED;
Expand All @@ -45,17 +45,17 @@ namespace NH::Bass
std::vector<Tone> m_Tones{};

public:
MidiFile(HashString themeId, HashString audioId, const String& filename)
: m_ThemeId(themeId), m_AudioId(audioId), m_Filename(filename) {}
MidiFile(HashString themeId, const String& filename, const String& targetFilter = "")
: m_ThemeId(themeId), m_Filename(filename), m_TargetFilter(targetFilter) {}

void LoadMidiFile(Executor& executor);
void LoadMidiFile(Executor& executor, const std::function<void(MidiFile&)>& onReady = nullptr);

[[nodiscard]] HashString GetThemeId() const { return m_ThemeId; }

[[nodiscard]] HashString GetAudioId() const { return m_AudioId; }

[[nodiscard]] const String& GetFilename() const { return m_Filename; }

[[nodiscard]] const String& GetTargetFilter() const { return m_TargetFilter; }

[[nodiscard]] StatusType GetStatus() const { return m_Status; }

[[nodiscard]] LoadingStatusType GetLoadingStatus() const { return m_LoadingStatus; }
Expand Down
20 changes: 15 additions & 5 deletions src/NH/Bass/MusicManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@

namespace NH::Bass
{
void MusicManager::AddTheme(HashString id, std::shared_ptr<MusicTheme> theme)
void MusicManager::AddTheme(HashString id, const std::shared_ptr<MusicTheme>& theme)
{
m_Themes.emplace(id, theme);
m_Themes.at(id)->LoadAudioFiles(Executors.IO);
m_Themes[id] = theme;
m_Themes[id]->LoadAudioFiles(Executors.IO);
log->Info("New theme {0}", id);
log->PrintRaw(LoggerLevel::Debug, m_Themes.at(id)->ToString());
log->PrintRaw(LoggerLevel::Debug, m_Themes[id]->ToString());
}

void MusicManager::RefreshTheme(HashString id)
{
if (m_Themes.contains(id))
{
m_Themes[id]->LoadAudioFiles(Executors.IO);
log->Info("Refresh theme {0}", id);
log->PrintRaw(LoggerLevel::Debug, m_Themes[id]->ToString());
}
}

std::vector<std::pair<HashString, std::shared_ptr<MusicTheme>>> MusicManager::GetThemesForZone(HashString zone)
Expand All @@ -29,6 +39,6 @@ namespace NH::Bass
{
return {};
}
return m_Themes.at(id);
return m_Themes[id];
}
}
4 changes: 3 additions & 1 deletion src/NH/Bass/MusicManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ namespace NH::Bass
std::unordered_map<HashString, std::shared_ptr<MusicTheme>> m_Themes;

public:
void AddTheme(HashString id, std::shared_ptr<MusicTheme> theme);
void AddTheme(HashString id, const std::shared_ptr<MusicTheme>& theme);

void RefreshTheme(HashString id);

[[nodiscard]] std::shared_ptr<MusicTheme> GetTheme(HashString id);

Expand Down
25 changes: 16 additions & 9 deletions src/NH/Bass/MusicTheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ namespace NH::Bass
MusicTheme MusicTheme::None = MusicTheme("<None>");
Logger* MusicTheme::log = CreateLogger("zBassMusic::MusicTheme");

MusicTheme::MusicTheme(const String& name)
: m_Name(name)
{

}
MusicTheme::MusicTheme(const String& name) : m_Name(name), m_TransitionInfo{m_Name} {}

void MusicTheme::SetAudioFile(HashString type, const String& filename)
{
Expand All @@ -27,18 +23,28 @@ namespace NH::Bass

void MusicTheme::SetAudioEffects(HashString type, const std::function<void(AudioEffects&)>& effectsSetter)
{
m_AudioEffects.emplace(std::make_pair(type, AudioEffects{}));
if (!m_AudioFiles.contains(type))
{
m_AudioEffects[type] = AudioEffects{};
}
effectsSetter(m_AudioEffects[type]);
if (m_AudioEffects[type].FadeOut.Active)
{
m_TransitionInfo.AddTransitionEffect(TransitionEffect::CROSSFADE, m_AudioEffects[type].FadeOut.Duration);
}
}

void MusicTheme::AddZone(HashString zone)
{
m_Zones.emplace_back(zone);
}

void MusicTheme::AddMidiFile(HashString type, const std::shared_ptr<MidiFile>& midiFile)
void MusicTheme::AddMidiFile(HashString type, std::shared_ptr<MidiFile> midiFile)
{
m_MidiFiles.emplace(std::make_pair(type, midiFile));
m_MidiFiles.emplace(std::make_pair(HashString(type), midiFile));
m_MidiFiles[type]->LoadMidiFile(Executors.IO, [this, type](MidiFile& midi) {
m_TransitionInfo.AddMidiFile(midi, type);
});
}

void MusicTheme::LoadAudioFiles(Executor& executor)
Expand Down Expand Up @@ -148,7 +154,7 @@ namespace NH::Bass
log->Error("Trying to play a music theme that has failed to load: {0}", f.Filename);
return CommandResult::DONE;
}
if (f.Status == AudioFile::StatusType::READY)
if (f.Status == AudioFile::StatusType::READY || (m_MidiFiles.contains(""_hs) && m_MidiFiles[""_hs]->GetStatus() == MidiFile::StatusType::PARSING))
{
engine.GetCommandQueue().AddCommand(std::make_shared<ScheduleThemeChangeCommand>(m_Name));
return CommandResult::DONE;
Expand All @@ -175,6 +181,7 @@ namespace NH::Bass

bool MusicTheme::HasZone(HashString zone) const
{
zone = String(zone.GetValue()).MakeUpper();
return std::find(m_Zones.begin(), m_Zones.end(), zone) != m_Zones.end();
}

Expand Down
5 changes: 4 additions & 1 deletion src/NH/Bass/MusicTheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <NH/Bass/MidiFile.h>
#include <NH/Bass/IEngine.h>
#include <NH/Bass/IChannel.h>
#include <NH/Bass/TransitionInfo.h>

#include <vector>
#include <unordered_map>
Expand Down Expand Up @@ -58,6 +59,7 @@ namespace NH::Bass

String m_Name;
size_t m_SyncHandlersId = 0;
TransitionInfo m_TransitionInfo;
std::unordered_map<HashString, AudioFile> m_AudioFiles;
std::unordered_map<HashString, AudioEffects> m_AudioEffects;
std::unordered_map<HashString, std::shared_ptr<MidiFile>> m_MidiFiles;
Expand All @@ -74,14 +76,15 @@ namespace NH::Bass
void SetAudioFile(HashString type, const String& filename);
void SetAudioEffects(HashString type, const std::function<void(AudioEffects&)>& effectsSetter);
void AddZone(HashString zone);
void AddMidiFile(HashString type, const std::shared_ptr<MidiFile>& midiFile);
void AddMidiFile(HashString type, std::shared_ptr<MidiFile> midiFile);
void LoadAudioFiles(Executor& executor);

void PlayInstant(IEngine& engine);
void ScheduleAfter(IEngine&, const std::shared_ptr<MusicTheme>& currentTheme);
void StopInstant(IEngine& engine);

[[nodiscard]] const String& GetName() const { return m_Name; }
[[nodiscard]] TransitionInfo& GetTransitionInfo() { return m_TransitionInfo; };
[[nodiscard]] bool HasAudioFile(HashString type) const { return m_AudioFiles.find(type) != m_AudioFiles.end(); }
[[nodiscard]] bool IsAudioFileReady(HashString type) const { return HasAudioFile(type) && m_AudioFiles.at(type).Status == AudioFile::StatusType::READY; }
[[nodiscard]] const AudioFile& GetAudioFile(HashString type) const { return m_AudioFiles.at(type); }
Expand Down
Loading

0 comments on commit d8f5f37

Please sign in to comment.