VAE - Virtual Audio Engine 1
Small Data Driven Audio Engine
vae_rtaudio.hpp
Go to the documentation of this file.
1#ifndef _VAE_RTAUDIO
2#define _VAE_RTAUDIO
3
4#include "./vae_device.hpp"
5#include "../vae_config.hpp"
6#include "../vae_util.hpp"
7
8#include "../../../external/rtaudio/RtAudio.h"
9
10namespace vae { namespace core {
11
12 class DeviceRtaudio final : public Device {
13 RtAudio mAudio; // Rt Device instance
14
15 bool cleanUp() {
16 VAE_PROFILER_SCOPE_NAMED("Cleanup RtAudio")
17 if (mAudio.isStreamRunning()) {
18 VAE_PROFILER_SCOPE_NAMED("Stop RtAudio Stream")
19 auto result = mAudio.stopStream();
20 if (result != RTAUDIO_NO_ERROR) {
21 VAE_ASSERT(false)
22 return false;
23 }
24 }
25 if (mAudio.isStreamOpen()) {
26 VAE_PROFILER_SCOPE_NAMED("Close RtAudio Stream")
27 mAudio.closeStream();
28 }
29 return true;
30 }
31
32 /**
33 * @brief Function called from the RtAudio thread.
34 */
35 static int AudioCallback(
36 void* out, void* in, unsigned int frames,
37 double streamTime, RtAudioStreamStatus status, void* data
38 ) {
39 (void) streamTime; // Prevent unused variable warnings.
40 (void) status; // Prevent unused variable warnings.
41 auto inFloat = static_cast<const float*>(in);
42 auto outFloat = static_cast<float*>(out);
43 static_cast<AudioThreadWorker*>(data)
44 ->swapBufferInterleaved(inFloat, outFloat, frames);
45 return 0;
46 }
47
48
49 public:
51 Backend& backend, const EngineConfig& config
52 ) : Device(backend, config) { };
53
55 cleanUp();
56 }
57
58 bool openDevice(DeviceInfo& device) override {
59 if (mBackend.getDeviceCount() < Size(device.id)) {
60 VAE_ERROR("Failed to open deivce with index out of bounds")
61 return false;
62 }
63 device.channelsIn = tklb::clamp<int>(device.channelsIn, 0, StaticConfig::MaxChannels);
64 device.channelsOut = tklb::clamp<int>(device.channelsOut, 0, StaticConfig::MaxChannels);
65 RtAudio::StreamParameters inParams, outParams;
66 inParams.deviceId = device.id;
67 inParams.nChannels = device.channelsIn;
68 outParams.deviceId = device.id;
69 outParams.nChannels = device.channelsOut;
70 if (device.bufferSize == 0) {
72 }
73
74 RtAudioErrorType result;
75 {
76 VAE_PROFILER_SCOPE_NAMED("Open RtAudio stream")
77 result = mAudio.openStream(
78 outParams.nChannels ? &outParams : nullptr,
79 inParams.nChannels ? &inParams : nullptr,
80 RTAUDIO_FLOAT32, device.sampleRate,
82 );
83 }
84
85 if (result != RTAUDIO_NO_ERROR) {
86 VAE_ERROR("Failed to open RtAudio device with code %i", result)
87 return false;
88 }
89
90 device.sampleRate = mAudio.getStreamSampleRate();
91 device.channelsIn = inParams.nChannels;
92 device.channelsOut = outParams.nChannels;
93
94 init(
95 device.sampleRate, device.channelsIn, device.channelsOut,
96 device.bufferSize // RtAudio writes back to this on openStream
97 );
98 {
99 VAE_PROFILER_SCOPE_NAMED("Start RtAudio stream")
100 result = mAudio.startStream();
101 }
102
103 if (result != RTAUDIO_NO_ERROR) {
104 VAE_ERROR("Failed to open RtAudio device with code %i", result)
105 cleanUp();
106 return false;
107 }
108
109 postInit();
110
111 return true;
112 }
113
114 bool closeDevice() override { return cleanUp(); }
115 };
116
117 class BackendRtAudio final : public Backend {
118 RtAudio mAudio; // This instance is only used for probing
120
122 public:
125 static BackendRtAudio backend;
126 return backend;
127 }
128
129 unsigned int getDeviceCount() override {
130 return mAudio.getDeviceCount();
131 }
132
133 DeviceInfo getDevice(unsigned int index) override {
134 const auto rtInfo = mAudio.getDeviceInfo(index);
135 TKLB_ASSERT(rtInfo.probed) // device needs to be probed
136
137 DeviceInfo info;
138 info.id = index;
139 info.channelsIn = rtInfo.inputChannels;
140 info.channelsOut = rtInfo.outputChannels;
141 info.sampleRate = Uint(rtInfo.preferredSampleRate);
142 tklb::memory::stringCopy(info.name, rtInfo.name.c_str(), sizeof(DeviceInfo::name));
143 tklb::memory::stringCopy(info.api, getName(), sizeof(DeviceInfo::api), false);
144 return info;
145 };
146
147 const char* getName() const override { return "rtaudio"; };
148
150 return getDevice(mAudio.getDefaultInputDevice());
151 };
152
154 return getDevice(mAudio.getDefaultOutputDevice());
155 };
156
157 Device* createDevice(const EngineConfig& config) override {
158 return new DeviceRtaudio(*this, config);
159 }
160 };
161} } // namespace vae::core
162
163#endif // _VAE_RTAUDIO
#define TKLB_ASSERT(condition)
Wrap assertions.
Definition: TAssert.h:18
Backend interface used to query devices before creating a actual device object.
Definition: vae_backend.hpp:14
virtual Size getDeviceCount()=0
Gets number of devices, needed to iterate them.
unsigned int getDeviceCount() override
Gets number of devices, needed to iterate them.
DeviceInfo getDefaultOutputDevice() override
const char * getName() const override
Returns name of the api.
static BackendRtAudio & instance()
DeviceInfo getDefaultInputDevice() override
Device * createDevice(const EngineConfig &config) override
Creates a device instance for this backend.
DeviceInfo getDevice(unsigned int index) override
Returns a spefic device info for index.
Interface for audio devices.
Definition: vae_device.hpp:18
AudioThreadWorker mWorker
Definition: vae_device.hpp:102
const EngineConfig & mConfig
Definition: vae_device.hpp:24
void init(Size sampleRate, Uchar channelsIn, Uchar channelsOut, Size bufferSize)
initializes buffers, queues and resamplers if needed Has to be called in openDevice once the samplera...
Definition: vae_device.hpp:114
Backend & mBackend
Definition: vae_device.hpp:23
static int AudioCallback(void *out, void *in, unsigned int frames, double streamTime, RtAudioStreamStatus status, void *data)
Function called from the RtAudio thread.
Definition: vae_rtaudio.hpp:35
bool openDevice(DeviceInfo &device) override
Opens a specific audio device.
Definition: vae_rtaudio.hpp:58
bool closeDevice() override
Closes the currently open device.
DeviceRtaudio(Backend &backend, const EngineConfig &config)
Definition: vae_rtaudio.hpp:50
static void stringCopy(char *dst, const char *src, size_t size, bool terminate=true)
Definition: TMemoryUtil.hpp:26
constexpr unsigned char MaxChannels
Maximum channel count used to pre allocate buffers.
Definition: vae.hpp:268
unsigned int Uint
Definition: vae_types.hpp:46
Contains Typedefinitions and basic structures use by the public API and internally.
Definition: vae.hpp:31
unsigned int Size
How the elements are addressed in the heapbuffer.
Definition: vae.hpp:33
Basic struct describing a audio device.
Definition: vae.hpp:102
unsigned int sampleRate
TODO not used?
Definition: vae.hpp:104
unsigned char channelsIn
Definition: vae.hpp:108
unsigned int bufferSize
desired bufferSize
Definition: vae.hpp:107
unsigned char channelsOut
Definition: vae.hpp:109
char name[255]
Device name reported from backend.
Definition: vae.hpp:105
int id
Negative values for invalid device.
Definition: vae.hpp:103
char api[4]
API abbreviation.
Definition: vae.hpp:106
Settings for the engine defined at EnginePimpl::init.
Definition: vae.hpp:157
Size preferredBufferSize
Buffer size that will be requested from device.
Definition: vae.hpp:233
Data shared with audio thread.
Definition: vae_device.hpp:37
#define VAE_ERROR(msg,...)
Definition: vae_logger.hpp:80
#define VAE_PROFILER_SCOPE_NAMED(name)
Profiles a scope and names it.
#define VAE_PROFILER_OVERLOAD_NEW()
Overloads new and delete of class to be tracked.
#define VAE_ASSERT(condition)
Definition: vae_util.hpp:11