Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
simd_buffer.hpp
Go to the documentation of this file.
1#pragma once
2
3// SIMD-friendly aligned buffer for audio DSP
4// Allocates memory aligned to SIMD register width for optimal vectorized access.
5
6#include <cstddef>
7#include <cstdlib>
8#include <cstring>
9#include <memory>
10#include <algorithm>
11
12#ifdef _MSC_VER
13#include <malloc.h>
14inline void* pulp_aligned_alloc(size_t alignment, size_t size) { return _aligned_malloc(size, alignment); }
15inline void pulp_aligned_free(void* p) { _aligned_free(p); }
16#elif defined(__ANDROID__)
17// Bionic exposes aligned_alloc only from API 28; posix_memalign supports
18// the older API floor and its allocation can be released with free.
19inline void* pulp_aligned_alloc(size_t alignment, size_t size) {
20 void* allocation = nullptr;
21 return posix_memalign(&allocation, alignment, size) == 0 ? allocation : nullptr;
22}
23inline void pulp_aligned_free(void* p) {
24 std::free(p);
25}
26#else
27inline void* pulp_aligned_alloc(size_t alignment, size_t size) { return std::aligned_alloc(alignment, size); }
28inline void pulp_aligned_free(void* p) { std::free(p); }
29#endif
30
31namespace pulp::signal {
32
34static constexpr size_t kSimdAlignment = 64;
35
42template <typename SampleType = float>
44public:
45 AlignedBufferT() = default;
46
47 explicit AlignedBufferT(size_t num_samples)
48 : size_(num_samples) {
49 if (num_samples > 0) {
50 // Round up to alignment boundary
51 size_t bytes = num_samples * sizeof(SampleType);
52 data_ = static_cast<SampleType*>(
53 pulp_aligned_alloc(kSimdAlignment, align_up(bytes)));
54 std::memset(data_, 0, align_up(bytes));
55 }
56 }
57
59
60 // Move only
62 : data_(other.data_), size_(other.size_) {
63 other.data_ = nullptr;
64 other.size_ = 0;
65 }
66
68 if (this != &other) {
69 pulp_aligned_free(data_);
70 data_ = other.data_;
71 size_ = other.size_;
72 other.data_ = nullptr;
73 other.size_ = 0;
74 }
75 return *this;
76 }
77
80
81 SampleType* data() { return data_; }
82 const SampleType* data() const { return data_; }
83 size_t size() const { return size_; }
84 bool empty() const { return size_ == 0; }
85
86 SampleType& operator[](size_t i) { return data_[i]; }
87 const SampleType& operator[](size_t i) const { return data_[i]; }
88
89 SampleType* begin() { return data_; }
90 SampleType* end() { return data_ + size_; }
91 const SampleType* begin() const { return data_; }
92 const SampleType* end() const { return data_ + size_; }
93
95 void clear() {
96 if (data_)
97 std::memset(data_, 0, size_ * sizeof(SampleType));
98 }
99
101 void resize(size_t new_size) {
102 if (new_size == size_) return;
103 pulp_aligned_free(data_);
104 data_ = nullptr;
105 size_ = new_size;
106 if (new_size > 0) {
107 size_t bytes = new_size * sizeof(SampleType);
108 data_ = static_cast<SampleType*>(
109 pulp_aligned_alloc(kSimdAlignment, align_up(bytes)));
110 std::memset(data_, 0, align_up(bytes));
111 }
112 }
113
115 void copy_from(const SampleType* src, size_t count) {
116 count = std::min(count, size_);
117 std::memcpy(data_, src, count * sizeof(SampleType));
118 }
119
120private:
121 static size_t align_up(size_t bytes) {
122 return (bytes + kSimdAlignment - 1) & ~(kSimdAlignment - 1);
123 }
124
125 SampleType* data_ = nullptr;
126 size_t size_ = 0;
127};
128
131
132} // namespace pulp::signal
RAII aligned buffer with SIMD-friendly access.
Definition simd_buffer.hpp:43
void resize(size_t new_size)
Resize (reallocates, does not preserve data).
Definition simd_buffer.hpp:101
AlignedBufferT & operator=(AlignedBufferT &&other) noexcept
Definition simd_buffer.hpp:67
void clear()
Clear buffer to zero.
Definition simd_buffer.hpp:95
~AlignedBufferT()
Definition simd_buffer.hpp:58
SampleType & operator[](size_t i)
Definition simd_buffer.hpp:86
void copy_from(const SampleType *src, size_t count)
Copy from raw pointer.
Definition simd_buffer.hpp:115
AlignedBufferT(size_t num_samples)
Definition simd_buffer.hpp:47
AlignedBufferT(AlignedBufferT &&other) noexcept
Definition simd_buffer.hpp:61
const SampleType * begin() const
Definition simd_buffer.hpp:91
SampleType * end()
Definition simd_buffer.hpp:90
SampleType * begin()
Definition simd_buffer.hpp:89
const SampleType * data() const
Definition simd_buffer.hpp:82
size_t size() const
Definition simd_buffer.hpp:83
SampleType * data()
Definition simd_buffer.hpp:81
bool empty() const
Definition simd_buffer.hpp:84
AlignedBufferT(const AlignedBufferT &)=delete
const SampleType & operator[](size_t i) const
Definition simd_buffer.hpp:87
AlignedBufferT & operator=(const AlignedBufferT &)=delete
const SampleType * end() const
Definition simd_buffer.hpp:92
Definition additive_bank.hpp:218
static constexpr size_t kSimdAlignment
Alignment in bytes for SIMD operations (covers AVX-512).
Definition simd_buffer.hpp:34
AlignedBufferT< double > AlignedBuffer64
Definition simd_buffer.hpp:130
@ i
Definition formant_filter_bank.hpp:20
AlignedBufferT< float > AlignedBuffer
Definition simd_buffer.hpp:129
void pulp_aligned_free(void *p)
Definition simd_buffer.hpp:28
void * pulp_aligned_alloc(size_t alignment, size_t size)
Definition simd_buffer.hpp:27