Zrythm v2.0.0-alpha.1+31.4967fd053471
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
port_observer.h
1// SPDX-FileCopyrightText: © 2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <variant>
7
8#include "dsp/processor_base.h"
9#include "utils/ring_buffer.h"
10
11#include <QObject>
12
13#include "midi_event.h"
14
15namespace zrythm::dsp
16{
17
18class Port;
19class AudioPort;
20class MidiPort;
21class CVPort;
22
23using ObservedPortPtr =
24 std::variant<const AudioPort *, const CVPort *, const MidiPort *>;
25
38class PortObserver : public QObject, public ProcessorBase
39{
40 Q_OBJECT
41 Q_DISABLE_COPY_MOVE (PortObserver)
42public:
43 static constexpr size_t kAudioRingSeconds = 5;
44 static constexpr size_t kMidiRingSize = 8192;
45
46 PortObserver (utils::IObjectRegistry &registry, const Port &observed_port);
47
48 PortUuid observed_port_uuid () const { return observed_port_uuid_; }
49 const Port &observed_port () const;
50
51 int num_channels () const { return static_cast<int> (audio_rings_.size ()); }
52
53 // --- Audio ring buffers (RT writes, drain timer reads) ---
54 RingBuffer<float> &audio_ring (int ch)
55 {
56 assert (ch >= 0 && ch < static_cast<int> (audio_rings_.size ()));
57 assert (audio_rings_[ch] != nullptr);
58 return *audio_rings_[ch];
59 }
60 const RingBuffer<float> &audio_ring (int ch) const
61 {
62 assert (ch >= 0 && ch < static_cast<int> (audio_rings_.size ()));
63 assert (audio_rings_[ch] != nullptr);
64 return *audio_rings_[ch];
65 }
66
67 // --- MIDI ring buffer (RT writes, drain timer reads) ---
69 {
70 assert (midi_ring_ != nullptr);
71 return *midi_ring_;
72 }
73 const RingBuffer<RealtimeMidiEvent> &midi_ring () const
74 {
75 assert (midi_ring_ != nullptr);
76 return *midi_ring_;
77 }
78
79 bool has_audio_rings () const { return !audio_rings_.empty (); }
80 bool has_midi_ring () const { return midi_ring_ != nullptr; }
81
82private:
83 void custom_process_block (
85 const dsp::ITransport &transport,
86 const dsp::TempoMap &tempo_map) noexcept override;
87
88 void custom_prepare_for_processing (
89 const graph::GraphNode * node,
90 units::sample_rate_t sample_rate,
91 units::sample_u32_t max_block_length) override;
92
93 void custom_release_resources () override;
94
95 void process_audio (
96 const AudioPort &port,
97 dsp::graph::ProcessBlockInfo time_nfo) noexcept [[clang::nonblocking]];
98 void
99 process_cv (const CVPort &port, dsp::graph::ProcessBlockInfo time_nfo) noexcept
100 [[clang::nonblocking]];
101 void process_midi (const MidiPort &port) noexcept [[clang::nonblocking]];
102
103 PortUuid observed_port_uuid_;
104 ObservedPortPtr typed_port_;
105
106 std::vector<std::unique_ptr<RingBuffer<float>>> audio_rings_;
107 std::unique_ptr<RingBuffer<RealtimeMidiEvent>> midi_ring_;
108};
109
110}
A ring buffer implementation for storing elements of type T.
Definition ring_buffer.h:39
Control Voltage port.
Definition cv_port.h:21
Interface for transport.
Definition itransport.h:16
A base class for ports used for connecting processors in the DSP graph.
Definition port.h:37
Represents a node in a DSP graph.
Definition graph_node.h:180
Abstract interface for a UUID-keyed object registry.
Common struct to pass around during processing to avoid repeating the data in function arguments.
Definition graph_node.h:51