19#include "../../external/tklb/src/util/TMath.hpp"
24#ifndef VAE_NO_AUDIO_DEVICE
28#ifndef VAE_NO_AUDIO_THREAD
31 #include <condition_variable>
39#define _VAE_PUBLIC_API
42namespace vae {
namespace core {
65 #ifndef VAE_NO_AUDIO_DEVICE
69 #ifndef VAE_NO_AUDIO_THREAD
78 #ifndef VAE_NO_AUDIO_DEVICE
97 auto remaining = d.canPush();
101 if (remaining < 32) {
110 Size renderedNormal = 0;
111 Size renderedSpatial = 0;
128 VAE_PROFILER_PLOT(
"Rendered Total Voices", int64_t(renderedSpatial + renderedNormal));
137 for (
Size i = 0; i < remaining; i++) {
170 #ifndef VAE_NO_AUDIO_THREAD
179 std::unique_lock<std::mutex> l(
mMutex);
252 #ifndef VAE_NO_AUDIO_DEVICE
264 #ifndef VAE_NO_AUDIO_THREAD
271 VAE_ERROR(
"Can't mix in audio thread since it's disabled via VAE_NO_AUDIO_THREAD")
287 #ifndef VAE_NO_AUDIO_DEVICE
289 #ifndef VAE_NO_AUDIO_THREAD
345#define VAE_NO_AUDIO_DEVICE
346 #ifdef VAE_NO_AUDIO_DEVICE
347 template <
typename T>
350 while (time < frames) {
398 VAE_ERROR(
"No emitter %u registered", emitterHandle)
403 VAE_ERROR(
"Fired event %i on unloaded bank %i", eventHandle, bankHandle)
409 if (bank.events.size() <= eventHandle) {
410 VAE_WARN(
"Fired missing event %i on bank %i", eventHandle, bankHandle)
414 auto&
event = bank.events[eventHandle];
420 VAE_DEBUG_EVENT(
"Event %i:%i starts source %i", eventHandle, bankHandle, event.source)
426 event, bankHandle, gain, emitterHandle, l.
id, mixerHandle
432 event, bankHandle, gain, emitterHandle, listenerHandle, mixerHandle
438 for (
auto& i : event.chained_events) {
440 VAE_DEBUG_EVENT(
"Event %i:%i starts chained event %i", eventHandle, bankHandle, i)
442 bankHandle, i, emitterHandle, gain,
443 mixerHandle, listenerHandle
448 VAE_DEBUG_EVENT(
"Event %i:%i failed to start voices", eventHandle, bankHandle)
455 auto& i =
event.chained_events[index];
457 VAE_DEBUG_EVENT(
"Event %i:%i starts random event %i", eventHandle, bankHandle, i)
459 bankHandle, i, emitterHandle, gain,
460 mixerHandle, listenerHandle
469 VAE_DEBUG_EVENT(
"Event %i:%i stops source %i", eventHandle, bankHandle, event.source)
472 for (
auto& i : event.chained_events) {
475 VAE_DEBUG_EVENT(
"Event %i:%i stops voices from event %i", eventHandle, bankHandle, i)
480 VAE_DEBUG_EVENT(
"Event %i:%i stops voices in mixer %i", eventHandle, bankHandle, event.mixer)
489 constexpr int as =
sizeof(data);
491 data.
bank = bankHandle;
492 data.
event = eventHandle;
521 bankHandle, eventHandle, emitterHandle,
522 gain, mixerHandle, listenerHandle
559#pragma region emitter
680#pragma endregion emitter
723 auto& m = b.
mixers[mixer];
724 auto& e = m.effects[index];
725 auto& p = e.parameters[param];
733#pragma endregion emitter
735#pragma region listener
770#pragma endregion listsner
773#pragma region bank_handling
837 VAE_INFO(
"Start Unload bank %i", bankHandle)
847 VAE_INFO(
"Start unloading all banks")
852#pragma endregion bank_handling
#define TKLB_DELEGATE(func, thisPrtRef)
void multiply(const AudioBufferTpl< T2, STORAGE2 > &buffer, Size length=0, Size offsetSrc=0, Size offsetDst=0)
Multiply two buffers.
void add(const AudioBufferTpl< T2, STORAGE2 > &buffer, Size length=0, Size offsetSrc=0, Size offsetDst=0)
Add the provided buffer.
uchar channels() const
Returns the amount of channels.
void setValidSize(const Size v)
Set the amount of valid samples currently in the buffer This is mostly a convenience flag since the a...
void set(const T2 *samples, Size length, const uchar channel=0, const Size offsetDst=0)
Set a single channel from an array.
Size putInterleaved(T2 *buffer, Size length=0, const Size offset=0) const
Puts the interleaved contents in the target buffer.
static BackendDummy & instance()
Backend interface used to query devices before creating a actual device object.
virtual Device * createDevice(const EngineConfig &)=0
Creates a device instance for this backend.
Result load(const char *path, Size size, const char *rootPath, int sampleRate)
Result unloadFromId(BankHandle bankHandle)
Result addEvent(BankHandle bankHandle, Event &event)
Result addMixer(BankHandle bankHandle, Mixer &mixer)
Bank & get(BankHandle bank)
void forEach(const Func &&func)
Iterate all loaded banks.
Result addSource(BankHandle bankHandle, Source &source, int sampleRate)
Result addBank(Bank &bank)
bool has(BankHandle bank)
Interface for audio devices.
virtual bool openDevice(DeviceInfo &device)=0
Opens a specific audio device.
void setCallback(Callback callback)
Central class handling all outside communication.
Result addMixer(BankHandle bankHandle, Mixer &mixer)
SpatialProcessor mSpatialProcessor
Spatial voice processor.
Engine & operator=(const Engine &)=delete
Result _VAE_PUBLIC_API fireGlobalEvent(GlobalEventHandle globalHandle, EmitterHandle emitterHandle, Sample gain=1.0, MixerHandle mixerHandle=InvalidMixerHandle, ListenerHandle listenerHandle=AllListeners)
Works like fireEvent but with a global Event identifier.
void process(const SampleIndex frames, T *output, int channels)
Result _VAE_PUBLIC_API addEmitter(EmitterHandle h)
Adds an emitter with a custom handle, can be an internal ID for example.
Processor mProcessor
Default Voice processor.
Result setMixerEffectParameter(BankHandle bank, MixerHandle mixer, Size index, Size param, Sample value)
Set the Mixer Effect Parameter.
ConditionVariable mAudioConsumed
Notifies the audio thread when more audio is needed.
Result muteMixerEffect(BankHandle bank, MixerHandle mixer, Size index, bool mute)
Bypass a effect in a mixer.
Result addEvent(BankHandle bankHandle, Event &event)
Add or replace event in a bank Locks audio thread.
void _VAE_PUBLIC_API setSpeed(EmitterHandle emitter, float speed)
Set the playback speed.
EmitterHandle _VAE_PUBLIC_API createEmitter()
Creates an emitter and returns the handle.
Sample mMasterVolume
Master Colume applied after limiting.
Result _VAE_PUBLIC_API fireEvent(BankHandle bankHandle, EventHandle eventHandle, EmitterHandle emitterHandle, Sample gain=1.0, MixerHandle mixerHandle=InvalidMixerHandle, ListenerHandle listenerHandle=AllListeners)
Main mechanism to start and stop sounds.
ScratchBuffer mScratchBuffer
used to combine the signal from all banks and push it to the device
Thread * mAudioThread
Thread processing voices and mixers.
std::condition_variable ConditionVariable
void _VAE_PUBLIC_API setLowpass(EmitterHandle emitter, float cutoff)
Simple lowpass filter for the voices.
Result setMixerVolume(BankHandle bank, MixerHandle mixer, Sample volume)
Set the Mixer Volume.
Result loadBank(Bank &bank)
Load bank from memory.
Result _VAE_PUBLIC_API init(const EngineConfig &config={})
Initializes the engine and does most of the upfront allocations.
Engine(const Engine *)=delete
SampleIndex mTime
Global engine time in samples.
void _VAE_PUBLIC_API setMasterVolume(Sample volume)
Set the global output volume before the limiter.
bool _VAE_PUBLIC_API checkVersion(int major, int minor, int patch)
Check if the compiled version matches.
Size _VAE_PUBLIC_API getActiveVoiceCount() const
Get the number of currently playing Voices.
Result _VAE_PUBLIC_API removeListener(ListenerHandle listener)
Unregister listener.
Size _VAE_PUBLIC_API getStreamTime() const
Engine(const Engine &)=delete
Don't allow any kind of move of copy of the object.
std::mutex mMutex
Mutex needed to use mAudioConsumed, doesn't actually do anything else.
Result _VAE_PUBLIC_API stop()
Stops processing and waits for audio thead to clean up.
MixerProcessor mMixerProcessor
Mixer channel processor.
Result _VAE_PUBLIC_API loadBank(const char *path, Size size=0)
Load bank from filesystem.
Result _VAE_PUBLIC_API loadHRTF(const char *path, Size size=0)
void _VAE_PUBLIC_API setVolume(EmitterHandle emitter, Sample gain)
Sets the volume of all active voices with this emitter.
void onThreadedBufferSwap(Device *device)
Called from audio device when using seperate audio thread.
EmitterHandle _VAE_PUBLIC_API createAutoEmitter(BankHandle bank, EventHandle event, float maxDist, const LocationDirection &locDir, float spread)
Emitter which triggers an event once a listener is close enough.
Result _VAE_PUBLIC_API start()
Tries to open default device and start audio thread.
Result addBank(Bank &bank)
void onBufferSwap(Device *device)
Called from audio device when it needs more audio.
Result addSource(BankHandle bankHandle, Source &source)
Add or replace a source in a bank.
Result _VAE_PUBLIC_API removeEmitter(EmitterHandle h)
Unregister a emiter an kill all its voices.
Sample mLimiterLastPeak
Master limiter last peak.
void _VAE_PUBLIC_API unloadAllBanks()
Unload every bank and data associated with it.
Result _VAE_PUBLIC_API unloadBankFromId(BankHandle bankHandle)
Unload bank from handle.
Time mTimeFract
Global engine time in seconds.
void threadedProcess()
Called from own audio thread, not the device.
SpatialManager mSpatialManager
Holds and manages spatial emitters.
void _VAE_PUBLIC_API seek(EmitterHandle emitter, Size time)
Set the current time of all voices with the emitter.
void _VAE_PUBLIC_API update()
Update function needs to be called regularly to handle outbound events and other housekeeping.
VoiceManger mVoiceManager
Holds and handle voices.
ListenerHandle _VAE_PUBLIC_API createListener()
Create a Listener object.
Device * mDevice
Output device.
BankManager mBankManager
Holds and manages banks.
void _VAE_PUBLIC_API setHighpass(EmitterHandle emitter, float cutoff)
Simple highpass filter for the voices.
Result _VAE_PUBLIC_API setListener(ListenerHandle listener, const LocationOrientation &locOr)
Set the position of a listener.
EngineConfig mConfig
Config object provided at initlalization.
Result _VAE_PUBLIC_API setEmitter(EmitterHandle emitter, const LocationDirection &locDir, float spread)
Set the Emitter position, orientation and spread.
Result _VAE_PUBLIC_API stopEmitter(EmitterHandle emitter)
Stop all voices from emitter.
void process()
Main processing function.
void mix(VoiceManger &manager, Bank &bank, SampleIndex frames)
Process the mixers for a single bank.
Non spatial voice processor.
Size mix(VoiceManger &manager, Bank &bank, SampleIndex frames, Size sampleRate)
Process a single bank.
ListenerHandle createListener()
EmitterHandle createEmitter()
Result addEmitter(EmitterHandle e)
Result setListener(ListenerHandle listener, const LocationOrientation &locOr)
EmitterHandle createAutoEmitter(BankHandle bank, EventHandle event, float maxDist, const LocationDirection &locDir, Sample spread)
bool hasEmitter(EmitterHandle e)
Result removeListener(ListenerHandle listener)
Result setEmitter(EmitterHandle emitter, const LocationDirection &locDir, Sample spread)
Result removeEmitter(EmitterHandle e)
Result forListeners(ListenerHandle handle, const Func &&func)
void update(VoiceManger &manager, Callback callback)
Emitter & getEmitter(EmitterHandle e)
Size mix(VoiceManger &manager, Bank &bank, SpatialManager &spatial, SampleIndex frames, Size sampleRate)
Process a single bank.
Result loadHRTF(const char *path, Size length, const char *rootPath, Size sampleRate)
There is only one voice pool and VAE and it's managed here.
Size getActiveVoiceCount() const
Result stop(Voice &v)
Stops a voice.
Result play(Event &event, const BankHandle bank, const Sample gain, const EmitterHandle emitter, const ListenerHandle listener, const MixerHandle mixer)
void setVoiceProperty(EmitterHandle emitter, T Voice::*member, const T &value)
void forEachFinishedVoice(const Func &&func)
static void set(void *dst, const unsigned char val, size_t size)
memset wrapper
T min(const T &v1, const T &v2)
T max(const T &v1, const T &v2)
constexpr Size MaxBlock
Maximum block size.
constexpr Size MaxChainedEvents
How many chained events can fit in chain_events on the core::Event structure.
constexpr unsigned char MaxChannels
Maximum channel count used to pre allocate buffers.
const char *const audioFrame
AudioBuffer::Size SampleIndex
constexpr int _VAE_ENGINE_SIZE
constexpr void splitGlobalEventHandle(const GlobalEventHandle &handle, BankHandle &bank, EventHandle &event)
Contains Typedefinitions and basic structures use by the public API and internally.
constexpr ListenerHandle AllListeners
Will address all listeners.
constexpr EmitterHandle InvalidEmitterHandle
unsigned int Size
How the elements are addressed in the heapbuffer.
float Sample
Default sample types used where ever possible, changing this means the engine needs to be recompiled,...
constexpr SourceHandle InvalidSourceHandle
double Time
Time sotred in seconds.
SmallHandle ListenerHandle
constexpr EventHandle InvalidEventHandle
LargeHandle EmitterHandle
GenericHandle EventHandle
The handle used to address events within a bank.
Result
Return Types for most engine functions.
@ InvalidBank
Valid bank handle needed.
@ InvalidEmitter
Emitter probably wasn't registered.
@ ValidHandleRequired
Handle provided wasn't valid but needs to be.
@ DeviceError
Can't open audio device.
constexpr MixerHandle InvalidMixerHandle
LargeHandle GlobalEventHandle
Used to globally address events, holds space for BankHandle and EventHandle.
Settings for the engine defined at EnginePimpl::init.
void * eventCallbackContext
Custom data that can be accached to the EventCallback to maintain context.
const char * rootPath
Path where the bank files are located, needs to end with a trailing /.
bool updateInAudioThread
If this is true update() does not need to be called on the engine instance.
EventCallback eventCallback
Each time a event of the type emit gets triggered Used to get information about ending sounds and sim...
bool processInBufferSwitch
If enabled, all processing and mixing will happen in the audio callback.
Size internalSampleRate
Samplerate requested from device.
Struct containing relevant data passed to EventCallback provided in the EngineConfig.
void * context
Can point to custom context data also provided when setting the callback, ! not context based on even...
EmitterHandle emitter
Which emitter.
EventHandle event
Which event.
BankHandle bank
Which bank the event is from.
Emitters have a position and direction vector.
Listener uses additional up vector.
Bank object containing Sources, Mixers and Events Can be loaded and unloaded at runtime.
HeapBuffer< Mixer > mixers
Audio Mixers which can have effects ! is presorted !
HeapBuffer< Event > events
Events defined.
bool autoplaying
whether the event was already triggered
An Event is used to control most of the eingines behavior.
@ 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.
static constexpr MixerHandle MasterMixerHandle
This is the master mixer for a bank.
Real speed
Playback speed, will alter pitch.
Real lowpass
Lowpasses the signal as the value approaches 1.
Real highpass
Highpasses the signal as the value approaches 1.
SourceHandle source
If invalid, means voice is not playing.
Sample gain
Volume of the voice.
EventHandle event
Which event triggered the voice to be played.
BankHandle bank
Which bank it belongs to.
MixerHandle mixer
Where the voice should mix to.
EmitterHandle emitter
Emitter used to control voice properties.
SampleIndex time
Current time in samples.
#define VAE_VERSION_MAJOR
#define VAE_VERSION_MINOR
#define VAE_VERSION_PATCH
#define _VAE_PUBLIC_API
Marks a function for export to the generated vae::EnginePimpl class generated from generate_pimpl....
#define VAE_ERROR(msg,...)
#define VAE_WARN(msg,...)
#define VAE_INFO(msg,...)
#define VAE_DEBUG_EVENT(msg,...)
#define VAE_DEBUG(msg,...)
#define VAE_PROFILER_FRAME_MARK_START(name)
Starts a named frame, uses const defined above to maintain the same pointer.
#define VAE_PROFILER_SCOPE_NAMED(name)
Profiles a scope and names it.
#define VAE_PROFILER_FRAME_MARK_END(name)
Stops a named frame.
#define VAE_PROFILER_SCOPE()
Profiles a scope.
#define VAE_PROFILER_PLOT(name, value)
Records a value.
#define VEA_PROFILER_THREAD_NAME(name)
Sets name for current thread.
#define VAE_PROFILER_FRAME_MARK()
Marks a frame to calculate FPS, not really needed for audio.
Internal types used across VAE.
Holds all voices and starts/stops them.