-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e058323
commit e63d0a7
Showing
2 changed files
with
98 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
#include "CAudio.h" | ||
#include "wsq.hpp" | ||
#include "SynchronizedAudioBufferList.h" | ||
#include "RingBuffer.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Copyright AudioKit. All Rights Reserved. Revision History at http://github.com/AudioKit/AudioKit/ | ||
|
||
#pragma once | ||
|
||
#include <atomic> | ||
#include <cstddef> // size_t | ||
#include <utility> // std::move | ||
|
||
namespace AudioKit { | ||
|
||
template <typename T> class RingBuffer { | ||
|
||
public: | ||
RingBuffer(size_t n = 1024) | ||
: ring_(new T[n]), head_(0), tail_(0), _size(n) {} | ||
|
||
~RingBuffer() { delete[] ring_; } | ||
|
||
bool push(const T &value) { | ||
size_t head = head_.load(std::memory_order_relaxed); | ||
size_t next_head = next(head); | ||
if (next_head == tail_.load(std::memory_order_acquire)) | ||
return false; | ||
ring_[head] = value; | ||
head_.store(next_head, std::memory_order_release); | ||
return true; | ||
} | ||
|
||
bool push(const T *array, size_t n) { | ||
const size_t head = head_.load(std::memory_order_relaxed); | ||
const size_t tail = tail_.load(std::memory_order_acquire); | ||
|
||
const size_t avail = write_available(head, tail); | ||
if (avail < n) { | ||
return false; | ||
} | ||
|
||
for (int i = 0; i < n; ++i) { | ||
ring_[(head + i) % _size] = array[i]; | ||
} | ||
|
||
const size_t next_head = (head + n) % _size; | ||
head_.store(next_head, std::memory_order_release); | ||
return true; | ||
} | ||
|
||
bool pop(T *value) { | ||
size_t tail = tail_.load(std::memory_order_relaxed); | ||
if (tail == head_.load(std::memory_order_acquire)) | ||
return false; | ||
|
||
// Move so the existing value is destroyed. | ||
*value = std::move(ring_[tail]); | ||
|
||
tail_.store(next(tail), std::memory_order_release); | ||
return true; | ||
} | ||
|
||
template <class F> size_t popAll(F f) { | ||
const size_t head = head_.load(std::memory_order_acquire); | ||
const size_t tail = tail_.load(std::memory_order_relaxed); | ||
|
||
const size_t avail = read_available(head, tail); | ||
|
||
for (size_t i = 0; i < avail; ++i) { | ||
f(std::move(ring_[(tail + i) % _size])); | ||
} | ||
|
||
const size_t next_tail = (tail + avail) % _size; | ||
tail_.store(next_tail, std::memory_order_release); | ||
|
||
return avail; | ||
} | ||
|
||
private: | ||
size_t next(size_t current) { return (current + 1) % _size; } | ||
|
||
size_t write_available(size_t head, size_t tail) const { | ||
size_t ret = tail - head - 1; | ||
if (head >= tail) | ||
ret += _size; | ||
return ret; | ||
} | ||
|
||
size_t read_available(size_t head, size_t tail) const { | ||
if (head >= tail) | ||
return head - tail; | ||
|
||
return head + _size - tail; | ||
} | ||
|
||
T *ring_; | ||
std::atomic<size_t> head_, tail_; | ||
size_t _size; | ||
}; | ||
|
||
} // namespace AudioKit |