MayaFlux 0.4.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 73 of file AudioSubsystem.cpp.

74{
75 m_callback_active.fetch_add(1, std::memory_order_acquire);
76
77 if (output_buffer == nullptr) {
79 "No output available");
80 m_callback_active.fetch_sub(1, std::memory_order_release);
81 return 1;
82 }
83
84 if (!m_is_running.load(std::memory_order_acquire)) {
85 if (output_buffer) {
86 auto total_samples = static_cast<uint32_t>(num_frames * m_stream_info.output.channels);
87 std::memset(output_buffer, 0, total_samples * sizeof(double));
88 }
89 m_callback_active.fetch_sub(1, std::memory_order_release);
90 return 0;
91 }
92
93 if (m_handle == nullptr) {
95 "Invalid processing handle");
96 m_callback_active.fetch_sub(1, std::memory_order_release);
97 return 1;
98 }
99
100 try {
101 uint32_t num_channels = m_stream_info.output.channels;
102 size_t total_samples = static_cast<size_t>(num_frames) * num_channels;
103 std::span<double> output_span(output_buffer, total_samples);
104
107
108 std::vector<std::span<const double>> buffer_data(num_channels);
109 std::vector<std::vector<std::vector<double>>> all_network_outputs(num_channels);
110 bool has_underrun = false;
111
113
114 for (uint32_t channel = 0; channel < num_channels; channel++) {
115 m_handle->buffers.process_channel(channel, num_frames);
116 all_network_outputs[channel] = m_handle->nodes.process_audio_networks(num_frames, channel);
117
118 auto channel_data = m_handle->buffers.read_channel_data(channel);
119
120 if (channel_data.size() < num_frames) {
122 "Channel buffer underrun");
123 has_underrun = true;
124
125 buffer_data[channel] = std::span<const double>();
126 } else {
127 buffer_data[channel] = channel_data;
128 }
129 }
130
131 for (size_t i = 0; i < num_frames; ++i) {
132
134
135 for (size_t j = 0; j < num_channels; ++j) {
136 double buffer_sample = 0.0;
137 if (!buffer_data[j].empty() && i < buffer_data[j].size()) {
138 buffer_sample = buffer_data[j][i];
139 }
140
141 double sample = m_handle->nodes.process_sample(j) + buffer_sample;
142
143 for (const auto& network_buffer : all_network_outputs[j]) {
144 if (i < network_buffer.size()) {
145 sample += network_buffer[i];
146 }
147 }
148
149 size_t index = i * num_channels + j;
150 output_span[index] = std::clamp(sample, -1., 1.);
151 }
152 }
153
156
157 if (m_snapshot_copy.size() != total_samples)
158 m_snapshot_copy.resize(total_samples);
159
160 std::memcpy(m_snapshot_copy.data(), output_buffer, total_samples * sizeof(double));
161 m_snapshot_size.store(static_cast<uint32_t>(total_samples), std::memory_order_release);
162 m_snapshot_ptr.store(m_snapshot_copy.data(), std::memory_order_release);
163 m_snapshot_generation.fetch_add(1, std::memory_order_release);
164 m_snapshot_generation.notify_all();
165
166 m_callback_active.fetch_sub(1, std::memory_order_release);
167 return has_underrun ? 1 : 0;
168
169 } catch (const std::exception& e) {
171 "Exception during audio output processing: {}", e.what());
172
173 if (output_buffer) {
174 auto total_samples = static_cast<uint32_t>(num_frames * m_stream_info.output.channels);
175 std::memset(output_buffer, 0, total_samples * sizeof(double));
176 }
177
178 m_callback_active.fetch_sub(1, std::memory_order_release);
179 return 1;
180 }
181}
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
std::atomic< uint64_t > m_snapshot_generation
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::atomic< uint32_t > m_snapshot_size
std::atomic< const double * > m_snapshot_ptr
std::vector< double > m_snapshot_copy
Owned copy of the last output cycle; decouples notification-thread reads from the callback write buff...
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_snapshot_copy, m_snapshot_generation, m_snapshot_ptr, m_snapshot_size, 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: