mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-21 05:53:02 +01:00
Add new audio objects for loading sounds
This commit is contained in:
220
src/openrct2/object/AudioSampleTable.cpp
Normal file
220
src/openrct2/object/AudioSampleTable.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2022 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "AudioSampleTable.h"
|
||||
|
||||
#include "../Context.h"
|
||||
#include "../PlatformEnvironment.h"
|
||||
#include "../audio/AudioContext.h"
|
||||
#include "../core/Json.hpp"
|
||||
#include "../core/Path.hpp"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
using namespace OpenRCT2::Audio;
|
||||
|
||||
struct SourceInfo
|
||||
{
|
||||
std::string Path;
|
||||
std::vector<int32_t> Range{};
|
||||
};
|
||||
|
||||
static std::vector<int32_t> ParseRange(std::string_view s)
|
||||
{
|
||||
// Currently only supports [###] or [###..###]
|
||||
std::vector<int32_t> result = {};
|
||||
if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']')
|
||||
{
|
||||
s = s.substr(1, s.length() - 2);
|
||||
auto parts = String::Split(s, "..");
|
||||
if (parts.size() == 1)
|
||||
{
|
||||
result.push_back(std::stoi(parts[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto left = std::stoi(parts[0]);
|
||||
auto right = std::stoi(parts[1]);
|
||||
if (left <= right)
|
||||
{
|
||||
for (auto i = left; i <= right; i++)
|
||||
{
|
||||
result.push_back(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto i = right; i >= left; i--)
|
||||
{
|
||||
result.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static SourceInfo ParseSource(std::string_view source)
|
||||
{
|
||||
SourceInfo info;
|
||||
if (String::StartsWith(source, "$RCT1:DATA/"))
|
||||
{
|
||||
auto name = source.substr(11);
|
||||
auto rangeStart = name.find('[');
|
||||
if (rangeStart != std::string::npos)
|
||||
{
|
||||
info.Range = ParseRange(name.substr(rangeStart));
|
||||
name = name.substr(0, rangeStart);
|
||||
}
|
||||
|
||||
auto env = GetContext()->GetPlatformEnvironment();
|
||||
auto dataPath = env->GetDirectoryPath(DIRBASE::RCT1, DIRID::DATA);
|
||||
info.Path = Path::Combine(dataPath, name);
|
||||
}
|
||||
else if (String::StartsWith(source, "$RCT2:DATA/"))
|
||||
{
|
||||
auto name = source.substr(11);
|
||||
auto rangeStart = name.find('[');
|
||||
if (rangeStart != std::string::npos)
|
||||
{
|
||||
info.Range = ParseRange(name.substr(rangeStart));
|
||||
name = name.substr(0, rangeStart);
|
||||
}
|
||||
|
||||
auto env = GetContext()->GetPlatformEnvironment();
|
||||
auto dataPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::DATA);
|
||||
info.Path = Path::Combine(dataPath, name);
|
||||
}
|
||||
else if (String::StartsWith(source, "$["))
|
||||
{
|
||||
info.Range = ParseRange(source.substr(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Path = source;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void AudioSampleTable::ReadFromJson(IReadObjectContext* context, const json_t& root)
|
||||
{
|
||||
json_t jSamples = root["samples"];
|
||||
if (jSamples.is_array())
|
||||
{
|
||||
for (auto& jSample : jSamples)
|
||||
{
|
||||
SourceInfo sourceInfo;
|
||||
int32_t modifier{};
|
||||
if (jSample.is_string())
|
||||
{
|
||||
sourceInfo = ParseSource(jSample.get<std::string>());
|
||||
}
|
||||
else if (jSample.is_object())
|
||||
{
|
||||
sourceInfo = ParseSource(jSample.at("source").get<std::string>());
|
||||
if (jSample.contains("modifier"))
|
||||
{
|
||||
modifier = jSample.at("modifier").get<int32_t>();
|
||||
}
|
||||
}
|
||||
|
||||
auto asset = context->GetAsset(sourceInfo.Path);
|
||||
if (sourceInfo.Range.empty())
|
||||
{
|
||||
auto& entry = _entries.emplace_back();
|
||||
entry.Asset = asset;
|
||||
entry.Modifier = modifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto index : sourceInfo.Range)
|
||||
{
|
||||
auto& entry = _entries.emplace_back();
|
||||
entry.Asset = asset;
|
||||
entry.PathIndex = index;
|
||||
entry.Modifier = modifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSampleTable::LoadFrom(const AudioSampleTable& table, size_t index, size_t length)
|
||||
{
|
||||
auto audioContext = GetContext()->GetAudioContext();
|
||||
auto numEntries = std::min(_entries.size(), length);
|
||||
for (size_t i = 0; i < numEntries; i++)
|
||||
{
|
||||
auto& entry = _entries[i];
|
||||
if (entry.Source != nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto sourceIndex = index + i;
|
||||
if (sourceIndex >= table._entries.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& sourceEntry = table._entries[sourceIndex];
|
||||
if (sourceEntry.Asset)
|
||||
{
|
||||
auto stream = sourceEntry.Asset->GetStream();
|
||||
if (stream != nullptr)
|
||||
{
|
||||
if (sourceEntry.PathIndex)
|
||||
{
|
||||
entry.Source = audioContext->CreateStreamFromCSS(std::move(stream), *sourceEntry.PathIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.Source = audioContext->CreateStreamFromWAV(std::move(stream));
|
||||
}
|
||||
entry.Modifier = sourceEntry.Modifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSampleTable::Load()
|
||||
{
|
||||
LoadFrom(*this, 0, _entries.size());
|
||||
}
|
||||
|
||||
void AudioSampleTable::Unload()
|
||||
{
|
||||
for (auto& entry : _entries)
|
||||
{
|
||||
entry.Source->Release();
|
||||
entry.Source = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioSampleTable::GetCount() const
|
||||
{
|
||||
return _entries.size();
|
||||
}
|
||||
|
||||
IAudioSource* AudioSampleTable::GetSample(uint32_t index) const
|
||||
{
|
||||
if (index < _entries.size())
|
||||
{
|
||||
return _entries[index].Source;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int32_t AudioSampleTable::GetSampleModifier(uint32_t index) const
|
||||
{
|
||||
if (index < _entries.size())
|
||||
{
|
||||
return _entries[index].Modifier;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user