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 units::sample_u32_t block_length = units::samples (256))
28 : sample_rate_ (sample_rate), block_length_ (block_length)
29 {
30 }
31
32 ~ThreadedMockHardwareAudioInterface () override { stop (); }
33
34 [[nodiscard]] units::sample_u32_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 block_length_.in (units::samples) *num_channels, 0.f);
72 std::vector<float> input_buf (
73 block_length_.in (units::samples) *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 ()
80 + (static_cast<size_t> (ch) * block_length_.in (units::samples));
81 input_ptrs[ch] =
82 input_buf.data ()
83 + (static_cast<size_t> (ch) * block_length_.in (units::samples));
84 }
85
86 while (
87 !stoken.stop_requested ()
88 && is_running_.load (std::memory_order_acquire))
89 {
90 auto * cb = callback_.load (std::memory_order_acquire);
91 if (cb)
92 {
93 cb->process_audio (
94 input_ptrs.data (), num_channels, output_ptrs.data (),
95 num_channels, block_length_.in<int> (units::samples));
96 process_call_count_.fetch_add (1, std::memory_order_acq_rel);
97 }
98 auto sleep_us = static_cast<int64_t> (
99 block_length_.in<double> (units::samples) * 1'000'000.0
100 / sample_rate_.in (units::sample_rate));
101 std::this_thread::sleep_for (std::chrono::microseconds (sleep_us));
102 }
103 });
104 }
105 }
106
108 {
109 stop ();
110 auto * cb = callback_.load (std::memory_order_acquire);
111 if (cb != nullptr)
112 {
113 cb->stopped ();
114 }
115 callback_.store (nullptr, std::memory_order_release);
116 }
117
118private:
119 void stop ()
120 {
121 is_running_.store (false, std::memory_order_release);
122 if (callback_thread_.joinable ())
123 {
124 callback_thread_.request_stop ();
125 callback_thread_.join ();
126 }
127 }
128
129 units::sample_rate_t sample_rate_;
130 units::sample_u32_t block_length_;
131 std::atomic<dsp::IAudioCallback *> callback_{ nullptr };
132 std::atomic<bool> is_running_{ false };
133 std::atomic<std::size_t> process_call_count_{ 0 };
134 std::jthread callback_thread_;
135};
136
137} // 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.
units::sample_u32_t get_block_length() const override
Returns the current block length (buffer size) in frames.
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.