arduino-audio-tools
BufferRTOS.h
1 #pragma once
2 #include "AudioConfig.h"
3 #include "AudioTools/CoreAudio/Buffers.h"
4 #include "AudioTools/CoreAudio/AudioLogger.h"
5 #include "AudioTools/CoreAudio/AudioBasic/Collections/Allocator.h"
6 
7 #ifdef ESP32
8 # include <freertos/stream_buffer.h>
9 # include "freertos/FreeRTOS.h"
10 #else
11 # include "FreeRTOS.h"
12 # include "stream_buffer.h"
13 #endif
14 
15 namespace audio_tools {
16 
17 // #if ESP_IDF_VERSION_MAJOR >= 4
18 
28 template <typename T>
29 class BufferRTOS : public BaseBuffer<T> {
30  public:
31  BufferRTOS(size_t streamBufferSize, size_t xTriggerLevel = 1,
32  TickType_t writeMaxWait = portMAX_DELAY,
33  TickType_t readMaxWait = portMAX_DELAY,
34  Allocator &allocator = DefaultAllocator)
35  : BaseBuffer<T>() {
36  readWait = readMaxWait;
37  writeWait = writeMaxWait;
38  current_size_bytes = (streamBufferSize+1) * sizeof(T);
39  trigger_level = xTriggerLevel;
40  p_allocator = &allocator;
41 
42  if (streamBufferSize > 0) {
43  setup();
44  }
45  }
46 
47  ~BufferRTOS() { end(); }
48 
50  bool resize(size_t size) {
51  bool result = true;
52  int req_size_bytes = (size + 1)*sizeof(T);
53  if (current_size_bytes != req_size_bytes) {
54  end();
55  current_size_bytes = req_size_bytes;
56  result = setup();
57  }
58  return result;
59  }
60 
61  void setReadMaxWait(TickType_t ticks) { readWait = ticks; }
62 
63  void setWriteMaxWait(TickType_t ticks) { writeWait = ticks; }
64 
65  void setWriteFromISR(bool active) { write_from_isr = active; }
66 
67  void setReadFromISR(bool active) { read_from_isr = active; }
68 
69  // reads a single value
70  T read() override {
71  T data = 0;
72  readArray(&data, sizeof(T));
73  return data;
74  }
75 
76  // reads multiple values
77  int readArray(T data[], int len) {
78  if (read_from_isr) {
79  xHigherPriorityTaskWoken = pdFALSE;
80  int result = xStreamBufferReceiveFromISR(xStreamBuffer, (void *)data,
81  sizeof(T) * len,
82  &xHigherPriorityTaskWoken);
83 #ifdef ESP32X
84  portYIELD_FROM_ISR();
85 #else
86  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
87 #endif
88  return result / sizeof(T);
89  } else {
90  return xStreamBufferReceive(xStreamBuffer, (void *)data, sizeof(T) * len,
91  readWait) / sizeof(T);
92  }
93  }
94 
95  int writeArray(const T data[], int len) {
96  LOGD("%s: %d", LOG_METHOD, len);
97  if (write_from_isr) {
98  xHigherPriorityTaskWoken = pdFALSE;
99  int result =
100  xStreamBufferSendFromISR(xStreamBuffer, (void *)data, sizeof(T) * len,
101  &xHigherPriorityTaskWoken);
102 #ifdef ESP32X
103  portYIELD_FROM_ISR();
104 #else
105  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
106 #endif
107  return result / sizeof(T);
108  } else {
109  return xStreamBufferSend(xStreamBuffer, (void *)data, sizeof(T) * len,
110  writeWait) / sizeof(T);
111  }
112  }
113 
114  // peeks the actual entry from the buffer
115  T peek() override {
116  LOGE("peek not implmented");
117  return 0;
118  }
119 
120  // checks if the buffer is full
121  bool isFull() override {
122  return xStreamBufferIsFull(xStreamBuffer) == pdTRUE;
123  }
124 
125  bool isEmpty() { return xStreamBufferIsEmpty(xStreamBuffer) == pdTRUE; }
126 
127  // write add an entry to the buffer
128  bool write(T data) override {
129  int len = sizeof(T);
130  return writeArray(&data, len) == len;
131  }
132 
133  // clears the buffer
134  void reset() override { xStreamBufferReset(xStreamBuffer); }
135 
136  // provides the number of entries that are available to read
137  int available() override {
138  return xStreamBufferBytesAvailable(xStreamBuffer) / sizeof(T);
139  }
140 
141  // provides the number of entries that are available to write
142  int availableForWrite() override {
143  return xStreamBufferSpacesAvailable(xStreamBuffer) / sizeof(T);
144  }
145 
146  // returns the address of the start of the physical read buffer
147  T *address() override {
148  LOGE("address() not implemented");
149  return nullptr;
150  }
151 
152  size_t size() { return current_size_bytes / sizeof(T); }
153 
154  protected:
155  StreamBufferHandle_t xStreamBuffer = nullptr;
156  StaticStreamBuffer_t static_stream_buffer;
157  uint8_t *p_data = nullptr;
158  Allocator *p_allocator = nullptr;
159  BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE.
160  int readWait = portMAX_DELAY;
161  int writeWait = portMAX_DELAY;
162  bool read_from_isr = false;
163  bool write_from_isr = false;
164  size_t current_size_bytes = 0;
165  size_t trigger_level = 0;
166 
169  bool setup() {
170  if (current_size_bytes == 0) return true;
171 
172  // allocate data if necessary
173  int size = (current_size_bytes + 1) * sizeof(T);
174  if (p_data == nullptr) {
175  p_data = (uint8_t *)p_allocator->allocate(size);
176  // check allocation
177  if (p_data == nullptr) {
178  LOGE("allocate falied for %d bytes", size)
179  return false;
180  }
181  }
182 
183 
184  // create stream buffer if necessary
185  if (xStreamBuffer == nullptr) {
186  xStreamBuffer = xStreamBufferCreateStatic(current_size_bytes, trigger_level,
187  p_data, &static_stream_buffer);
188  }
189  if (xStreamBuffer == nullptr) {
190  LOGE("xStreamBufferCreateStatic failed");
191  return false;
192  }
193  // make sure that the data is empty
194  reset();
195  return true;
196  }
197 
199  void end() {
200  if (xStreamBuffer != nullptr) vStreamBufferDelete(xStreamBuffer);
201  p_allocator->free(p_data);
202  current_size_bytes = 0;
203  p_data = nullptr;
204  xStreamBuffer = nullptr;
205  }
206 };
207 // #endif // ESP_IDF_VERSION_MAJOR >= 4
208 
209 template <class T>
210 using SynchronizedBufferRTOS = BufferRTOS<T>;
211 
212 } // namespace audio_tools
213 
Memory allocateator which uses malloc.
Definition: Allocator.h:22
Shared functionality of all buffers.
Definition: Buffers.h:30
Buffer implementation which is using a FreeRTOS StreamBuffer. The default allocator uses psram is ava...
Definition: BufferRTOS.h:29
T * address() override
returns the address of the start of the physical read buffer
Definition: BufferRTOS.h:147
T peek() override
peeks the actual entry from the buffer
Definition: BufferRTOS.h:115
bool write(T data) override
write add an entry to the buffer
Definition: BufferRTOS.h:128
int available() override
provides the number of entries that are available to read
Definition: BufferRTOS.h:137
int availableForWrite() override
provides the number of entries that are available to write
Definition: BufferRTOS.h:142
bool isFull() override
checks if the buffer is full
Definition: BufferRTOS.h:121
void end()
Release resurces: call resize to restart again.
Definition: BufferRTOS.h:199
int writeArray(const T data[], int len)
Fills the buffer data.
Definition: BufferRTOS.h:95
bool resize(size_t size)
Re-Allocats the memory and the queue.
Definition: BufferRTOS.h:50
void reset() override
clears the buffer
Definition: BufferRTOS.h:134
T read() override
reads a single value
Definition: BufferRTOS.h:70
bool setup()
Definition: BufferRTOS.h:169
int readArray(T data[], int len)
reads multiple values
Definition: BufferRTOS.h:77
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823