24 Q_PROPERTY (
int sampleRate READ sampleRate NOTIFY sampleRateChanged)
29 enum class State : std::uint8_t
44 std::shared_ptr<juce::AudioDeviceManager> device_mgr,
46 QObject * parent =
nullptr);
57 Q_INVOKABLE
int xRunCount ()
const {
return load_measurer_.getXRunCount (); }
58 Q_INVOKABLE
double loadPercentage ()
const
60 return load_measurer_.getLoadAsPercentage ();
63 int sampleRate ()
const {
return get_sample_rate ().in (units::sample_rate); }
65 Q_SIGNAL
void sampleRateChanged (
int sampleRate);
95 [[clang::nonblocking]];
97 enum class ProcessReturnStatus : std::uint8_t
114 nframes_t total_frames_to_process)
noexcept [[clang::nonblocking]]
115 -> ProcessReturnStatus;
128 nframes_t nframes)
noexcept [[clang::nonblocking]];
130 auto &get_monitor_out_port () {
return monitor_out_; }
132 auto * midi_panic_processor ()
const {
return midi_panic_processor_.get (); }
139 auto get_device_manager ()
const {
return device_manager_; }
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_; }
146 bool exporting ()
const {
return exporting_; }
147 void set_exporting (
bool exporting) { exporting_.store (exporting); }
149 auto get_processing_lock () [[clang::blocking]]
151 return SemaphoreRAII (process_lock_,
true);
156 auto * dev = device_manager_->getCurrentAudioDevice ();
157 assert (dev !=
nullptr);
158 return dev->getCurrentBufferSizeSamples ();
161 units::sample_rate_t get_sample_rate ()
const
163 auto * dev = device_manager_->getCurrentAudioDevice ();
164 assert (dev !=
nullptr);
165 return units::sample_rate (
static_cast<int> (dev->getCurrentSampleRate ()));
176 const std::function<
void ()> &func,
177 bool recalculate_graph);
185 void activate_impl (
bool activate);
188 dsp::PortRegistry port_registry_;
196 std::shared_ptr<juce::AudioDeviceManager> device_manager_;
203 std::atomic_uint64_t cycle_{ 0 };
225 std::unique_ptr<dsp::MidiPort> midi_in_;
230 moodycamel::LightweightSemaphore process_lock_{ 1 };
233 std::atomic_bool run_{
false };
236 std::atomic_bool exporting_{
false };
238 juce::AudioProcessLoadMeasurer load_measurer_;
247 std::atomic_bool capture_cc_{
false };
250 std::array<midi_byte_t, 3> last_cc_captured_{};
252 std::atomic<State> state_{ State::Uninitialized };
253 static_assert (
decltype (state_)::is_always_lock_free);
255 utils::QObjectUniquePtr<dsp::MidiPanicProcessor> midi_panic_processor_;
257 std::unique_ptr<AudioCallback> audio_callback_;
263 bool callback_running_{};
AudioEngine(dsp::Transport &transport, std::shared_ptr< juce::AudioDeviceManager > device_mgr, dsp::DspGraphDispatcher &graph_dispatcher, QObject *parent=nullptr)
Create a new audio engine.
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.
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.