Zrythm v2.0.0-alpha.1+31.4967fd053471
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
clip_playback_data_provider.h
1// SPDX-FileCopyrightText: © 2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <atomic>
7
8#include "dsp/graph_node.h"
9#include "dsp/midi_event_buffer.h"
10#include "structure/tracks/track_fwd.h"
11
12#include <farbot/RealtimeObject.hpp>
13#include <juce_audio_basics/juce_audio_basics.h>
14
15namespace zrythm::structure::tracks
16{
17
21class ClipPlaybackDataProvider final
22{
23 struct MidiCache
24 {
25 MidiCache (
26 std::vector<dsp::SampleBasedMidiEvent> &&midi_events,
27 structure::tracks::ClipQuantizeOption quantize_opt,
28 units::precise_tick_t end_position)
29 : midi_events_ (std::move (midi_events)), quantize_opt_ (quantize_opt),
30 end_position_ (end_position)
31 {
32 }
33 std::vector<dsp::SampleBasedMidiEvent> midi_events_;
34 structure::tracks::ClipQuantizeOption quantize_opt_;
35
39 units::precise_tick_t end_position_;
40 };
41
42 struct AudioCache
43 {
44 AudioCache (
45 juce::AudioSampleBuffer audio_buffer,
46 structure::tracks::ClipQuantizeOption quantize_opt,
47 units::precise_tick_t end_position)
48 : audio_buffer_ (std::move (audio_buffer)),
49 quantize_opt_ (quantize_opt), end_position_ (end_position)
50 {
51 }
52
53 juce::AudioSampleBuffer audio_buffer_;
54 structure::tracks::ClipQuantizeOption quantize_opt_;
55
59 units::precise_tick_t end_position_;
60 };
61
62public:
63 ClipPlaybackDataProvider (const dsp::TempoMap &tempo_map);
64
72 const arrangement::MidiRegion &midi_region,
73 structure::tracks::ClipQuantizeOption quantize_option);
74
81 const arrangement::AudioRegion &audio_region,
82 structure::tracks::ClipQuantizeOption quantize_option);
83
89 void
90 queue_stop_playback (structure::tracks::ClipQuantizeOption quantize_option);
91
92 // TrackEventProvider interface
93 void process_midi_events (
94 const dsp::graph::ProcessBlockInfo &time_nfo,
95 dsp::MidiEventBuffer &output_buffer) noexcept [[clang::nonblocking]];
96
101 const dsp::graph::ProcessBlockInfo &time_nfo,
102 std::span<float> left_buffer,
103 std::span<float> right_buffer) noexcept [[clang::nonblocking]];
104
108 auto playing () const { return playing_.load (); }
109
110 auto current_playback_position_in_clip () const
111 {
112 return internal_clip_buffer_position_.load ();
113 }
114
115private:
120 void update_playback_position (
121 const dsp::graph::ProcessBlockInfo &time_nfo,
122 units::sample_t clip_loop_end_samples);
123
127 std::pair<units::sample_t, units::sample_t> handle_quantization_and_start (
128 const dsp::graph::ProcessBlockInfo &time_nfo,
129 units::sample_t clip_loop_end_samples,
130 structure::tracks::ClipQuantizeOption quantize_opt);
131
135 template <typename ProcessFunc>
136 void process_chunks_with_looping (
137 units::sample_t internal_buffer_start_offset,
138 units::sample_t samples_to_process,
139 units::sample_t clip_loop_end_samples,
140 units::sample_t output_buffer_timestamp_offset,
141 ProcessFunc process_chunk);
142
148 void clear_active_buffers ();
149
150private:
152 farbot::RealtimeObject<
153 std::optional<MidiCache>,
154 farbot::RealtimeObjectOptions::nonRealtimeMutatable>
155 active_midi_playback_sequence_;
156
158 farbot::RealtimeObject<
159 std::optional<AudioCache>,
160 farbot::RealtimeObjectOptions::nonRealtimeMutatable>
161 active_audio_playback_buffer_;
162
163 const dsp::TempoMap &tempo_map_;
164
173 std::atomic<bool> playing_{ false };
174
182 bool was_playing_{ false };
183
190 std::atomic<units::sample_t> internal_clip_buffer_position_;
191
198 std::atomic<units::sample_t> last_seen_timeline_position_;
199
206 std::atomic<units::sample_t> clip_launch_timeline_position_;
207
208 static_assert (decltype (internal_clip_buffer_position_)::is_always_lock_free);
209 static_assert (decltype (last_seen_timeline_position_)::is_always_lock_free);
210 static_assert (decltype (clip_launch_timeline_position_)::is_always_lock_free);
211};
212
213}
Packed contiguous buffer for RT MIDI events.
A region for playing back audio samples.
A Region containing MIDI events.
Definition midi_region.h:24
void queue_stop_playback(structure::tracks::ClipQuantizeOption quantize_option)
Requests that playback is stopped at the next quantization point.
auto playing() const
Whether currently playing any part of the clip.
void generate_audio_events(const arrangement::AudioRegion &audio_region, structure::tracks::ClipQuantizeOption quantize_option)
Generate the audio buffer to be used during realtime processing.
void process_audio_events(const dsp::graph::ProcessBlockInfo &time_nfo, std::span< float > left_buffer, std::span< float > right_buffer) noexcept
Process audio events for clip launcher playback.
void generate_midi_events(const arrangement::MidiRegion &midi_region, structure::tracks::ClipQuantizeOption quantize_option)
Generate the MIDI event sequence to be used during realtime processing.
Common struct to pass around during processing to avoid repeating the data in function arguments.
Definition graph_node.h:51