Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
graph_node.h
1// SPDX-FileCopyrightText: © 2019-2021, 2024-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3/*
4 * This file incorporates work covered by the following copyright and
5 * permission notice:
6 *
7 * ---
8 *
9 * Copyright (C) 2017, 2019 Robin Gareus <robin@gareus.org>
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 *
24 * SPDX-License-Identifier: GPL-2.0-or-later
25 *
26 * ---
27 */
28
29#pragma once
30
31#include "dsp/itransport.h"
32#include "dsp/tempo_map.h"
33#include "utils/units.h"
34
35#include <QObject>
36
37namespace zrythm::utils
38{
39class Utf8String;
40}
41
42namespace zrythm::dsp::graph
43{
44class GraphNode;
45
51{
52public:
53 void print () const;
54
55 static constexpr ProcessBlockInfo from_position_and_nframes (
56 units::sample_u64_t transport_position,
57 units::sample_u32_t nframes)
58 {
59 return {
60 .transport_position_ = transport_position,
61 .buffer_offset_ = units::samples (0),
62 .nframes_ = nframes
63 };
64 }
65
66 [[gnu::hot]] constexpr units::sample_u64_t end_position () const noexcept
67 {
69 }
70
71public:
74 units::sample_u64_t transport_position_;
75
78 units::sample_u32_t buffer_offset_;
79
83 units::sample_u32_t nframes_;
84};
85
99{
100public:
101 virtual ~IProcessable () { release_resources (); }
102
106 virtual utils::Utf8String get_node_name () const = 0;
107
112 [[gnu::hot]] virtual units::sample_u32_t get_single_playback_latency () const
113 {
114 return units::samples (0);
115 }
116
126 const GraphNode * node,
127 units::sample_rate_t sample_rate,
128 units::sample_u32_t max_block_length);
129
130protected:
131 virtual void prepare_for_processing_impl (
132 const GraphNode * node,
133 units::sample_rate_t sample_rate,
134 units::sample_u32_t max_block_length)
135 {
136 }
137
138public:
139 [[gnu::hot]] virtual void process_block (
141 const dsp::ITransport &transport,
142 const dsp::TempoMap &tempo_map) noexcept [[clang::nonblocking]] { };
143
150 virtual void release_resources () { }
151};
152
153class InitialProcessor final : public QObject, public IProcessable
154{
155 Q_OBJECT
156
157public:
159};
160
179class GraphNode
180{
181public:
182 using NodeId = int;
183
184 GraphNode (NodeId id, IProcessable &processable);
185 GraphNode (const GraphNode &) = delete;
186 GraphNode &operator= (const GraphNode &) = delete;
187 GraphNode (GraphNode &&) = delete;
188 GraphNode &operator= (GraphNode &&) = delete;
189 ~GraphNode () noexcept = default;
190
192 std::string print_node_to_str () const;
193
194 // For debugging purposes.
195 NodeId get_id () const { return node_id_; }
196
207 [[gnu::hot]] void process (
209 units::sample_u64_t remaining_preroll_frames,
210 const dsp::ITransport &transport,
211 const dsp::TempoMap &tempo_map) const;
212
213 units::sample_u32_t get_single_playback_latency () const
214 {
215 return processable_.get_single_playback_latency ();
216 }
217
225 void set_route_playback_latency (units::sample_u32_t dest_latency);
226
227 void connect_to (GraphNode &target);
228
237 void set_skip_processing (bool skip) { bypass_ = skip; }
238
239 IProcessable &get_processable () { return processable_; }
240 const IProcessable &get_processable () const { return processable_; }
241
245 auto &feeds () const { return childnodes_; }
246
250 auto &depends () const { return parentnodes_; }
251
252 bool remove_feed (const GraphNode &feed);
253 bool remove_depend (const GraphNode &depend);
254
255private:
256 void add_feeds (GraphNode &dest);
257 void add_depends (GraphNode &src);
258
269 [[gnu::hot]] void compensate_latency (
271 units::sample_u32_t remaining_preroll_frames,
272 const dsp::ITransport &transport,
273 const dsp::TempoMap &tempo_map) const;
274
284 [[gnu::hot]] void process_chunks_after_splitting_at_loop_points (
286 const dsp::ITransport &transport,
287 const dsp::TempoMap &tempo_map) const;
288
289public:
291 std::atomic<int> refcount_ = 0;
292
299 units::sample_u32_t playback_latency_;
300
301 // TODO
308 units::sample_u32_t capture_latency_;
309
312
314 units::sample_u32_t route_playback_latency_;
315
316 /* For debugging. These are set by
317 * GraphNodeCollection.set_initial_and_terminal_nodes(). */
318 bool terminal_{ false };
319 bool initial_{ false };
320
321private:
322 NodeId node_id_ = 0;
323
330 std::vector<std::reference_wrapper<GraphNode>> parentnodes_;
331
337 std::vector<std::reference_wrapper<GraphNode>> childnodes_;
338
339 IProcessable &processable_;
340
344 bool bypass_ = false;
345};
346
354{
355public:
361 units::sample_u32_t get_max_route_playback_latency () const;
362
367
372
379
380 GraphNode * find_node_for_processable (const IProcessable &processable) const;
381
382public:
386 std::vector<std::unique_ptr<GraphNode>> graph_nodes_;
387
394 std::vector<std::reference_wrapper<GraphNode>> trigger_nodes_;
395
401 std::vector<std::reference_wrapper<GraphNode>> terminal_nodes_;
402
403 std::unique_ptr<InitialProcessor> initial_processor_;
404};
405
406} // namespace zrythm::dsp::graph
Interface for transport.
Definition itransport.h:47
Manages the collection of graph nodes.
Definition graph_node.h:354
void update_latencies()
Updates the latencies of all nodes.
void set_initial_and_terminal_nodes()
Updates the initial and terminal nodes based on graph_nodes_.
void finalize_nodes()
Sets the initial/terminal nodes.
Definition graph_node.h:378
std::vector< std::reference_wrapper< GraphNode > > trigger_nodes_
A subset of graph_nodes_ that are trigger nodes.
Definition graph_node.h:394
std::vector< std::reference_wrapper< GraphNode > > terminal_nodes_
A subset of graph_nodes_ that are terminal nodes.
Definition graph_node.h:401
units::sample_u32_t get_max_route_playback_latency() const
Returns the max playback latency of the trigger nodes.
std::vector< std::unique_ptr< GraphNode > > graph_nodes_
All nodes in the graph.
Definition graph_node.h:386
Represents a node in a DSP graph.
Definition graph_node.h:180
int init_refcount_
Initial incoming node count.
Definition graph_node.h:311
std::string print_node_to_str() const
For general debugging.
units::sample_u32_t capture_latency_
The capture latency of the node, in samples.
Definition graph_node.h:308
std::atomic< int > refcount_
Incoming node count.
Definition graph_node.h:291
auto & feeds() const
Read-only access to child nodes (outgoing connections).
Definition graph_node.h:245
units::sample_u32_t playback_latency_
The playback latency of the node, in samples.
Definition graph_node.h:299
void set_route_playback_latency(units::sample_u32_t dest_latency)
Sets the playback latency of the given node recursively.
units::sample_u32_t route_playback_latency_
The route's playback latency so far.
Definition graph_node.h:314
auto & depends() const
Read-only access to parent nodes (incoming connections).
Definition graph_node.h:250
void process(dsp::graph::ProcessBlockInfo time_nfo, units::sample_u64_t remaining_preroll_frames, const dsp::ITransport &transport, const dsp::TempoMap &tempo_map) const
Processes the GraphNode.
void set_skip_processing(bool skip)
Sets whether processing should be skipped for this node.
Definition graph_node.h:237
Interface for objects that can be processed in the DSP graph.
Definition graph_node.h:99
virtual utils::Utf8String get_node_name() const =0
Returns a human friendly name of the node.
void prepare_for_processing(const GraphNode *node, units::sample_rate_t sample_rate, units::sample_u32_t max_block_length)
Called to allocate resources required for processing.
virtual void release_resources()
Called to release resources allocated by prepare_for_processing().
Definition graph_node.h:150
virtual units::sample_u32_t get_single_playback_latency() const
Returns the latency of only the given processable, without adding the previous/next latencies (zero l...
Definition graph_node.h:112
utils::Utf8String get_node_name() const override
Returns a human friendly name of the node.
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:37
String utilities.
Common struct to pass around during processing to avoid repeating the data in function arguments.
Definition graph_node.h:51
units::sample_u32_t buffer_offset_
Offset in the current processing cycle's audio buffer, between 0 and the number of frames in AudioEng...
Definition graph_node.h:78
units::sample_u32_t nframes_
Number of frames to process in this call, starting from the offset.
Definition graph_node.h:83
units::sample_u64_t transport_position_
Transport (timeline) position at the start of this chunk (already taking into account the offset).
Definition graph_node.h:74