react-native-audio-api 0.11.0-nightly-6ba0571-20251210 → 0.11.0-nightly-c0ffb48-20251211

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,9 +10,7 @@
10
10
  #include <audioapi/libs/miniaudio/decoders/libvorbis/miniaudio_libvorbis.h>
11
11
  #include <audioapi/libs/miniaudio/miniaudio.h>
12
12
 
13
- #ifndef AUDIO_API_TEST_SUITE
14
13
  #include <android/log.h>
15
- #endif // AUDIO_API_TEST_SUITE
16
14
  #if !RN_AUDIO_API_FFMPEG_DISABLED
17
15
  #include <audioapi/libs/ffmpeg/FFmpegDecoding.h>
18
16
  #endif // RN_AUDIO_API_FFMPEG_DISABLED
@@ -31,7 +29,6 @@ std::vector<float> AudioDecoder::readAllPcmFrames(ma_decoder &decoder, int outpu
31
29
  std::vector<float> temp(CHUNK_SIZE * outputChannels);
32
30
  ma_uint64 outFramesRead = 0;
33
31
 
34
- #ifndef AUDIO_API_TEST_SUITE
35
32
  while (true) {
36
33
  ma_uint64 tempFramesDecoded = 0;
37
34
  ma_decoder_read_pcm_frames(&decoder, temp.data(), CHUNK_SIZE, &tempFramesDecoded);
@@ -46,8 +43,6 @@ std::vector<float> AudioDecoder::readAllPcmFrames(ma_decoder &decoder, int outpu
46
43
  if (outFramesRead == 0) {
47
44
  __android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
48
45
  }
49
- #endif
50
- return buffer;
51
46
  }
52
47
 
53
48
  std::shared_ptr<AudioBuffer> AudioDecoder::makeAudioBufferFromFloatBuffer(
@@ -73,7 +68,6 @@ std::shared_ptr<AudioBuffer> AudioDecoder::makeAudioBufferFromFloatBuffer(
73
68
  std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithFilePath(
74
69
  const std::string &path,
75
70
  float sampleRate) {
76
- #ifndef AUDIO_API_TEST_SUITE
77
71
  if (AudioDecoder::pathHasExtension(path, {".mp4", ".m4a", ".aac"})) {
78
72
  #if !RN_AUDIO_API_FFMPEG_DISABLED
79
73
  auto buffer = ffmpegdecoder::decodeWithFilePath(path, static_cast<int>(sampleRate));
@@ -116,14 +110,10 @@ std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithFilePath(
116
110
  std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
117
111
  ma_decoder_uninit(&decoder);
118
112
  return makeAudioBufferFromFloatBuffer(buffer, outputSampleRate, outputChannels);
119
- #else
120
- return nullptr;
121
- #endif
122
113
  }
123
114
 
124
115
  std::shared_ptr<AudioBuffer>
125
116
  AudioDecoder::decodeWithMemoryBlock(const void *data, size_t size, float sampleRate) {
126
- #ifndef AUDIO_API_TEST_SUITE
127
117
  const AudioFormat format = AudioDecoder::detectAudioFormat(data, size);
128
118
  if (format == AudioFormat::MP4 || format == AudioFormat::M4A || format == AudioFormat::AAC) {
129
119
  #if !RN_AUDIO_API_FFMPEG_DISABLED
@@ -161,9 +151,6 @@ AudioDecoder::decodeWithMemoryBlock(const void *data, size_t size, float sampleR
161
151
  std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
162
152
  ma_decoder_uninit(&decoder);
163
153
  return makeAudioBufferFromFloatBuffer(buffer, outputSampleRate, outputChannels);
164
- #else
165
- return nullptr;
166
- #endif
167
154
  }
168
155
 
169
156
  std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithPCMInBase64(
@@ -103,7 +103,7 @@ void BiquadFilterNode::getFrequencyResponse(
103
103
  float *magResponseOutput,
104
104
  float *phaseResponseOutput,
105
105
  const size_t length) {
106
- #ifndef AUDIO_API_TEST_SUITE
106
+ #if !RN_AUDIO_API_TEST
107
107
  applyFilter();
108
108
  #endif
109
109
 
@@ -31,9 +31,9 @@
31
31
  #include <audioapi/core/AudioNode.h>
32
32
  #include <audioapi/core/AudioParam.h>
33
33
  #include <audioapi/core/types/BiquadFilterType.h>
34
- #ifdef AUDIO_API_TEST_SUITE
34
+ #if RN_AUDIO_API_TEST
35
35
  #include <gtest/gtest_prod.h>
36
- #endif
36
+ #endif // RN_AUDIO_API_TEST
37
37
 
38
38
  #include <algorithm>
39
39
  #include <cmath>
@@ -48,10 +48,10 @@ namespace audioapi {
48
48
  class AudioBus;
49
49
 
50
50
  class BiquadFilterNode : public AudioNode {
51
- #ifdef AUDIO_API_TEST_SUITE
51
+ #if RN_AUDIO_API_TEST
52
52
  friend class BiquadFilterTest;
53
53
  FRIEND_TEST(BiquadFilterTest, GetFrequencyResponse);
54
- #endif
54
+ #endif // RN_AUDIO_API_TEST
55
55
 
56
56
  public:
57
57
  explicit BiquadFilterNode(BaseAudioContext *context);
@@ -8,7 +8,7 @@
8
8
 
9
9
  #if !RN_AUDIO_API_TEST
10
10
  #include <audioapi/core/AudioContext.h>
11
- #endif
11
+ #endif // RN_AUDIO_API_TEST
12
12
 
13
13
  #include <algorithm>
14
14
  #include <limits>
@@ -30,7 +30,7 @@ void AudioScheduledSourceNode::start(double when) {
30
30
  if (auto context = dynamic_cast<AudioContext *>(context_)) {
31
31
  context->start();
32
32
  }
33
- #endif
33
+ #endif // RN_AUDIO_API_TEST
34
34
 
35
35
  playbackState_ = PlaybackState::SCHEDULED;
36
36
  startTime_ = when;
@@ -294,6 +294,7 @@ bool StreamerNode::setupDecoder() {
294
294
 
295
295
  void StreamerNode::cleanup() {
296
296
  this->playbackState_ = PlaybackState::FINISHED;
297
+ isNodeFinished_.store(true, std::memory_order_release);
297
298
  if (streamingThread_.joinable()) {
298
299
  StreamingData dummy;
299
300
  while (receiver_.try_receive(dummy) == channels::spsc::ResponseStatus::SUCCESS)
@@ -24,19 +24,17 @@ extern "C" {
24
24
  }
25
25
  #endif // RN_AUDIO_API_FFMPEG_DISABLED
26
26
 
27
+ #include <audioapi/utils/SpscChannel.hpp>
27
28
  #include <atomic>
28
29
  #include <cmath>
29
30
  #include <memory>
30
31
  #include <string>
31
32
  #include <utility>
32
- #ifndef AUDIO_API_TEST_SUITE
33
- #include <audioapi/utils/SpscChannel.hpp>
34
33
 
35
34
  static constexpr audioapi::channels::spsc::OverflowStrategy STREAMER_NODE_SPSC_OVERFLOW_STRATEGY =
36
35
  audioapi::channels::spsc::OverflowStrategy::WAIT_ON_FULL;
37
36
  static constexpr audioapi::channels::spsc::WaitStrategy STREAMER_NODE_SPSC_WAIT_STRATEGY =
38
37
  audioapi::channels::spsc::WaitStrategy::ATOMIC_WAIT;
39
- #endif // AUDIO_API_TEST_SUITE
40
38
 
41
39
  static constexpr bool VERBOSE = false;
42
40
  static constexpr int CHANNEL_CAPACITY = 32;
@@ -2,49 +2,52 @@
2
2
  #include <cstddef>
3
3
  #include <new>
4
4
 
5
- template<typename T, std::size_t Align = 16>
5
+ template <typename T, std::size_t Align = 16>
6
6
  class AlignedAllocator {
7
- public:
7
+ public:
8
8
  using value_type = T;
9
9
  using size_type = std::size_t;
10
10
  using difference_type = std::ptrdiff_t;
11
11
 
12
12
  AlignedAllocator() noexcept = default;
13
- template<class U> AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept {}
13
+ template <class U>
14
+ AlignedAllocator(const AlignedAllocator<U, Align> &) noexcept {}
14
15
 
15
- T* allocate(std::size_t n) {
16
+ T *allocate(std::size_t n) {
16
17
  // We want to maximize performance on hot paths, so we hint unlikely branches
17
- if (n == 0) [[ unlikely ]] {
18
+ if (n == 0) [[unlikely]] {
18
19
  return nullptr;
19
20
  }
20
21
  std::size_t bytes = n * sizeof(T);
21
22
  // C++17 aligned new
22
- void* p = ::operator new(bytes, std::align_val_t(Align));
23
+ void *p = ::operator new(bytes, std::align_val_t(Align));
23
24
 
24
25
  // We have more serious problems if this happens than speed concerns
25
26
  // so we can opt the branch prediction
26
- if (!p) [[ unlikely ]] {
27
+ if (!p) [[unlikely]] {
27
28
  throw std::bad_alloc();
28
29
  }
29
- return static_cast<T*>(p);
30
+ return static_cast<T *>(p);
30
31
  }
31
32
 
32
- void deallocate(T* p, std::size_t) noexcept {
33
- ::operator delete(p, std::align_val_t(Align));
33
+ void deallocate(T *p, std::size_t) noexcept {
34
+ ::operator delete(p, std::align_val_t(Align));
34
35
  }
35
36
 
36
37
  // Rebind allocator to type U (required by std::vector)
37
- template<class U>
38
- struct rebind { using other = AlignedAllocator<U, Align>; };
38
+ template <class U>
39
+ struct rebind {
40
+ using other = AlignedAllocator<U, Align>;
41
+ };
39
42
 
40
43
  // Comparison operators (required by std::vector)
41
- template<typename U, std::size_t UAlign>
42
- bool operator==(const AlignedAllocator<U, UAlign>&) const noexcept {
44
+ template <typename U, std::size_t UAlign>
45
+ bool operator==(const AlignedAllocator<U, UAlign> &) const noexcept {
43
46
  return Align == UAlign;
44
47
  }
45
48
 
46
- template<typename U, std::size_t UAlign>
47
- bool operator!=(const AlignedAllocator<U, UAlign>&) const noexcept {
49
+ template <typename U, std::size_t UAlign>
50
+ bool operator!=(const AlignedAllocator<U, UAlign> &) const noexcept {
48
51
  return Align != UAlign;
49
52
  }
50
53
  };
@@ -1,8 +1,11 @@
1
1
  #pragma once
2
2
 
3
- /// Benchmarking utilities
3
+ // Benchmarking utilities
4
4
  #include <chrono>
5
+ #include <cstdio>
6
+ #include <string>
5
7
  #include <unordered_map>
8
+ #include <utility>
6
9
 
7
10
  #ifdef ANDROID
8
11
  #include <android/log.h>
@@ -10,49 +13,49 @@
10
13
 
11
14
  namespace audioapi::benchmarks {
12
15
 
13
- /// @brief Gets the execution time of a function
14
- /// @tparam Func The type of the function to benchmark
15
- /// @param func The function to benchmark
16
- /// @return The duration of the function execution in nanoseconds
17
- /// @note This function is safe to use across threads
18
- template <typename Func>
19
- double getExecutionTime(Func&& func) {
20
- auto start = std::chrono::high_resolution_clock::now();
21
- std::forward<Func>(func)();
22
- auto end = std::chrono::high_resolution_clock::now();
23
- return std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
24
- }
25
-
26
- /// @brief Logs the average execution time of a function
27
- /// @tparam Func The type of the function to benchmark
28
- /// @param msg The message to log
29
- /// @param func The function to benchmark
30
- /// @return The duration of the function execution in nanoseconds
31
- /// @note This function should not be used in production
32
- /// @note This function is not thread-safe and should be used preferably once in a codebase when you need to measure performance
33
- template <typename Func>
34
- double logAvgExecutionTime(const std::string& msg, Func&& func) {
35
- double duration = getExecutionTime(std::forward<Func>(func));
36
-
37
- static std::unordered_map<std::string, double> durationsSum;
38
- static std::unordered_map<std::string, int> durationsCount;
39
-
40
- // Ensure initialization for first time
41
- if (durationsSum.find(msg) == durationsSum.end()) {
42
- durationsSum[msg] = 0.0;
43
- durationsCount[msg] = 0;
44
- }
45
-
46
- durationsSum[msg] += duration;
47
- durationsCount[msg]++;
48
-
49
- long long avgDuration = static_cast<long long>(durationsSum[msg] / durationsCount[msg]);
50
-
51
- #ifdef ANDROID
52
- __android_log_print(ANDROID_LOG_INFO, "AudioAPI", "%s: %lld ns", msg.c_str(), avgDuration);
53
- #else
54
- printf("%s: %lld ns\n", msg.c_str(), avgDuration);
55
- #endif
56
- return duration;
57
- }
58
- }
16
+ /// @brief Gets the execution time of a function
17
+ /// @tparam Func The type of the function to benchmark
18
+ /// @param func The function to benchmark
19
+ /// @return The duration of the function execution in nanoseconds
20
+ /// @note This function is safe to use across threads
21
+ template <typename Func>
22
+ double getExecutionTime(Func &&func) {
23
+ auto start = std::chrono::high_resolution_clock::now();
24
+ std::forward<Func>(func)();
25
+ auto end = std::chrono::high_resolution_clock::now();
26
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
27
+ }
28
+
29
+ /// @brief Logs the average execution time of a function
30
+ /// @tparam Func The type of the function to benchmark
31
+ /// @param msg The message to log
32
+ /// @param func The function to benchmark
33
+ /// @return The duration of the function execution in nanoseconds
34
+ /// @note This function should not be used in production
35
+ /// @note This function is not thread-safe and should be used preferably once in a codebase when you need to measure performance
36
+ template <typename Func>
37
+ double logAvgExecutionTime(const std::string &msg, Func &&func) {
38
+ double duration = getExecutionTime(std::forward<Func>(func));
39
+
40
+ static std::unordered_map<std::string, double> durationsSum;
41
+ static std::unordered_map<std::string, int> durationsCount;
42
+
43
+ // Ensure initialization for first time
44
+ if (durationsSum.find(msg) == durationsSum.end()) {
45
+ durationsSum[msg] = 0.0;
46
+ durationsCount[msg] = 0;
47
+ }
48
+
49
+ durationsSum[msg] += duration;
50
+ durationsCount[msg]++;
51
+
52
+ int64_t avgDuration = static_cast<int64_t>(durationsSum[msg] / durationsCount[msg]);
53
+
54
+ #ifdef ANDROID
55
+ __android_log_print(ANDROID_LOG_INFO, "AudioAPI", "%s: %lld ns", msg.c_str(), avgDuration);
56
+ #else
57
+ printf("%s: %lld ns\n", msg.c_str(), avgDuration);
58
+ #endif
59
+ return duration;
60
+ }
61
+ } // namespace audioapi::benchmarks
@@ -2,8 +2,9 @@
2
2
 
3
3
  #include <audioapi/utils/SpscChannel.hpp>
4
4
 
5
- #include <type_traits>
6
5
  #include <functional>
6
+ #include <type_traits>
7
+ #include <utility>
7
8
 
8
9
  namespace audioapi {
9
10
  using namespace channels::spsc;
@@ -27,32 +28,34 @@ template <typename T>
27
28
  class CrossThreadEventScheduler {
28
29
  public:
29
30
  explicit CrossThreadEventScheduler(size_t capacity) {
30
- auto [sender, receiver] = channel<std::function<void(T&)>>(capacity);
31
+ auto [sender, receiver] = channel<std::function<void(T &)>>(capacity);
31
32
  eventSender_ = std::move(sender);
32
33
  eventReceiver_ = std::move(receiver);
33
34
  }
34
- CrossThreadEventScheduler(const CrossThreadEventScheduler&) = delete;
35
- CrossThreadEventScheduler& operator=(const CrossThreadEventScheduler&) = delete;
35
+ CrossThreadEventScheduler(const CrossThreadEventScheduler &) = delete;
36
+ CrossThreadEventScheduler &operator=(const CrossThreadEventScheduler &) = delete;
36
37
 
37
38
  /// @brief Schedules an event to be processed on the audio thread.
38
39
  /// @param event The event to schedule.
39
40
  /// @return True if the event was successfully scheduled, false if the queue is full.
40
- bool scheduleEvent(std::function<void(T&)> &&event) noexcept(noexcept(eventSender_.try_send(std::move(event)))) {
41
+ bool scheduleEvent(std::function<void(T &)> &&event) noexcept(
42
+ noexcept(eventSender_.try_send(std::move(event)))) {
41
43
  return eventSender_.try_send(std::move(event)) == ResponseStatus::SUCCESS;
42
44
  }
43
45
 
44
46
  /// @brief Processes all scheduled events.
45
47
  /// @param data The data to pass to each event.
46
- void processAllEvents(T& data) noexcept(noexcept(eventReceiver_.try_receive(std::declval<std::function<void(T&)>&>()))) {
47
- std::function<void(T&)> event;
48
+ void processAllEvents(T &data) noexcept(
49
+ noexcept(eventReceiver_.try_receive(std::declval<std::function<void(T &)> &>()))) {
50
+ std::function<void(T &)> event;
48
51
  while (eventReceiver_.try_receive(event) == ResponseStatus::SUCCESS) {
49
52
  event(data);
50
53
  }
51
54
  }
52
55
 
53
56
  private:
54
- Sender<std::function<void(T&)>> eventSender_;
55
- Receiver<std::function<void(T&)>> eventReceiver_;
57
+ Sender<std::function<void(T &)>> eventSender_;
58
+ Receiver<std::function<void(T &)>> eventReceiver_;
56
59
  };
57
60
 
58
61
  } // namespace audioapi
@@ -1,12 +1,14 @@
1
1
  #pragma once
2
2
  #include <functional>
3
+ #include <memory>
4
+ #include <utility>
3
5
 
4
6
  namespace audioapi {
5
7
 
6
8
  /// @brief A forward declaration of a move-only function wrapper.
7
9
  /// @note it is somehow required to have <R(Args...)> specialization below
8
10
  /// @tparam Signature
9
- template<typename Signature>
11
+ template <typename Signature>
10
12
  class move_only_function; // Forward declaration
11
13
 
12
14
  /// @brief A move-only function wrapper similar to std::function but non-copyable.
@@ -18,7 +20,7 @@ class move_only_function; // Forward declaration
18
20
  /// @note IMPORTANT: This thing is implemented in C++23 standard and can be replaced with std::move_only_function once we switch to C++23.
19
21
  /// @tparam R
20
22
  /// @tparam ...Args
21
- template<typename R, typename... Args>
23
+ template <typename R, typename... Args>
22
24
  class move_only_function<R(Args...)> {
23
25
  /// @brief The base class for type erasure.
24
26
  /// @note It gets optimized by Empty Base Optimization (EBO) when possible.
@@ -29,7 +31,7 @@ class move_only_function<R(Args...)> {
29
31
 
30
32
  /// @brief The implementation of the callable object.
31
33
  /// @tparam F
32
- template<typename F>
34
+ template <typename F>
33
35
  struct callable_impl : callable_base {
34
36
  /// @brief The stored callable object.
35
37
  F f;
@@ -38,8 +40,8 @@ class move_only_function<R(Args...)> {
38
40
  /// @tparam G
39
41
  /// @param func
40
42
  /// @note The enable_if_t ensures that F can be constructed from G&&.
41
- template<typename G, typename = std::enable_if_t<std::is_constructible_v<F, G&&>>>
42
- callable_impl(G&& func) : f(std::forward<G>(func)) {}
43
+ template <typename G, typename = std::enable_if_t<std::is_constructible_v<F, G &&>>>
44
+ explicit callable_impl(G &&func) : f(std::forward<G>(func)) {}
43
45
 
44
46
  /// @brief Invoke the stored callable object with the given arguments.
45
47
  /// @param args
@@ -58,19 +60,19 @@ class move_only_function<R(Args...)> {
58
60
  /// @brief The unique pointer to the base callable type.
59
61
  std::unique_ptr<callable_base> impl_;
60
62
 
61
- public:
63
+ public:
62
64
  move_only_function() = default;
63
65
  move_only_function(std::nullptr_t) noexcept : impl_(nullptr) {}
64
66
 
65
- template<typename F>
66
- move_only_function(F&& f)
67
- : impl_(std::make_unique<callable_impl<std::decay_t<F>>>(std::forward<F>(f))) {}
67
+ template <typename F>
68
+ move_only_function(F &&f)
69
+ : impl_(std::make_unique<callable_impl<std::decay_t<F>>>(std::forward<F>(f))) {}
68
70
 
69
- move_only_function(const move_only_function&) = delete;
70
- move_only_function& operator=(const move_only_function&) = delete;
71
+ move_only_function(const move_only_function &) = delete;
72
+ move_only_function &operator=(const move_only_function &) = delete;
71
73
 
72
- move_only_function(move_only_function&&) = default;
73
- move_only_function& operator=(move_only_function&&) = default;
74
+ move_only_function(move_only_function &&) = default;
75
+ move_only_function &operator=(move_only_function &&) = default;
74
76
 
75
77
  inline explicit operator bool() const noexcept {
76
78
  return impl_ != nullptr;
@@ -78,13 +80,13 @@ public:
78
80
 
79
81
  inline R operator()(Args... args) {
80
82
  /// We are unlikely to hit this case as we want to optimize for the common case.
81
- if (impl_ == nullptr) [[ unlikely ]] {
83
+ if (impl_ == nullptr) [[unlikely]] {
82
84
  throw std::bad_function_call{};
83
85
  }
84
86
  return (*impl_)(std::forward<Args>(args)...);
85
87
  }
86
88
 
87
- void swap(move_only_function& other) noexcept {
89
+ void swap(move_only_function &other) noexcept {
88
90
  impl_.swap(other.impl_);
89
91
  }
90
92
  };
@@ -3,6 +3,7 @@
3
3
  #include <bit>
4
4
  #include <memory>
5
5
  #include <type_traits>
6
+ #include <utility>
6
7
 
7
8
  namespace audioapi {
8
9
 
@@ -16,15 +17,10 @@ template <typename T, size_t capacity_>
16
17
  class RingBiDirectionalBuffer {
17
18
  public:
18
19
  /// @brief Constructor for RingBuffer.
19
- RingBiDirectionalBuffer()
20
- : headIndex_(0), tailIndex_(0) {
20
+ RingBiDirectionalBuffer() : headIndex_(0), tailIndex_(0) {
21
21
  static_assert(isPowerOfTwo(capacity_), "RingBiDirectionalBuffer's capacity must be power of 2");
22
- buffer_ = static_cast<T*>(
23
- ::operator new[](
24
- capacity_ * sizeof(T),
25
- static_cast<std::align_val_t>(alignof(T))
26
- )
27
- );
22
+ buffer_ = static_cast<T *>(
23
+ ::operator new[](capacity_ * sizeof(T), static_cast<std::align_val_t>(alignof(T))));
28
24
  }
29
25
 
30
26
  /// @brief Destructor for RingBuffer.
@@ -32,11 +28,7 @@ class RingBiDirectionalBuffer {
32
28
  for (int i = headIndex_; i != tailIndex_; i = nextIndex(i)) {
33
29
  buffer_[i].~T();
34
30
  }
35
- ::operator delete[](
36
- buffer_,
37
- capacity_ * sizeof(T),
38
- static_cast<std::align_val_t>(alignof(T))
39
- );
31
+ ::operator delete[](buffer_, capacity_ * sizeof(T), static_cast<std::align_val_t>(alignof(T)));
40
32
  }
41
33
 
42
34
  /// @brief Push a value into the ring buffer.
@@ -44,8 +36,8 @@ class RingBiDirectionalBuffer {
44
36
  /// @param value The value to push.
45
37
  /// @return True if the value was pushed successfully, false if the buffer is full.
46
38
  template <typename U>
47
- bool pushBack(U&& value) noexcept(std::is_nothrow_constructible_v<T, U&&>) {
48
- if (isFull()) [[ unlikely ]] {
39
+ bool pushBack(U &&value) noexcept(std::is_nothrow_constructible_v<T, U &&>) {
40
+ if (isFull()) [[unlikely]] {
49
41
  return false;
50
42
  }
51
43
  new (&buffer_[tailIndex_]) T(std::forward<U>(value));
@@ -58,8 +50,8 @@ class RingBiDirectionalBuffer {
58
50
  /// @param value The value to push.
59
51
  /// @return True if the value was pushed successfully, false if the buffer is full.
60
52
  template <typename U>
61
- bool pushFront(U&& value) noexcept(std::is_nothrow_constructible_v<T, U&&>) {
62
- if (isFull()) [[ unlikely ]] {
53
+ bool pushFront(U &&value) noexcept(std::is_nothrow_constructible_v<T, U &&>) {
54
+ if (isFull()) [[unlikely]] {
63
55
  return false;
64
56
  }
65
57
  headIndex_ = prevIndex(headIndex_);
@@ -70,8 +62,9 @@ class RingBiDirectionalBuffer {
70
62
  /// @brief Pop a value from the front of the buffer.
71
63
  /// @param out The value popped from the buffer.
72
64
  /// @return True if the value was popped successfully, false if the buffer is empty.
73
- bool popFront(T& out) noexcept(std::is_nothrow_move_constructible_v<T> && std::is_nothrow_destructible_v<T>) {
74
- if (isEmpty()) [[ unlikely ]] {
65
+ bool popFront(T &out) noexcept(
66
+ std::is_nothrow_move_constructible_v<T> && std::is_nothrow_destructible_v<T>) {
67
+ if (isEmpty()) [[unlikely]] {
75
68
  return false;
76
69
  }
77
70
  out = std::move(buffer_[headIndex_]);
@@ -83,7 +76,7 @@ class RingBiDirectionalBuffer {
83
76
  /// @brief Pop a value from the front of the buffer.
84
77
  /// @return True if the value was popped successfully, false if the buffer is empty.
85
78
  bool popFront() noexcept(std::is_nothrow_destructible_v<T>) {
86
- if (isEmpty()) [[ unlikely ]] {
79
+ if (isEmpty()) [[unlikely]] {
87
80
  return false;
88
81
  }
89
82
  buffer_[headIndex_].~T();
@@ -94,8 +87,9 @@ class RingBiDirectionalBuffer {
94
87
  /// @brief Pop a value from the back of the buffer.
95
88
  /// @param out The value popped from the buffer.
96
89
  /// @return True if the value was popped successfully, false if the buffer is empty.
97
- bool popBack(T& out) noexcept(std::is_nothrow_move_constructible_v<T> && std::is_nothrow_destructible_v<T>) {
98
- if (isEmpty()) [[ unlikely ]] {
90
+ bool popBack(T &out) noexcept(
91
+ std::is_nothrow_move_constructible_v<T> && std::is_nothrow_destructible_v<T>) {
92
+ if (isEmpty()) [[unlikely]] {
99
93
  return false;
100
94
  }
101
95
  tailIndex_ = prevIndex(tailIndex_);
@@ -107,7 +101,7 @@ class RingBiDirectionalBuffer {
107
101
  /// @brief Pop a value from the back of the buffer.
108
102
  /// @return True if the value was popped successfully, false if the buffer is empty.
109
103
  bool popBack() noexcept(std::is_nothrow_destructible_v<T>) {
110
- if (isEmpty()) [[ unlikely ]] {
104
+ if (isEmpty()) [[unlikely]] {
111
105
  return false;
112
106
  }
113
107
  tailIndex_ = prevIndex(tailIndex_);
@@ -117,25 +111,25 @@ class RingBiDirectionalBuffer {
117
111
 
118
112
  /// @brief Peek at the front of the buffer.
119
113
  /// @return A const reference to the front element of the buffer.
120
- const inline T& peekFront() const noexcept {
114
+ const inline T &peekFront() const noexcept {
121
115
  return buffer_[headIndex_];
122
116
  }
123
117
 
124
118
  /// @brief Peek at the back of the buffer.
125
119
  /// @return A const reference to the back element of the buffer.
126
- const inline T& peekBack() const noexcept {
120
+ const inline T &peekBack() const noexcept {
127
121
  return buffer_[prevIndex(tailIndex_)];
128
122
  }
129
123
 
130
124
  /// @brief Peek at the front of the buffer.
131
125
  /// @return A mutable reference to the front element of the buffer.
132
- inline T& peekFrontMut() noexcept {
126
+ inline T &peekFrontMut() noexcept {
133
127
  return buffer_[headIndex_];
134
128
  }
135
129
 
136
130
  /// @brief Peek at the back of the buffer.
137
131
  /// @return A mutable reference to the back element of the buffer.
138
- inline T& peekBackMut() noexcept {
132
+ inline T &peekBackMut() noexcept {
139
133
  return buffer_[prevIndex(tailIndex_)];
140
134
  }
141
135
 
@@ -196,4 +190,4 @@ class RingBiDirectionalBuffer {
196
190
  }
197
191
  };
198
192
 
199
- };
193
+ }; // namespace audioapi