Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
|
The audio engine. More...
#include <src/engine/device_io/engine.h>
Data Structures | |
struct | PositionInfo |
struct | State |
Public Types | |
enum class | SampleRate : basic_enum_base_type_t { SR_22050 , SR_32000 , SR_44100 , SR_48000 , SR_88200 , SR_96000 , SR_192000 } |
Samplerates to be used in comboboxes. More... | |
enum class | BufferSize : basic_enum_base_type_t { _16 , _32 , _64 , _128 , _256 , _512 , _1024 , _2048 , _4096 } |
Buffer sizes to be used in combo boxes. More... | |
using | BeatsPerBarGetter = std::function<int ()> |
using | BpmGetter = std::function<bpm_t ()> |
![]() | |
using | TrackUuid = dsp::PortIdentifier::TrackUuid |
using | PluginUuid = dsp::PortIdentifier::PluginUuid |
using | PortUuid = dsp::PortIdentifier::PortUuid |
Public Member Functions | |
AudioEngine (Project *project=nullptr, std::shared_ptr< juce::AudioDeviceManager > device_mgr=std::make_shared< juce::AudioDeviceManager >()) | |
Create a new audio engine. | |
~AudioEngine () override | |
Closes any connections and free's data. | |
auto & | get_port_registry () |
auto & | get_port_registry () const |
structure::tracks::TrackRegistry & | get_track_registry () |
structure::tracks::TrackRegistry & | get_track_registry () const |
void | set_port_metadata_from_owner (dsp::PortIdentifier &id, PortRange &range) const override |
Function that will be called by the Port to update the identifier's relevant members based on this port owner. | |
utils::Utf8String | get_full_designation_for_port (const dsp::PortIdentifier &id) const override |
void | wait_for_pause (State &state, bool force_pause, bool with_fadeout) |
void | realloc_port_buffers (nframes_t buf_size) |
void | init_loaded (Project *project) |
void | resume (State &state) |
void | wait_n_cycles (int n) |
Waits for n processing cycles to finish. | |
void | append_ports (std::vector< Port * > &ports) |
void | setup (BeatsPerBarGetter beats_per_bar_getter, BpmGetter bpm_getter) |
Sets up the audio engine after the project is initialized/loaded. | |
void | activate (bool activate) |
Activates the audio engine to start processing and receiving events. | |
void | update_frames_per_tick (int beats_per_bar, bpm_t bpm, sample_rate_t sample_rate, bool thread_check, bool update_from_ticks, bool bpm_change) |
Updates frames per tick based on the time sig, the BPM, and the sample rate. | |
bool | process_prepare (nframes_t nframes, SemaphoreRAII< moodycamel::LightweightSemaphore > *sem=nullptr) |
To be called by each implementation to prepare the structures before processing. | |
int | process (nframes_t total_frames_to_process) |
Processes current cycle. | |
void | post_process (nframes_t roll_nframes, nframes_t nframes) |
To be called after processing for common logic. | |
void | reset_bounce_mode () |
Reset the bounce mode on the engine, all tracks and regions to OFF. | |
std::pair< AudioPort &, AudioPort & > | get_monitor_out_ports () |
std::pair< AudioPort &, AudioPort & > | get_dummy_input_ports () |
void | panic_all () |
Queues MIDI note off to event queues. | |
void | clear_output_buffers (nframes_t nframes) |
Clears the underlying backend's output buffers. | |
auto | get_device_manager () const |
nframes_t | get_block_length () const |
sample_rate_t | get_sample_rate () const |
![]() | |
virtual void | on_control_change_event (const PortUuid &port_uuid, const dsp::PortIdentifier &id, float val) |
Will be called when a control port's value changes. | |
virtual void | on_midi_activity (const dsp::PortIdentifier &id) |
Called during processing if the MIDI port contains new MIDI events. | |
virtual bool | should_sum_data_from_backend () const |
Whether during processing, the port should sum the data from its backend buffers coming in. | |
virtual bool | should_bounce_to_master (utils::audio::BounceStep step) const |
Whether the port should add its data to the master output when bouncing. | |
virtual bool | are_events_on_midi_channel_approved (midi_byte_t channel) const |
Returns whether MIDI events on this channel on an input port should be processed (not ignored). | |
Static Public Member Functions | |
static AudioEngine * | get_active_instance () |
Data Fields | |
Project * | project_ = nullptr |
Pointer to owner project, if any. | |
std::shared_ptr< juce::AudioDeviceManager > | device_manager_ |
std::atomic_uint64_t | cycle_ = 0 |
Cycle count to know which cycle we are in. | |
dsp::FramesPerTick | frames_per_tick_ |
Number of frames/samples per tick. | |
dsp::TicksPerFrame | ticks_per_frame_ |
Reciprocal of frames_per_tick_. | |
bool | buf_size_set_ {} |
True iff buffer size callback fired. | |
std::unique_ptr< session::Router > | router_ |
The processing graph router. | |
std::unique_ptr< MidiPort > | midi_clock_in_ |
MIDI Clock input TODO. | |
std::unique_ptr< MidiPort > | midi_clock_out_ |
MIDI Clock output. | |
std::unique_ptr< session::ControlRoom > | control_room_ |
The ControlRoom. | |
std::unique_ptr< AudioPool > | pool_ |
Audio file pool. | |
std::optional< PortUuidReference > | dummy_left_input_ |
Used during tests to pass input data for recording. | |
std::optional< PortUuidReference > | dummy_right_input_ |
std::optional< PortUuidReference > | monitor_out_left_ |
Monitor - these should be the last ports in the signal chain. | |
std::optional< PortUuidReference > | monitor_out_right_ |
std::atomic_bool | trigger_midi_activity_ { false } |
Flag to tell the UI that this channel had MIDI activity. | |
std::unique_ptr< MidiPort > | midi_editor_manual_press_ |
Manual note press events from the piano roll. | |
std::unique_ptr< MidiPort > | midi_in_ |
Port used for receiving MIDI in messages for binding CC and other non-recording purposes. | |
nframes_t | nframes_ = 0 |
Number of frames/samples in the current cycle, per channel. | |
moodycamel::LightweightSemaphore | port_operation_lock_ { 1 } |
Semaphore for blocking DSP while a plugin and its ports are deleted. | |
std::atomic_bool | run_ { false } |
Ok to process or not. | |
bool | preparing_to_export_ = false |
To be set to true when preparing to export. | |
std::atomic_bool | exporting_ { false } |
Whether currently exporting. | |
std::atomic_bool | panic_ { false } |
Send note off MIDI everywhere. | |
dsp::PanLaw | pan_law_ = {} |
Pan law. | |
dsp::PanAlgorithm | pan_algo_ = {} |
Pan algorithm. | |
RtDuration | max_time_taken_ {} |
Time taken to process in the last cycle. | |
RtTimePoint | timestamp_start_ {} |
Timestamp at the start of the current cycle. | |
RtTimePoint | last_timestamp_start_ {} |
Expected timestamp at the end of the current cycle. | |
nframes_t | remaining_latency_preroll_ = 0 |
Timestamp at end of previous cycle. | |
QPointer< dsp::PortConnectionsManager > | port_connections_manager_ |
std::unique_ptr< session::SampleProcessor > | sample_processor_ |
std::atomic_bool | capture_cc_ { false } |
To be set to 1 when the CC from the Midi in port should be captured. | |
std::array< midi_byte_t, 3 > | last_cc_captured_ {} |
Last MIDI CC captured. | |
bool | denormal_prevention_val_positive_ = true |
Whether the denormal prevention value (1e-12 ~ 1e-20) is positive. | |
float | denormal_prevention_val_ = 1e-12f |
BounceMode | bounce_mode_ = BounceMode::Off |
If this is on, only tracks/regions marked as "for bounce" will be allowed to make sound. | |
utils::audio::BounceStep | bounce_step_ = {} |
Bounce step cache. | |
bool | bounce_with_parents_ = false |
Whether currently bouncing with parents (cache). | |
std::unique_ptr< session::Metronome > | metronome_ |
The metronome. | |
std::atomic_bool | cycle_running_ { false } |
Whether the cycle is currently running. | |
bool | setup_ = false |
Whether the engine is already set up. | |
bool | activated_ = false |
Whether the engine is currently activated. | |
bool | destroying_ = false |
Whether the engine is currently undergoing destruction. | |
bool | updating_frames_per_tick_ = false |
True while updating frames per tick. | |
PositionInfo | pos_nfo_before_ = {} |
Position info at the end of the previous cycle before moving the transport. | |
PositionInfo | pos_nfo_current_ = {} |
Position info at the start of the current cycle. | |
PositionInfo | pos_nfo_at_end_ = {} |
Expected position info at the end of the current cycle. | |
std::unique_ptr< AudioCallback > | audio_callback_ |
Friends | |
void | init_from (AudioEngine &obj, const AudioEngine &other, utils::ObjectCloneType clone_type) |
void | to_json (nlohmann::json &j, const AudioEngine &engine) |
void | from_json (const nlohmann::json &j, AudioEngine &engine) |
using zrythm::engine::device_io::AudioEngine::BeatsPerBarGetter = std::function<int ()> |
using zrythm::engine::device_io::AudioEngine::BpmGetter = std::function<bpm_t ()> |
|
strong |
|
strong |
zrythm::engine::device_io::AudioEngine::AudioEngine | ( | Project * | project = nullptr, |
std::shared_ptr< juce::AudioDeviceManager > | device_mgr = std::make_shared< juce::AudioDeviceManager >() ) |
Create a new audio engine.
This only initializes the engine and does not connect to any backend.
void zrythm::engine::device_io::AudioEngine::activate | ( | bool | activate | ) |
Activates the audio engine to start processing and receiving events.
activate | Activate or deactivate. |
void zrythm::engine::device_io::AudioEngine::clear_output_buffers | ( | nframes_t | nframes | ) |
Clears the underlying backend's output buffers.
Used when returning early.
|
inline |
|
inline |
|
overridevirtual |
Reimplemented from IPortOwner.
|
inline |
|
inline |
|
inline |
void zrythm::engine::device_io::AudioEngine::init_loaded | ( | Project * | project | ) |
project |
ZrythmError | if failed to initialize. |
void zrythm::engine::device_io::AudioEngine::panic_all | ( | ) |
Queues MIDI note off to event queues.
void zrythm::engine::device_io::AudioEngine::post_process | ( | nframes_t | roll_nframes, |
nframes_t | nframes ) |
To be called after processing for common logic.
roll_nframes | Frames to roll (add to the playhead - if transport rolling). |
nframes | Total frames for this processing cycle. |
int zrythm::engine::device_io::AudioEngine::process | ( | nframes_t | total_frames_to_process | ) |
Processes current cycle.
To be called by each implementation in its callback.
bool zrythm::engine::device_io::AudioEngine::process_prepare | ( | nframes_t | nframes, |
SemaphoreRAII< moodycamel::LightweightSemaphore > * | sem = nullptr ) |
To be called by each implementation to prepare the structures before processing.
Clears buffers, marks all as unprocessed, etc.
sem | SemamphoreRAII to check if acquired. If not acquired before calling this function, it will only clear output buffers and return true. |
|
overridevirtual |
Function that will be called by the Port to update the identifier's relevant members based on this port owner.
id | The identifier to update. |
Implements IPortOwner.
void zrythm::engine::device_io::AudioEngine::setup | ( | BeatsPerBarGetter | beats_per_bar_getter, |
BpmGetter | bpm_getter ) |
Sets up the audio engine after the project is initialized/loaded.
This also calls update_frames_per_tick() which requires the project to be initialized/loaded.
void zrythm::engine::device_io::AudioEngine::update_frames_per_tick | ( | int | beats_per_bar, |
bpm_t | bpm, | ||
sample_rate_t | sample_rate, | ||
bool | thread_check, | ||
bool | update_from_ticks, | ||
bool | bpm_change ) |
Updates frames per tick based on the time sig, the BPM, and the sample rate.
thread_check | Whether to throw a warning if not called from GTK thread. |
update_from_ticks | Whether to update the positions based on ticks (true) or frames (false). |
bpm_change | Whether this is a BPM change. |
void zrythm::engine::device_io::AudioEngine::wait_for_pause | ( | State & | state, |
bool | force_pause, | ||
bool | with_fadeout ) |
force_pause | Whether to force transport pause, otherwise for engine to process and handle the pause request. |
void zrythm::engine::device_io::AudioEngine::wait_n_cycles | ( | int | n | ) |
Waits for n processing cycles to finish.
Used during tests.
|
friend |
bool zrythm::engine::device_io::AudioEngine::activated_ = false |
std::unique_ptr<AudioCallback> zrythm::engine::device_io::AudioEngine::audio_callback_ |
BounceMode zrythm::engine::device_io::AudioEngine::bounce_mode_ = BounceMode::Off |
utils::audio::BounceStep zrythm::engine::device_io::AudioEngine::bounce_step_ = {} |
bool zrythm::engine::device_io::AudioEngine::bounce_with_parents_ = false |
bool zrythm::engine::device_io::AudioEngine::buf_size_set_ {} |
std::atomic_bool zrythm::engine::device_io::AudioEngine::capture_cc_ { false } |
std::unique_ptr<session::ControlRoom> zrythm::engine::device_io::AudioEngine::control_room_ |
std::atomic_uint64_t zrythm::engine::device_io::AudioEngine::cycle_ = 0 |
std::atomic_bool zrythm::engine::device_io::AudioEngine::cycle_running_ { false } |
float zrythm::engine::device_io::AudioEngine::denormal_prevention_val_ = 1e-12f |
bool zrythm::engine::device_io::AudioEngine::denormal_prevention_val_positive_ = true |
Whether the denormal prevention value (1e-12 ~ 1e-20) is positive.
This should be swapped often to avoid DC offset prevention algorithms removing it.
See https://www.earlevel.com/main/2019/04/19/floating-point-denormals/ for details.
bool zrythm::engine::device_io::AudioEngine::destroying_ = false |
std::shared_ptr<juce::AudioDeviceManager> zrythm::engine::device_io::AudioEngine::device_manager_ |
std::optional<PortUuidReference> zrythm::engine::device_io::AudioEngine::dummy_left_input_ |
std::optional<PortUuidReference> zrythm::engine::device_io::AudioEngine::dummy_right_input_ |
std::atomic_bool zrythm::engine::device_io::AudioEngine::exporting_ { false } |
dsp::FramesPerTick zrythm::engine::device_io::AudioEngine::frames_per_tick_ |
std::array<midi_byte_t, 3> zrythm::engine::device_io::AudioEngine::last_cc_captured_ {} |
RtTimePoint zrythm::engine::device_io::AudioEngine::last_timestamp_start_ {} |
RtDuration zrythm::engine::device_io::AudioEngine::max_time_taken_ {} |
Time taken to process in the last cycle.
Max time taken in the last few processing cycles.
This is used by the DSP usage meter, which also clears the value to 0 upon reading it.
std::unique_ptr<session::Metronome> zrythm::engine::device_io::AudioEngine::metronome_ |
std::unique_ptr<MidiPort> zrythm::engine::device_io::AudioEngine::midi_clock_in_ |
std::unique_ptr<MidiPort> zrythm::engine::device_io::AudioEngine::midi_clock_out_ |
std::unique_ptr<MidiPort> zrythm::engine::device_io::AudioEngine::midi_editor_manual_press_ |
Manual note press events from the piano roll.
The events from here should be read by the corresponding track processor's MIDI in port (TrackProcessor.midi_in). To avoid having to recalculate the graph to reattach this port to the correct track processor, only connect this port to the initial processor in the routing graph and fetch the events manually when processing the corresponding track processor.
std::unique_ptr<MidiPort> zrythm::engine::device_io::AudioEngine::midi_in_ |
std::optional<PortUuidReference> zrythm::engine::device_io::AudioEngine::monitor_out_left_ |
std::optional<PortUuidReference> zrythm::engine::device_io::AudioEngine::monitor_out_right_ |
nframes_t zrythm::engine::device_io::AudioEngine::nframes_ = 0 |
dsp::PanAlgorithm zrythm::engine::device_io::AudioEngine::pan_algo_ = {} |
dsp::PanLaw zrythm::engine::device_io::AudioEngine::pan_law_ = {} |
std::atomic_bool zrythm::engine::device_io::AudioEngine::panic_ { false } |
std::unique_ptr<AudioPool> zrythm::engine::device_io::AudioEngine::pool_ |
QPointer<dsp::PortConnectionsManager> zrythm::engine::device_io::AudioEngine::port_connections_manager_ |
moodycamel::LightweightSemaphore zrythm::engine::device_io::AudioEngine::port_operation_lock_ { 1 } |
PositionInfo zrythm::engine::device_io::AudioEngine::pos_nfo_at_end_ = {} |
PositionInfo zrythm::engine::device_io::AudioEngine::pos_nfo_before_ = {} |
PositionInfo zrythm::engine::device_io::AudioEngine::pos_nfo_current_ = {} |
bool zrythm::engine::device_io::AudioEngine::preparing_to_export_ = false |
Project* zrythm::engine::device_io::AudioEngine::project_ = nullptr |
nframes_t zrythm::engine::device_io::AudioEngine::remaining_latency_preroll_ = 0 |
std::unique_ptr<session::Router> zrythm::engine::device_io::AudioEngine::router_ |
std::atomic_bool zrythm::engine::device_io::AudioEngine::run_ { false } |
std::unique_ptr<session::SampleProcessor> zrythm::engine::device_io::AudioEngine::sample_processor_ |
bool zrythm::engine::device_io::AudioEngine::setup_ = false |
dsp::TicksPerFrame zrythm::engine::device_io::AudioEngine::ticks_per_frame_ |
Reciprocal of frames_per_tick_.
RtTimePoint zrythm::engine::device_io::AudioEngine::timestamp_start_ {} |
std::atomic_bool zrythm::engine::device_io::AudioEngine::trigger_midi_activity_ { false } |
bool zrythm::engine::device_io::AudioEngine::updating_frames_per_tick_ = false |