MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
CoreAudioBackend.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "AudioBackend.hpp"
4
5#ifdef COREAUDIO_BACKEND
6
7#include <AudioUnit/AudioUnit.h>
8#include <CoreAudio/CoreAudio.h>
9
10namespace MayaFlux::Core {
11
12/**
13 * @class CoreAudioBackend
14 * @brief Native macOS CoreAudio backend.
15 *
16 * Provides device enumeration and stream creation using the CoreAudio HAL.
17 * Unlike RtAudio, this backend talks directly to CoreAudio and does not
18 * rely on any third-party abstraction layer.
19 */
20class CoreAudioBackend final : public IAudioBackend {
21public:
22 CoreAudioBackend();
23 ~CoreAudioBackend() override;
24
25 std::unique_ptr<AudioDevice> create_device_manager() override;
26
27 std::unique_ptr<AudioStream> create_stream(
28 unsigned int output_device_id,
29 unsigned int input_device_id,
30 GlobalStreamInfo& stream_info,
31 void* user_data) override;
32
33 [[nodiscard]] std::string get_version_string() const override;
34
35 void cleanup() override;
36};
37
38/**
39 * @class CoreAudioDevice
40 * @brief Enumerates CoreAudio devices and default endpoints.
41 */
42class CoreAudioDevice final : public AudioDevice {
43public:
44 CoreAudioDevice();
45 ~CoreAudioDevice() override = default;
46
47 [[nodiscard]] std::vector<DeviceInfo> get_output_devices() const override;
48 [[nodiscard]] std::vector<DeviceInfo> get_input_devices() const override;
49
50 [[nodiscard]] unsigned int get_default_output_device() const override;
51 [[nodiscard]] unsigned int get_default_input_device() const override;
52
53 [[nodiscard]] AudioDeviceID resolve_output_device(
54 unsigned int index) const;
55
56 [[nodiscard]] AudioDeviceID resolve_input_device(
57 unsigned int index) const;
58
59private:
60 struct DeviceEntry {
61 AudioDeviceID id {};
62 DeviceInfo info;
63 };
64
65 void enumerate_devices();
66
67 std::vector<DeviceEntry> m_outputs;
68 std::vector<DeviceEntry> m_inputs;
69
70 unsigned int m_default_output = 0;
71 unsigned int m_default_input = 0;
72 AudioDeviceID m_default_output_id = kAudioObjectUnknown;
73 AudioDeviceID m_default_input_id = kAudioObjectUnknown;
74
75 [[nodiscard]] static std::string get_device_name(AudioDeviceID device_id);
76 [[nodiscard]] static uint32_t get_channel_count(
77 AudioDeviceID device_id,
78 AudioObjectPropertyScope scope);
79
80 [[nodiscard]] static double get_nominal_sample_rate(
81 AudioDeviceID device_id);
82};
83
84/**
85 * @class CoreAudioStream
86 * @brief Duplex CoreAudio stream backed by a HAL AudioUnit.
87 *
88 * CoreAudio drives the render callback from its own realtime thread.
89 * Input capture is pulled via AudioUnitRender() from the input bus
90 * and presented to the MayaFlux callback using the standard
91 * output/input/frame-count abstraction.
92 */
93class CoreAudioStream final : public AudioStream {
94public:
95 CoreAudioStream(
96 AudioDeviceID output_device_id,
97 AudioDeviceID input_device_id,
98 GlobalStreamInfo& stream_info,
99 void* user_data);
100
101 ~CoreAudioStream() override;
102
103 void open() override;
104 void start() override;
105 void stop() override;
106 void pause() override;
107 void resume() override;
108 void close() override;
109
110 [[nodiscard]] bool is_running() const override;
111 [[nodiscard]] bool is_open() const override;
112
113 void set_process_callback(
114 std::function<int(void*, void*, unsigned int)> callback) override;
115
116private:
117 /**
118 * @brief CoreAudio realtime callback.
119 */
120 static OSStatus output_callback(
121 void* ref_con,
122 AudioUnitRenderActionFlags* action_flags,
123 const AudioTimeStamp* time_stamp,
124 UInt32 bus_number,
125 UInt32 num_frames,
126 AudioBufferList* io_data);
127
128 static OSStatus input_callback(
129 void* ref_con,
130 AudioUnitRenderActionFlags* action_flags,
131 const AudioTimeStamp* time_stamp,
132 UInt32 bus_number,
133 UInt32 num_frames,
134 AudioBufferList* io_data);
135
136 bool configure_output_unit();
137 bool configure_input_unit();
138 bool configure_output_device();
139 bool configure_input_device();
140 bool configure_output_format();
141 bool configure_input_format();
142
143 AudioUnit m_output_unit = nullptr;
144 AudioUnit m_input_unit = nullptr;
145
146 AudioDeviceID m_output_device_id = kAudioObjectUnknown;
147 AudioDeviceID m_input_device_id = kAudioObjectUnknown;
148
149 GlobalStreamInfo& m_stream_info;
150 void* m_user_data = nullptr;
151
152 std::function<int(void*, void*, unsigned int)> m_process_callback;
153
154 AudioBufferList* m_input_buffer_list = nullptr;
155
156 std::atomic<bool> m_input_enabled { false };
157
158 std::atomic<bool> m_is_open { false };
159 std::atomic<bool> m_is_running { false };
160 std::atomic<bool> m_is_paused { false };
161};
162
163} // namespace MayaFlux::Core
164
165#endif // COREAUDIO_BACKEND
void stop()
Stop all Portal::Graphics operations.
Definition Graphics.cpp:69