Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
recording_session.h
1// SPDX-FileCopyrightText: © 2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <atomic>
7#include <concepts>
8#include <memory>
9#include <vector>
10
11#include "controllers/recording_audio_packet.h"
12#include "controllers/recording_midi_packet.h"
13#include "utils/units.h"
14
15#include <QtClassHelperMacros>
16
17namespace zrythm::controllers
18{
19
20template <typename T>
22 requires (T &slot, const T &source, units::sample_u32_t block_length) {
23 { T::copy_from (slot, source) };
24 { T::resize (slot, block_length) };
25 };
26
43template <RecordingPacket Packet> class RecordingSession
44{
45public:
46 enum class State : uint8_t
47 {
48 Armed,
49 Capturing,
50 Finalizing,
51 };
52
53 explicit RecordingSession (units::sample_u32_t max_block_length);
54 ~RecordingSession ();
55
56 Q_DISABLE_COPY_MOVE (RecordingSession)
57
58 static constexpr size_t kFifoCapacity = 1024;
59
60 using PacketType = Packet;
61
68 void prepare_for_processing (units::sample_u32_t block_length);
69
76 void write (
77 units::sample_t timeline_position,
78 bool transport_recording,
79 std::span<const float> l_data,
80 std::span<const float> r_data) noexcept [[clang::nonblocking]]
81 requires std::same_as<Packet, RecordingAudioPacket>;
82
89 void write (
90 units::sample_t timeline_position,
91 bool transport_recording,
92 std::span<const dsp::MidiEvent> midi_events,
93 units::sample_u32_t nframes) noexcept [[clang::nonblocking]]
94 requires std::same_as<Packet, RecordingMidiPacket>;
95
102 [[nodiscard]] std::vector<Packet> drain_pending () [[clang::blocking]];
103
104 [[nodiscard]] auto state () const
105 {
106 return state_.load (std::memory_order_acquire);
107 }
108
112 void finalize () noexcept [[clang::nonblocking]];
113
117 void reset ();
118
119 [[nodiscard]] uint64_t dropped_packets () const
120 {
121 return dropped_packets_.load (std::memory_order_relaxed);
122 }
123
124private:
125 struct Impl;
126 std::unique_ptr<Impl> impl_;
127
128 std::atomic<State> state_{ State::Armed };
129 std::atomic<uint64_t> dropped_packets_{ 0 };
130};
131
132using AudioRecordingSession = RecordingSession<RecordingAudioPacket>;
133using MidiRecordingSession = RecordingSession<RecordingMidiPacket>;
134
135}
Per-track recording state with a lock-free SPSC queue.
std::vector< Packet > drain_pending()
Non-RT: drains all pending packets from the ring buffer.
void write(units::sample_t timeline_position, bool transport_recording, std::span< const float > l_data, std::span< const float > r_data) noexcept
RT-safe: writes audio data into the ring buffer.
void prepare_for_processing(units::sample_u32_t block_length)
Prepares internal buffers for processing at the given block length.
void finalize() noexcept
Transitions to Finalizing state, rejecting further writes.
void write(units::sample_t timeline_position, bool transport_recording, std::span< const dsp::MidiEvent > midi_events, units::sample_u32_t nframes) noexcept
RT-safe: writes MIDI events into the ring buffer.