Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
engine.h
1// SPDX-FileCopyrightText: © 2018-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "dsp/audio_callback.h"
7#include "dsp/audio_port.h"
8#include "dsp/graph_dispatcher.h"
9#include "dsp/hardware_audio_interface.h"
10#include "dsp/midi_panic_processor.h"
11#include "dsp/midi_port.h"
12#include "dsp/transport.h"
13#include "utils/concurrency.h"
14#include "utils/types.h"
15
16namespace zrythm::dsp
17{
18
22class AudioEngine : public QObject
23{
24 Q_OBJECT
25 Q_PROPERTY (int sampleRate READ sampleRate NOTIFY sampleRateChanged)
26 QML_ELEMENT
27 QML_UNCREATABLE ("")
28
29public:
30 enum class State : std::uint8_t
31 {
32 Uninitialized,
33 Initialized,
34 Active,
35 };
36
37public:
44 dsp::Transport &transport,
45 IHardwareAudioInterface &hw_interface,
46 dsp::DspGraphDispatcher &graph_dispatcher,
47 const dsp::TempoMap &tempo_map,
48 QObject * parent = nullptr);
49
53 ~AudioEngine () override;
54
55 // =========================================================
56 // QML interface
57 // =========================================================
58
59 Q_INVOKABLE int xRunCount () const { return load_measurer_.getXRunCount (); }
60 Q_INVOKABLE double loadPercentage () const
61 {
62 return load_measurer_.getLoadAsPercentage ();
63 }
64
65 int sampleRate () const { return get_sample_rate ().in (units::sample_rate); }
66
67 Q_SIGNAL void sampleRateChanged (int sampleRate);
68
69 // =========================================================
70
76 void wait_for_pause (EngineState &state, bool force_pause, bool with_fadeout);
77
78 void resume (const EngineState &state);
79
80 Q_INVOKABLE void activate ();
81 void deactivate ();
82
93 [[gnu::hot]] bool process_prepare (
94 dsp::Transport::TransportSnapshot &transport_snapshot,
95 nframes_t nframes,
97 [[clang::nonblocking]];
98
99 enum class ProcessReturnStatus : std::uint8_t
100 {
101 // Process completed normally
102 ProcessCompleted,
103 // Process skipped (e.g., when recalculating the graph)
104 ProcessSkipped,
105 // Process failed for some reason
106 ProcessFailed,
107 };
108
114 [[gnu::hot]] auto process (
115 const dsp::PlayheadProcessingGuard &playhead_guard,
116 nframes_t total_frames_to_process) noexcept [[clang::nonblocking]]
117 -> ProcessReturnStatus;
118
127 dsp::Transport::TransportSnapshot &transport_snapshot,
128 const dsp::PlayheadProcessingGuard &playhead_guard,
129 nframes_t roll_nframes,
130 nframes_t nframes) noexcept [[clang::nonblocking]];
131
132 auto &get_monitor_out_port () { return monitor_out_; }
133
134 auto * midi_panic_processor () const { return midi_panic_processor_.get (); }
135
139 void panic_all ();
140
141 bool activated () const { return state_ == State::Active; }
142 bool running () const { return run_.load (); }
143 void set_running (bool run) { run_.store (run); }
144 auto &graph_dispatcher () { return graph_dispatcher_; }
145
146 bool exporting () const { return exporting_; }
147 void set_exporting (bool exporting) { exporting_.store (exporting); }
148
149 auto get_processing_lock () [[clang::blocking]]
150 {
151 return SemaphoreRAII (process_lock_, true);
152 }
153
154 nframes_t get_block_length () const
155 {
156 return hw_interface_.get_block_length ();
157 }
158
159 units::sample_rate_t get_sample_rate () const
160 {
161 return hw_interface_.get_sample_rate ();
162 }
163
172 const std::function<void ()> &func,
173 bool recalculate_graph);
174
175private:
181 void activate_impl (bool activate);
182
183private:
184 dsp::PortRegistry port_registry_;
185 dsp::ProcessorParameterRegistry param_registry_{ port_registry_ };
186
187 dsp::Transport &transport_;
188
190 const dsp::TempoMap &tempo_map_;
191
193 dsp::DspGraphDispatcher &graph_dispatcher_;
194
195 IHardwareAudioInterface &hw_interface_;
196
202 std::atomic_uint64_t cycle_{ 0 };
203
216 dsp::AudioPort monitor_out_;
217
224 std::unique_ptr<dsp::MidiPort> midi_in_;
225
229 moodycamel::LightweightSemaphore process_lock_{ 1 };
230
232 std::atomic_bool run_{ false };
233
235 std::atomic_bool exporting_{ false };
236
237 juce::AudioProcessLoadMeasurer load_measurer_;
238
243 nframes_t remaining_latency_preroll_{};
244
246 std::atomic_bool capture_cc_{ false };
247
249 std::array<midi_byte_t, 3> last_cc_captured_{};
250
251 std::atomic<State> state_{ State::Uninitialized };
252 static_assert (decltype (state_)::is_always_lock_free);
253
254 utils::QObjectUniquePtr<dsp::MidiPanicProcessor> midi_panic_processor_;
255
256 std::unique_ptr<AudioCallback> audio_callback_;
257
262 bool callback_running_{};
263};
264}
RAII wrapper class for std::binary_semaphore.
Definition concurrency.h:62
~AudioEngine() override
Closes any connections and free's data.
void advance_playhead_after_processing(dsp::Transport::TransportSnapshot &transport_snapshot, const dsp::PlayheadProcessingGuard &playhead_guard, nframes_t roll_nframes, nframes_t nframes) noexcept
Advances the playhead if transport is rolling.
void execute_function_with_paused_processing_synchronously(const std::function< void()> &func, bool recalculate_graph)
Executes the given function after pausing processing and then resumes processing.
auto process(const dsp::PlayheadProcessingGuard &playhead_guard, nframes_t total_frames_to_process) noexcept -> ProcessReturnStatus
Processes current cycle.
void wait_for_pause(EngineState &state, bool force_pause, bool with_fadeout)
bool process_prepare(dsp::Transport::TransportSnapshot &transport_snapshot, nframes_t nframes, SemaphoreRAII< moodycamel::LightweightSemaphore > &sem) noexcept
To be called by each implementation to prepare the structures before processing.
AudioEngine(dsp::Transport &transport, IHardwareAudioInterface &hw_interface, dsp::DspGraphDispatcher &graph_dispatcher, const dsp::TempoMap &tempo_map, QObject *parent=nullptr)
Create a new audio engine.
void panic_all()
Queues MIDI note off to event queues.
Audio port specifics.
Definition audio_port.h:25
The DspGraphDispatcher class manages the processing graph for the audio engine.
Abstraction for hardware audio interface.
RAII helper for Playhead audio processing block.
Definition playhead.h:236
Wrapper over a Uuid registry that provides (slow) lookup by unique ID.
Definition parameter.h:505
The Transport class represents the transport controls and state for an audio engine.
Definition transport.h:45
uint32_t nframes_t
Frame count.
Definition types.h:58