MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RtAudioBackend.cpp
Go to the documentation of this file.
1#include "RtAudioBackend.hpp"
4
5namespace {
6
7RtAudio::Api to_rtaudio_api(MayaFlux::Core::GlobalStreamInfo::AudioApi api)
8{
10 switch (api) {
11 case Api::ALSA:
12 return RtAudio::LINUX_ALSA;
13 case Api::PULSE:
14 return RtAudio::LINUX_PULSE;
15 case Api::JACK:
16 return RtAudio::UNIX_JACK;
17 case Api::CORE:
18 return RtAudio::MACOSX_CORE;
19 case Api::WASAPI:
20 return RtAudio::WINDOWS_WASAPI;
21 case Api::ASIO:
22 return RtAudio::WINDOWS_ASIO;
23 case Api::DS:
24 return RtAudio::WINDOWS_DS;
25 case Api::OSS:
26 return RtAudio::LINUX_OSS;
27 default:
28 return RtAudio::UNSPECIFIED;
29 }
30}
31
32}
33
34namespace MayaFlux::Core {
35
37 : m_context(RtAudioSingleton::get_instance())
38{
39}
40
42
43std::unique_ptr<AudioDevice> RtAudioBackend::create_device_manager()
44{
45 return std::make_unique<RtAudioDevice>(m_context);
46}
47
48std::unique_ptr<AudioStream> RtAudioBackend::create_stream(
49 unsigned int output_device_id,
50 unsigned int input_device_id,
51 const GlobalStreamInfo& stream_info,
52 void* user_data)
53{
54 return std::make_unique<RtAudioStream>(
56 output_device_id,
57 input_device_id,
58 stream_info,
59 user_data);
60}
61
63{
64 return RtAudio::getVersion();
65}
66
68{
69 return m_context->getCurrentApi();
70}
71
76
78 : m_context(context)
79 , m_defaultOutputDevice(0)
80 , m_defaultInputDevice(0)
81{
82 if (!context) {
83 throw std::invalid_argument("RtAudioDevice: context must not be null");
84 }
85
86 if (m_context->getDeviceCount() == 0) {
87 throw std::runtime_error("No audio devices found");
88 }
89
90 m_defaultOutputDevice = m_context->getDefaultOutputDevice();
91 m_defaultInputDevice = m_context->getDefaultInputDevice();
92
93 for (unsigned int id : m_context->getDeviceIds()) {
94 try {
95 RtAudio::DeviceInfo info = m_context->getDeviceInfo(id);
96
97 if (info.outputChannels > 0) {
100 }
101
102 if (info.inputChannels > 0) {
105 }
106 } catch (RtAudioErrorType& e) {
107 std::cerr << "Error probing device: " << id << ": " << e << "\n";
108 }
109 }
110}
111
112std::vector<DeviceInfo> RtAudioDevice::get_output_devices() const
113{
114 return m_output_devices;
115}
116
117std::vector<DeviceInfo> RtAudioDevice::get_input_devices() const
118{
119 return m_input_devices;
120}
121
123{
125}
126
128{
130}
131
133 RtAudio* context,
134 unsigned int output_device_id,
135 unsigned int input_device_id,
136 const GlobalStreamInfo& streamInfo,
137 void* userData)
138 : m_context(context)
139 , m_out_parameters()
140 , m_options()
141 , m_userData(userData)
142 , m_isOpen(false)
143 , m_isRunning(false)
144 , m_stream_info(streamInfo)
145{
146 if (!context) {
147 throw std::invalid_argument("RtAudioStream: context must not be null");
148 }
149
150 m_out_parameters.deviceId = output_device_id;
151 m_out_parameters.nChannels = streamInfo.output.channels;
152
153 m_in_parameters.deviceId = input_device_id;
154
156}
157
159{
160 if (is_running()) {
161 stop();
162 }
163 if (is_open()) {
164 close();
165 }
166}
167
169{
170 m_options.flags = 0;
171
172 switch (m_stream_info.priority) {
174 m_options.flags |= RTAUDIO_SCHEDULE_REALTIME;
175 break;
177 default:
178 break;
179 }
180
182 m_options.flags |= RTAUDIO_NONINTERLEAVED;
183 }
184
185 if (m_stream_info.buffer_count > 0) {
186 m_options.numberOfBuffers = static_cast<unsigned int>(m_stream_info.buffer_count);
187 }
188
189 m_options.priority = 0;
190
191 auto rtSpecificOpt = m_stream_info.backend_options.find("rtaudio.exclusive");
192 if (rtSpecificOpt != m_stream_info.backend_options.end()) {
193 try {
194 bool exclusive = std::any_cast<bool>(rtSpecificOpt->second);
195 if (exclusive) {
196#ifdef _WIN32
197 m_options.flags |= RtAudio::Api::WINDOWS_WASAPI;
198#endif
199 }
200 } catch (const std::bad_any_cast&) {
201 error_rethrow(
204 std::source_location::current(),
205 "Invalid type for rtaudio.exclusive option; expected bool");
206 }
207 }
208}
209
211{
212 if (is_open()) {
213 return;
214 }
215
216 try {
217 RtAudioFormat format = RTAUDIO_FLOAT64;
218
219 switch (m_stream_info.format) {
221 format = RTAUDIO_FLOAT32;
222 break;
224 format = RTAUDIO_FLOAT64;
225 break;
227 format = RTAUDIO_SINT16;
228 break;
230 format = RTAUDIO_SINT24;
231 break;
233 format = RTAUDIO_SINT32;
234 break;
235 }
236
237 RtAudio::StreamParameters* inputParamsPtr = nullptr;
238
240 // inputParams.deviceId = m_stream_info.input.device_id >= 0 ? m_stream_info.input.device_id : m_context->getDefaultInputDevice();
242 // inputParams.firstChannel = 0;
243 inputParamsPtr = &m_in_parameters;
244 }
245
247
248 m_context->openStream(
250 inputParamsPtr,
251 format,
255 this,
256 &m_options);
257
258 m_isOpen = true;
259 } catch (const RtAudioErrorType& e) {
261 m_isOpen = false;
262
263 error_rethrow(
266 std::source_location::current(),
267 "Failed to open RtAudio stream: {}",
268 m_context->getErrorText());
269 }
270}
271
273{
274 if (!is_open()) {
275 throw std::runtime_error("Cannot start stream: stream not open");
276 }
277
278 if (is_running()) {
279 return;
280 }
281
282 try {
283 m_context->startStream();
284 m_isRunning = true;
285 } catch (const RtAudioErrorType& e) {
286 error_rethrow(
289 std::source_location::current(),
290 "Failed to start RtAudio stream: {}",
291 m_context->getErrorText());
292 }
293}
294
296{
297 if (!is_running()) {
298 return;
299 }
300
301 try {
302 m_context->stopStream();
303 m_isRunning = false;
304 } catch (const RtAudioErrorType& e) {
305 error_rethrow(
308 std::source_location::current(),
309 "Failed to stop RtAudio stream: {}",
310 m_context->getErrorText());
311 }
312}
313
315{
316 if (!m_isOpen || !m_context) {
317 return;
318 }
319
320 if (is_running()) {
321 stop();
322 }
323
324 try {
325 if (m_context->isStreamOpen()) {
326 m_context->closeStream();
328 }
329 m_isOpen = false;
330 } catch (const RtAudioErrorType& e) {
331 m_isOpen = false;
333
334 error_rethrow(
337 std::source_location::current(),
338 "Failed to close RtAudio stream: {}",
339 m_context->getErrorText());
340 }
341}
342
344{
345 return m_isRunning && m_context->isStreamRunning();
346}
347
349{
350 return m_isOpen && m_context->isStreamOpen();
351}
352
354 std::function<int(void*, void*, unsigned int)> processCallback)
355{
356 m_process_callback = std::move(processCallback);
357}
358
360 void* output_buffer,
361 void* input_buffer,
362 unsigned int num_frames,
363 double /*stream_time*/,
364 RtAudioStreamStatus /*status*/,
365 void* user_data)
366{
367 auto stream = static_cast<RtAudioStream*>(user_data);
368
369 if (stream && stream->m_process_callback) {
370 return stream->m_process_callback(output_buffer, input_buffer, num_frames);
371 }
372
373 return 0;
374}
375
377{
378 switch (type) {
380 return std::make_unique<RtAudioBackend>();
381 default:
382 throw std::runtime_error("Unsupported audio backend type");
383 }
384}
385
386} // namespace MayaFlux::Core
static std::unique_ptr< IAudioBackend > create_backend(Utils::AudioBackendType type)
Creates a specific audio backend implementation.
int get_api_type() const override
Retrieves the RtAudio API type identifier.
std::string get_version_string() const override
Retrieves the RtAudio library version.
std::unique_ptr< AudioStream > create_stream(unsigned int output_device_id, unsigned int input_device_id, const GlobalStreamInfo &stream_info, void *user_data) override
Creates an RtAudio-specific audio stream.
RtAudio * m_context
Pointer to the underlying RtAudio context.
void cleanup() override
Releases all resources held by the backend.
RtAudioBackend()
Initializes the RtAudio backend.
std::unique_ptr< AudioDevice > create_device_manager() override
Creates an RtAudio-specific device manager.
~RtAudioBackend() override
Cleans up the RtAudio backend.
std::vector< DeviceInfo > m_output_devices
Cached list of output devices.
unsigned int m_defaultOutputDevice
System identifier for the default output device.
RtAudioDevice(RtAudio *context)
Initializes the device manager with an RtAudio context.
RtAudio * m_context
Pointer to the underlying RtAudio context.
std::vector< DeviceInfo > get_input_devices() const override
Retrieves information about all available input devices.
std::vector< DeviceInfo > m_input_devices
Cached list of input devices.
std::vector< DeviceInfo > get_output_devices() const override
Retrieves information about all available output devices.
unsigned int get_default_output_device() const override
Gets the system's primary output device identifier.
unsigned int get_default_input_device() const override
Gets the system's primary input device identifier.
unsigned int m_defaultInputDevice
System identifier for the default input device.
static void mark_stream_closed()
Deregisters an active audio stream from the system.
static void mark_stream_open()
Registers an active audio stream in the system.
static void cleanup()
Releases all audio system resources.
Thread-safe global access point for audio system resources.
RtAudio::StreamOptions m_options
RtAudio-specific stream options.
GlobalStreamInfo m_stream_info
Copy of the stream configuration for reference.
void set_process_callback(std::function< int(void *, void *, unsigned int)> processCallback) override
Sets the function to process audio data.
void start() override
Activates the audio stream and begins data transfer.
void stop() override
Deactivates the audio stream and halts data transfer.
void configure_stream_options()
Configures RtAudio stream options based on GlobalStreamInfo.
~RtAudioStream() override
Ensures proper cleanup of stream resources.
bool m_isOpen
Flag indicating if the stream is currently open.
bool is_open() const override
Checks if the stream is initialized and ready for activation.
void open() override
Initializes the audio stream and allocates required resources.
bool m_isRunning
Flag indicating if the stream is currently running.
RtAudio::StreamParameters m_in_parameters
RtAudio-specific stream input configuration parameters.
RtAudio::StreamParameters m_out_parameters
RtAudio-specific stream output configuration parameters.
RtAudioStream(RtAudio *context, unsigned int output_device_id, unsigned int input_device_id, const GlobalStreamInfo &streamInfo, void *userData)
Initializes an audio stream with the specified configuration.
void close() override
Terminates the audio stream and releases all resources.
RtAudio * m_context
Pointer to the underlying RtAudio context.
std::function< int(void *, void *, unsigned int)> m_process_callback
User-provided callback function for audio processing.
static int rtAudioCallback(void *output_buffer, void *input_buffer, unsigned int num_frames, double stream_time, RtAudioStreamStatus status, void *user_data)
Static callback function for the RtAudio API.
bool is_running() const override
Checks if the stream is actively processing audio data.
RtAudio implementation of the audio stream interface.
static DeviceInfo convert_device_info(const RtAudio::DeviceInfo &rtInfo, unsigned int id, unsigned int defaultOutputDevice, unsigned int defaultInputDevice)
Converts RtAudio-specific device information to the engine's device model.
@ AudioBackend
Audio processing backend (RtAudio, JACK, ASIO)
@ Core
Core engine, backend, subsystems.
uint32_t channels
Number of discrete channels in this set.
bool enabled
Whether this channel set is active in the stream.
uint32_t buffer_size
Number of samples per processing block.
ChannelConfig input
Configuration for input signal channels (disabled by default)
AudioApi
Enumeration of supported audio APIs for wrapper backends like RtAudio.
uint32_t sample_rate
Number of samples processed per second (Hz)
@ FLOAT64
64-bit floating point representation (-1.0 to 1.0)
@ INT16
16-bit integer representation (-32768 to 32767)
@ INT32
32-bit integer representation (-2147483648 to 2147483647)
@ INT24
24-bit integer representation (-8388608 to 8388607)
@ FLOAT32
32-bit floating point representation (-1.0 to 1.0)
ChannelConfig output
Configuration for output signal channels.
AudioFormat format
Sample data format for stream processing.
@ REALTIME
Maximum resource priority with timing guarantees.
StreamPriority priority
System resource priority for audio processing.
double buffer_count
Number of buffers in the processing queue (0 for system default)
std::unordered_map< std::string, std::any > backend_options
Backend-specific configuration parameters.
bool non_interleaved
Channel organization mode (true: planar, false: interleaved)
Comprehensive configuration for digital audio stream processing.