VAE - Virtual Audio Engine 1
Small Data Driven Audio Engine
vae::core::BankLoader Class Reference

#include <vae_bank_loader.hpp>

Collaboration diagram for vae::core::BankLoader:

Public Member Functions

Result load (const char *path, Size length, const char *rootPath, Bank &bank)
 Load a bank.json and all wav files referenced in it. More...
 

Static Private Member Functions

static void * allocate (size_t size, int zero, void *context)
 
static void deallocate (void *ptr, void *context)
 

Private Attributes

SourceLoader mSourceLoader
 

Detailed Description

Definition at line 21 of file vae_bank_loader.hpp.

Member Function Documentation

◆ allocate()

static void * vae::core::BankLoader::allocate ( size_t  size,
int  zero,
void *  context 
)
inlinestaticprivate

Definition at line 22 of file vae_bank_loader.hpp.

22 {
23 memory::AllocatorFS<char> allocator;
24 void* ptr = reinterpret_cast<void*>(allocator.allocate(size));
25 if (zero) {
26 memset(ptr, 0, size);
27 }
28 return ptr;
29 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ deallocate()

static void vae::core::BankLoader::deallocate ( void *  ptr,
void *  context 
)
inlinestaticprivate

Definition at line 31 of file vae_bank_loader.hpp.

31 {
32 memory::AllocatorFS<char> allocator;
33 allocator.deallocate(reinterpret_cast<char*>(ptr), 0);
34 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load()

Result vae::core::BankLoader::load ( const char *  path,
Size  length,
const char *  rootPath,
Bank bank 
)
inline

Load a bank.json and all wav files referenced in it.

Parameters
pathThe path to the bank folder. Folder must contain a bank.json. Wav files are relative to this path
bankThe bank object to populae
Returns
Result

Open file and decode json

Deserialize Source and preload signal data

Deserialize Mixers. Don't initialize anything yet

Definition at line 44 of file vae_bank_loader.hpp.

44 {
46
47 /**
48 * Open file and decode json
49 */
50 PathString folder; // Folder to the bank
51 const char* encoded = path; // The plain json text
52
53 String jsonText;
54
55 if (length == 0) { // length 0 indicates the file is on disk
56 VAE_DEBUG("Started loading bank %s", path)
57 VAE_PROFILER_SCOPE_NAMED("BankFile IO")
58 folder = rootPath;
59 folder.append(path);
60 folder.append("/");
61 PathString json = folder;
62 json.append("bank.json");
63 fs::File file(json.c_str());
64 jsonText.resize(file.size());
65 if (!file.readAll(jsonText.data())) {
66 VAE_DEBUG("Failed to read file")
67 return Result::FileOpenError;
68 }
69 length = jsonText.size();
70 encoded = jsonText.c_str();
71 }
72
73
74
75 json_settings settings = { };
76 settings.mem_alloc = allocate;
77 settings.mem_free = deallocate;
78
79 json_value* json;
80 {
81 VAE_PROFILER_SCOPE_NAMED("BankFile Parsing")
82 json = json_parse_ex(&settings, encoded, length, 0);
83 }
84 if (json == nullptr) { return Result::BankFormatError; }
85 json_value& data = (*json);
86
87 bank.name = (const char*) data["name"];
88 bank.id = (json_int_t) data["id"];
89 bank.path = path;
90
91 /**
92 * Deserialize Source and preload signal data
93 */
94 auto sources = data["sources"];
95 if (sources.type == json_array) {
96 VAE_PROFILER_SCOPE_NAMED("Deserialize sources")
97 bank.sources.resize(sources.u.array.length);
98 for (auto& iraw : sources.u.array) {
99 auto& i = *iraw;
100 SourceHandle id = (json_int_t) i["id"];
101
102 if (sources.u.array.length <= id) { return Result::BankFormatIndexError; }
103
104 String asd = (const char*) i["name"];
105
106 Source& s = bank.sources[id];
107 if (s.id != InvalidSourceHandle) {
108 VAE_ERROR("Duplicate Source id %i in bank %i", s.id, bank.id)
109 return Result::BankFormatDuplicateIndex;
110 }
111 s.id = id;
112 s.name = (const char*) i["name"];
113 s.path = (const char*) i["path"];
114
115 if (i["gain"].type == json_double) s.gain = (double) i["gain"];
116 if (i["resample"].type == json_boolean) s.resample = i["resample"];
117 if (i["stream"].type == json_boolean) s.stream = i["stream"];
118
119 IdString format = { i["format"] };
120 if (format == "wav") s.format = Source::Format::wav;
121 if (format == "ogg") s.format = Source::Format::ogg;
122 if (format == "generator") s.format = Source::Format::generator;
123
124 auto result = mSourceLoader.load(s, folder.c_str());
125 if (result != Result::Success) {
126 VAE_ERROR("Failed to load source %s", s.path.c_str())
127 }
128 }
129 }
130
131 /**
132 * Deserialize Mixers. Don't initialize anything yet
133 */
134 auto mixers = data["mixers"];
135 if (mixers.type == json_array) {
136 VAE_PROFILER_SCOPE_NAMED("Deserialize mixers")
137 bank.mixers.resize(mixers.u.array.length);
138 for (auto& iraw : mixers.u.array) {
139 auto& i = *iraw;
140
141 MixerHandle id = (json_int_t) i["id"];
142
143 if (mixers.u.array.length <= id) {
144 VAE_ERROR("Mixer %i:%i id out of bounds.", id, bank.id);
146 }
147
148 auto& m = bank.mixers[id];
149
150 if (m.id != InvalidMixerHandle) {
151 VAE_ERROR("Duplicate Mixer id %i in bank %i", m.id, bank.id)
152 return Result::BankFormatDuplicateIndex;
153 }
154
155 m.name = (const char*) i["name"];
156 m.id = id;
157
158 if (i["parent"].type == json_integer) m.parent = (json_int_t) i["parent"];
159 if (i["gain"].type == json_double) m.gain = (double) i["gain"];
160
161 if (m.id != Mixer::MasterMixerHandle && m.id <= m.parent) {
162 // Mixer can only write to mixers with lower ids than themselves
163 // this avoids recursion and makes mixing easier
164 VAE_ERROR("Mixer %i:%i tried to mix to %i. ", id, bank.id, m.parent);
166 }
167
168 auto effects = i["effects"];
169 if (effects.type != json_array || effects.u.array.length == 0) { continue; }
170
171
172 for (auto& iraw : effects.u.array) {
173 auto& i = *iraw;
174
175 json_int_t index = i["index"];
176 auto& e = m.effects[index];
177 e.bypassed = i["bypassed"];
178 e.name = i["name"];
179
180 int paramIndex = 0;
181 for (auto& j : i["parameters"].u.array) {
182
183 e.parameters[paramIndex].name = (const char*) (*j)[0];
184 e.parameters[paramIndex].value = (double) (*j)[1];
185 paramIndex++;
186 }
187 }
188 }
189 }
190
191 auto events = data["events"];
192 {
193 VAE_PROFILER_SCOPE_NAMED("Deserialize events")
194 bank.events.resize(events.u.array.length);
195 for (auto& iraw : events.u.array) {
196 auto& i = *iraw;
197 EventHandle id = (json_int_t) i["id"];
198
199 if (events.u.array.length <= id) {
200 VAE_ERROR("Event %i:%i id out of bounds.", id, bank.id)
201 return Result::BankFormatIndexError;
202 }
203
204 Event& e = bank.events[id];
205
206 if (e.id != InvalidEventHandle) {
207 VAE_ERROR("Duplicate Event id %i in bank %i", e.id, bank.id)
208 return Result::BankFormatDuplicateIndex;
209 }
210
211 e.id = id;
212 e.name = (const char*) i["name"];
213
214 IdString action = { i["action"] };
215 if (action == "start_rand") e.action = Event::Action::random;
216 if (action == "emit") e.action = Event::Action::emit;
217 if (action == "stop") e.action = Event::Action::stop;
218 if (action == "start") e.action = Event::Action::start;
219
220 if (i["force_mixer"].type == json_boolean) e.force_mixer = i["force_mixer"];
221 if (i["spatial"].type == json_boolean) e.spatial = i["spatial"];
222 if (i["critical"].type == json_boolean) e.critical = i["critical"];
223 if (i["loop"].type == json_boolean) e.loop = i["loop"];
224 if (i["hrtf"].type == json_boolean) e.HRTF = i["hrtf"];
225 if (i["attenuate"].type == json_boolean) e.attenuate = i["attenuate"];
226 if (i["mixer"].type == json_integer) e.mixer = (json_int_t) i["mixer"];
227 if (i["gain"].type == json_double) e.gain = (double) i["gain"];
228 if (i["source"].type == json_integer) e.source = (json_int_t) i["source"];
229 if (i["on_end"].type == json_integer) e.on_end = (json_int_t) i["on_end"];
230
231 if (i["chained_events"].type == json_array) {
232 auto onStart = i["chained_events"].u.array;
233 if (StaticConfig::MaxChainedEvents < onStart.length) {
234 VAE_ERROR("Event %i:%i has too many chained chained_events events.", id, bank.id)
235 return Result::TooManyRecords;
236 }
237 for (size_t j = 0; j < onStart.length; j++) {
238 e.chained_events[j] = (json_int_t) (*onStart.values[j]);
239 }
240 }
241
242 }
243 }
244
245 json_value_free_ex(&settings, json);
246 return Result::Success;
247 }
static void * allocate(size_t size, int zero, void *context)
static void deallocate(void *ptr, void *context)
constexpr Size MaxChainedEvents
How many chained events can fit in chain_events on the core::Event structure.
Definition: vae.hpp:302
tklb::StackString< 16 > IdString
Non optional string used to id things.
Definition: vae_types.hpp:96
tklb::String< HeapBuffer< char > > PathString
Non optional string used for locations, maybe replaceable with a unique_ptr or something.
Definition: vae_types.hpp:95
SmallHandle MixerHandle
Definition: vae.hpp:44
constexpr SourceHandle InvalidSourceHandle
Definition: vae.hpp:56
constexpr EventHandle InvalidEventHandle
Definition: vae.hpp:55
GenericHandle EventHandle
The handle used to address events within a bank.
Definition: vae.hpp:41
Result
Return Types for most engine functions.
Definition: vae.hpp:73
@ BankFormatError
Generic bank loading error.
@ BankFormatBadMixHirarchy
A mixer can only write to mixers with lower ids than themselves (no recursion)
@ BankFormatIndexError
A index is out of bounds.
GenericHandle SourceHandle
Definition: vae.hpp:42
constexpr MixerHandle InvalidMixerHandle
Definition: vae.hpp:58
HeapBuffer< char > String
Definition: string.cpp:4
Definition: string.cpp:6
@ random
triggers one random chained_events event
@ emit
Emits an event to the EventCallback defined in the engine config.
@ start
Starts a source if defined and every Event in chained_events.
@ stop
Stops a source if defined and stops every voice started from a event in chained_events.
@ ogg
Uses stb_vorbis to decode oggs.
@ wav
Uses dr_wav to decode wavs.
@ generator
Not implemented.
Result load(Source &s, const char *path)
Loads a wav file for the resource.
#define VAE_ERROR(msg,...)
Definition: vae_logger.hpp:80
#define VAE_DEBUG(msg,...)
Definition: vae_logger.hpp:83
#define VAE_PROFILER_SCOPE_NAMED(name)
Profiles a scope and names it.
#define VAE_PROFILER_SCOPE()
Profiles a scope.
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mSourceLoader

SourceLoader vae::core::BankLoader::mSourceLoader
private

Definition at line 36 of file vae_bank_loader.hpp.


The documentation for this class was generated from the following file: