MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ process_output()

int MayaFlux::Core::AudioSubsystem::process_output ( double *  output_buffer,
unsigned int  num_frames 
)

Processes output data for audio interface.

Parameters
output_bufferPointer to interleaved output buffer
num_framesNumber of frames to process
Returns
Status code (0 for success)

Processes node graph and buffer operations, then fills the output buffer with processed audio data in interleaved format for the audio interface. This is the main processing entry point called by audio callbacks.

Definition at line 62 of file AudioSubsystem.cpp.

63{
64 m_callback_active.fetch_add(1, std::memory_order_acquire);
65
66 if (output_buffer == nullptr) {
68 "No output available");
69 m_callback_active.fetch_sub(1, std::memory_order_release);
70 return 1;
71 }
72
73 if (!m_is_running.load(std::memory_order_acquire)) {
74 if (output_buffer) {
75 auto total_samples = static_cast<uint32_t>(num_frames * m_stream_info.output.channels);
76 std::memset(output_buffer, 0, total_samples * sizeof(double));
77 }
78 m_callback_active.fetch_sub(1, std::memory_order_release);
79 return 0;
80 }
81
82 if (m_handle == nullptr) {
84 "Invalid processing handle");
85 m_callback_active.fetch_sub(1, std::memory_order_release);
86 return 1;
87 }
88
89 try {
90 uint32_t num_channels = m_stream_info.output.channels;
91 size_t total_samples = static_cast<size_t>(num_frames) * num_channels;
92 std::span<double> output_span(output_buffer, total_samples);
93
96
97 std::vector<std::span<const double>> buffer_data(num_channels);
98 std::vector<std::vector<std::vector<double>>> all_network_outputs(num_channels);
99 bool has_underrun = false;
100
102
103 for (uint32_t channel = 0; channel < num_channels; channel++) {
104 m_handle->buffers.process_channel(channel, num_frames);
105 all_network_outputs[channel] = m_handle->nodes.process_audio_networks(num_frames, channel);
106
107 auto channel_data = m_handle->buffers.read_channel_data(channel);
108
109 if (channel_data.size() < num_frames) {
111 "Channel buffer underrun");
112 has_underrun = true;
113
114 buffer_data[channel] = std::span<const double>();
115 } else {
116 buffer_data[channel] = channel_data;
117 }
118 }
119
120 for (size_t i = 0; i < num_frames; ++i) {
121
123
124 for (size_t j = 0; j < num_channels; ++j) {
125 double buffer_sample = 0.0;
126 if (!buffer_data[j].empty() && i < buffer_data[j].size()) {
127 buffer_sample = buffer_data[j][i];
128 }
129
130 double sample = m_handle->nodes.process_sample(j) + buffer_sample;
131
132 for (const auto& network_buffer : all_network_outputs[j]) {
133 if (i < network_buffer.size()) {
134 sample += network_buffer[i];
135 }
136 }
137
138 size_t index = i * num_channels + j;
139 output_span[index] = std::clamp(sample, -1., 1.);
140 }
141 }
142
145
146 m_callback_active.fetch_sub(1, std::memory_order_release);
147 return has_underrun ? 1 : 0;
148
149 } catch (const std::exception& e) {
151 "Exception during audio output processing: {}", e.what());
152
153 if (output_buffer) {
154 auto total_samples = static_cast<uint32_t>(num_frames * m_stream_info.output.channels);
155 std::memset(output_buffer, 0, total_samples * sizeof(double));
156 }
157
158 m_callback_active.fetch_sub(1, std::memory_order_release);
159 return 1;
160 }
161}
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
std::atomic< int > m_callback_active
Active callback counter.
std::atomic< bool > m_is_running
Subsystem running state.
GlobalStreamInfo m_stream_info
Audio stream configuration.
SubsystemProcessingHandle * m_handle
Reference to processing handle.
std::span< const double > read_channel_data(uint32_t channel) const
Get read-only access to channel data.
void process_channel(uint32_t channel, uint32_t processing_units)
Process specific channel.
std::vector< std::vector< double > > process_audio_networks(uint32_t num_samples, uint32_t channel=0)
NodeProcessingHandle nodes
Node processing interface.
BufferProcessingHandle buffers
Buffer processing interface.
void process_buffer_cycle()
Process all tasks scheduled for current buffer cycle.
void process(uint64_t processing_units)
Process all tasks in token domain.
@ AudioCallback
Audio callback thread - strictest real-time requirements.
@ Core
Core engine, backend, subsystems.
uint32_t channels
Number of discrete channels in this set.
ChannelConfig output
Configuration for output signal channels.

References MayaFlux::Journal::AudioCallback, MayaFlux::Core::SubsystemProcessingHandle::buffers, MayaFlux::Core::GlobalStreamInfo::ChannelConfig::channels, MayaFlux::Core::BufferProcessingHandle::cleanup_completed_routing(), MayaFlux::Core::NodeProcessingHandle::cleanup_completed_routing(), MayaFlux::Journal::Core, m_callback_active, m_handle, m_is_running, m_stream_info, MF_RT_ERROR, MF_RT_WARN, MayaFlux::Core::SubsystemProcessingHandle::nodes, MayaFlux::Core::GlobalStreamInfo::output, MayaFlux::Core::TaskSchedulerHandle::process(), MayaFlux::Core::NodeProcessingHandle::process_audio_networks(), MayaFlux::Core::TaskSchedulerHandle::process_buffer_cycle(), MayaFlux::Core::BufferProcessingHandle::process_channel(), MayaFlux::Core::NodeProcessingHandle::process_sample(), MayaFlux::Core::BufferProcessingHandle::read_channel_data(), MayaFlux::Core::SubsystemProcessingHandle::tasks, MayaFlux::Core::BufferProcessingHandle::update_routing_states(), and MayaFlux::Core::NodeProcessingHandle::update_routing_states().

Referenced by process_audio(), and register_callbacks().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: