Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
mock_hardware_audio_interface_threaded.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 <thread>
8
9#include "dsp/hardware_audio_interface.h"
10#include "dsp/iaudio_callback.h"
11#include "utils/units.h"
12
13namespace zrythm::test_helpers
14{
15
22class ThreadedMockHardwareAudioInterface : public dsp::IHardwareAudioInterface
23{
24public:
25 explicit ThreadedMockHardwareAudioInterface (
26 units::sample_rate_t sample_rate = units::sample_rate (48000),
27 nframes_t block_length = 256)
28 : sample_rate_ (sample_rate), block_length_ (block_length)
29 {
30 }
31
32 ~ThreadedMockHardwareAudioInterface () override { stop (); }
33
34 [[nodiscard]] nframes_t get_block_length () const override
35 {
36 return block_length_;
37 }
38 [[nodiscard]] units::sample_rate_t get_sample_rate () const override
39 {
40 return sample_rate_;
41 }
42
49 [[nodiscard]] std::size_t process_call_count () const
50 {
51 return process_call_count_.load (std::memory_order_acquire);
52 }
53
54 void add_audio_callback (dsp::IAudioCallback * callback) override
55 {
56 stop ();
57 auto * old_cb = callback_.load (std::memory_order_acquire);
58 if (old_cb != nullptr)
59 {
60 old_cb->stopped ();
61 }
62 if (callback != nullptr)
63 {
64 callback_.store (callback, std::memory_order_release);
65 callback->about_to_start ();
66
67 is_running_.store (true, std::memory_order_release);
68 callback_thread_ = std::jthread ([this] (std::stop_token stoken) {
69 constexpr int num_channels = 2;
70 std::vector<float> output_buf (
71 static_cast<size_t> (block_length_) * num_channels, 0.f);
72 std::vector<float> input_buf (
73 static_cast<size_t> (block_length_) * num_channels, 0.f);
74 std::vector<float *> output_ptrs (num_channels);
75 std::vector<const float *> input_ptrs (num_channels);
76 for (int ch = 0; ch < num_channels; ++ch)
77 {
78 output_ptrs[ch] =
79 output_buf.data () + static_cast<size_t> (ch) * block_length_;
80 input_ptrs[ch] =
81 input_buf.data () + static_cast<size_t> (ch) * block_length_;
82 }
83
84 while (
85 !stoken.stop_requested ()
86 && is_running_.load (std::memory_order_acquire))
87 {
88 auto * cb = callback_.load (std::memory_order_acquire);
89 if (cb)
90 {
91 cb->process_audio (
92 input_ptrs.data (), num_channels, output_ptrs.data (),
93 num_channels, static_cast<int> (block_length_));
94 process_call_count_.fetch_add (1, std::memory_order_acq_rel);
95 }
96 auto sleep_us = static_cast<int64_t> (
97 static_cast<double> (block_length_) * 1'000'000.0
98 / sample_rate_.in (units::sample_rate));
99 std::this_thread::sleep_for (std::chrono::microseconds (sleep_us));
100 }
101 });
102 }
103 }
104
106 {
107 stop ();
108 auto * cb = callback_.load (std::memory_order_acquire);
109 if (cb != nullptr)
110 {
111 cb->stopped ();
112 }
113 callback_.store (nullptr, std::memory_order_release);
114 }
115
116private:
117 void stop ()
118 {
119 is_running_.store (false, std::memory_order_release);
120 if (callback_thread_.joinable ())
121 {
122 callback_thread_.request_stop ();
123 callback_thread_.join ();
124 }
125 }
126
127 units::sample_rate_t sample_rate_;
128 nframes_t block_length_;
129 std::atomic<dsp::IAudioCallback *> callback_{ nullptr };
130 std::atomic<bool> is_running_{ false };
131 std::atomic<std::size_t> process_call_count_{ 0 };
132 std::jthread callback_thread_;
133};
134
135} // namespace zrythm::test_helpers
Pure-abstract audio callback interface.
virtual void about_to_start()=0
Called when the audio device is about to start processing.
Abstraction for hardware audio interface.
void remove_audio_callback(dsp::IAudioCallback *callback) override
Removes a previously added audio callback.
void add_audio_callback(dsp::IAudioCallback *callback) override
Adds an audio callback to receive audio I/O events.
std::size_t process_call_count() const
Returns the number of times process_audio has been called.
units::sample_rate_t get_sample_rate() const override
Returns the current sample rate.
nframes_t get_block_length() const override
Returns the current block length (buffer size) in frames.
uint32_t nframes_t
Frame count.
Definition types.h:58