arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
BufferRP2040.h
1#pragma once
2
3#ifndef ARDUINO_ARCH_RP2040
4# error "Unsupported architecture"
5#endif
6
7#include "AudioToolsConfig.h"
8#include "AudioTools/CoreAudio/AudioLogger.h"
9#include "AudioTools/CoreAudio/Buffers.h"
10
11namespace audio_tools {
12
13// #if ESP_IDF_VERSION_MAJOR >= 4
14
30template <typename T>
31class BufferRP2040T : public BaseBuffer<T> {
32 public:
33 BufferRP2040T(int bufferCount) : BaseBuffer<T>() {
34 buffer_size = 1;
35 buffer_size_bytes = sizeof(T);
36 buffer_size_req_bytes = buffer_size_bytes * bufferCount;
37 }
38
39 BufferRP2040T(size_t bufferSize, int bufferCount) : BaseBuffer<T>() {
40 buffer_size = bufferSize;
41 buffer_size_bytes = bufferSize * sizeof(T);
42 buffer_size_req_bytes = buffer_size_bytes * bufferCount;
43 }
44
45 ~BufferRP2040T() { reset(); }
46
48 bool resize(size_t size) {
49 int req_bytes = size * sizeof(T);
50 if (buffer_size_alloc_bytes < req_bytes) {
51 LOGI("resize %d -> %d", buffer_size_alloc_bytes / sizeof(T), size);
52 assert(buffer_size_bytes > 0);
53 write_buffer.resize(buffer_size);
54 read_buffer.resize(buffer_size * 2);
55 // create new queu
56 if (req_bytes > buffer_size_alloc_bytes) {
57 // release existing queue
58 if (buffer_size_alloc_bytes > 0) {
59 queue_free(&queue);
60 }
61
62 int count = req_bytes / buffer_size_bytes;
63 LOGI("queue_init(size:%d, count:%d)", buffer_size_bytes, count);
64 queue_init(&queue, buffer_size_bytes, count);
65 buffer_size_alloc_bytes = req_bytes;
66 }
67 }
68 return true;
69 }
70
71 // reads a single value
72 bool read(T& data) {
73 return readArray(&data, 1)==1;
74 }
75
76
77 // peeks the actual entry from the buffer
78 bool peek(T &result) override {
79 LOGE("peek not implemented");
80 return false;
81 }
82
83 // reads multiple values
84 int readArray(T data[], int len) override {
85 LOGD("readArray: %d", len);
86 // handle unalloc;ated queue
87 if (buffer_size_alloc_bytes == 0) return 0;
88
89 // blocking read
90 while (is_blocking_read && read_buffer.available() + available() < len)
91 delay(1);
92
93 // fill read buffer if necessary
94 while (read_buffer.availableForWrite() >= buffer_size) {
95 LOGD("reading %d %d ", buffer_size, read_buffer.availableForWrite());
96 T tmp[buffer_size];
97 if (queue_try_remove(&queue, tmp)){
98 LOGD("queue_try_remove -> success");
99 read_buffer.writeArray(tmp, buffer_size);
100 } else {
101 LOGD("queue_try_remove -> failed");
102 break;
103 }
104 }
105 LOGD("read_buffer.available: %d, availableForWrite: %d ", read_buffer.available(), read_buffer.availableForWrite());
106 int result = read_buffer.readArray(data, len);
107 LOGD("=> readArray: %d -> %d", len, result);
108 return result;
109 }
110
111 int writeArray(const T data[], int len) override {
112 LOGD("writeArray: %d", len);
113 int result = 0;
114 // make sure that we have the data allocated
115 resize(buffer_size_req_bytes / sizeof(T));
116
117 if (is_blocking_write) {
118 result = writeBlocking(data, len);
119 } else {
120 result = writeNonBlocking(data, len);
121 }
122
123 return result;
124 }
125
126 // checks if the buffer is full
127 bool isFull() override {
128 if (buffer_size_alloc_bytes == 0) return false;
129 return queue_is_full(&queue);
130 }
131
132 bool isEmpty() {
133 if (buffer_size_alloc_bytes == 0) return true;
134 return queue_is_empty(&queue);
135 }
136
137 // write add an entry to the buffer
138 bool write(T data) override { return writeArray(&data, 1) == 1; }
139
140 // clears the buffer
141 void reset() override {
142 queue_free(&queue);
143 buffer_size_alloc_bytes = 0;
144 }
145
146 // provides the number of entries that are available to read
147 int available() override {
148 if (buffer_size_alloc_bytes == 0) return 0;
149 return (queue_get_level(&queue) * buffer_size);
150 }
151
152 // provides the number of entries that are available to write
153 int availableForWrite() override {
154 if (buffer_size_alloc_bytes == 0) return size();
155 return size() - available(); }
156
157 // returns the address of the start of the physical read buffer
158 T *address() override {
159 LOGE("address() not implemented");
160 return nullptr;
161 }
162
163 size_t size() { return buffer_size_alloc_bytes / sizeof(T); }
164
166 void setBlockingWrite(bool flag){
167 is_blocking_write = flag;
168 }
169
171 void setBlockingRead(bool flag){
172 is_blocking_read = flag;
173 }
174
175
176 protected:
177 queue_t queue;
178 int buffer_size_alloc_bytes = 0;
179 int buffer_size_req_bytes = 0;
180 int buffer_size_bytes = 0;
181 int buffer_size = 0;
182 SingleBuffer<T> write_buffer{0};
183 audio_tools::RingBuffer<T> read_buffer{0};
184 bool is_blocking_write = true;
185 bool is_blocking_read = false;
186
187 int writeBlocking(const T data[], int len) {
188 LOGD("writeArray: %d", len);
189
190 if (len > buffer_size_bytes){
191 LOGE("write %d too big for buffer_size: %d", len, buffer_size_bytes);
192 return 0;
193 }
194
195 // fill the write buffer and when it is full flush it to the queue
196 for (int j = 0; j < len; j++) {
197 write_buffer.write(data[j]);
198 if (write_buffer.isFull()) {
199 LOGD("queue_add_blocking");
200 queue_add_blocking(&queue, write_buffer.data());
201 write_buffer.reset();
202 }
203 }
204 return len;
205 }
206
207 int writeNonBlocking(const T data[], int len) {
208 if (len != buffer_size_bytes){
209 LOGE("write %d must be buffer_size: %d", len, buffer_size_bytes);
210 return 0;
211 }
212
213 if (queue_try_add(&queue, write_buffer.data())){
214 return len;
215 }
216 return 0;
217 }
218
219};
220
221using BufferRP2040 = BufferRP2040T<uint8_t>;
222
223} // namespace audio_tools
Shared functionality of all buffers.
Definition Buffers.h:26
Buffer implementation which is based on a RP2040 queue. This class is intended to be used to exchange...
Definition BufferRP2040.h:31
void setBlockingRead(bool flag)
When we use a blockingread, the we wait for the data to be available.
Definition BufferRP2040.h:171
void setBlockingWrite(bool flag)
When we use a non blocking write, the write size must be identical with the buffer size.
Definition BufferRP2040.h:166
bool peek(T &result) override
peeks the actual entry from the buffer
Definition BufferRP2040.h:78
bool write(T data) override
write add an entry to the buffer
Definition BufferRP2040.h:138
int available() override
provides the number of entries that are available to read
Definition BufferRP2040.h:147
bool read(T &data)
reads a single value
Definition BufferRP2040.h:72
int availableForWrite() override
provides the number of entries that are available to write
Definition BufferRP2040.h:153
T * address() override
returns the address of the start of the physical read buffer
Definition BufferRP2040.h:158
bool isFull() override
checks if the buffer is full
Definition BufferRP2040.h:127
int writeArray(const T data[], int len) override
Fills the buffer data.
Definition BufferRP2040.h:111
bool resize(size_t size)
Re-Allocats the memory and the queue (size is in entries)
Definition BufferRP2040.h:48
void reset() override
clears the buffer
Definition BufferRP2040.h:141
int readArray(T data[], int len) override
reads multiple values
Definition BufferRP2040.h:84
Implements a typed Ringbuffer.
Definition Buffers.h:308
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:175
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10