3#include "AudioTools/CoreAudio/AudioBasic/Collections.h"
4#include "AudioTools/CoreAudio/AudioBasic/Str.h"
5#include "AudioTools/CoreAudio/AudioLogger.h"
34 virtual bool read(T &result) = 0;
38 if (data ==
nullptr) {
43 for (
int j = 0; j < lenResult; j++) {
46 LOGD(
"readArray %d -> %d", len, lenResult);
64 for (
int j = 0; j < len; j++) {
65 if (!
write(data[j])) {
71 LOGD(
"writeArray %d -> %d", len, result);
85 virtual bool peek(T &result) = 0;
90 bool isEmpty() {
return available() == 0; }
110 virtual size_t size() = 0;
115 if (size() == 0)
return 0.0f;
116 return 100.0f *
static_cast<float>(
available()) /
117 static_cast<float>(size());
121 void setWritePos(
int pos) {};
135 LOGD(
"%s: %d", LOG_METHOD, len);
137 int result = min(len, p_buffer->available());
138 for (
int j = 0; j < result; j++) {
140 p_buffer->read(sample);
148 template <
int rows,
int channels>
150 int lenResult = min(rows, p_buffer->available());
151 for (
int j = 0; j < lenResult; j++) {
153 p_buffer->read(sample);
154 for (
int i = 0; i < channels; i++) {
163 BaseBuffer<T> *p_buffer =
nullptr;
194 this->owns_buffer =
false;
195 this->buffer = (uint8_t *)
data;
196 this->current_read_pos = 0;
197 this->current_write_pos = len;
202 if (current_write_pos < buffer.size()) {
203 buffer[current_write_pos++] = sample;
209 bool read(T &result)
override {
210 bool success =
false;
211 if (current_read_pos < current_write_pos) {
212 result = buffer[current_read_pos++];
218 bool peek(T &result)
override {
219 bool success =
false;
220 if (current_read_pos < current_write_pos) {
221 result = buffer[current_read_pos];
228 int result = current_write_pos - current_read_pos;
229 return max(result, 0);
241 return len_available;
243 current_read_pos += len;
244 len_available -= len;
245 memmove(buffer.data(), buffer.data() + current_read_pos, len_available);
246 current_read_pos = 0;
247 current_write_pos = len_available;
249 if (is_clear_with_zero) {
250 memset(buffer.data() + current_write_pos, 0,
251 buffer.size() - current_write_pos);
258 T *
address()
override {
return buffer.data(); }
261 T *
data() {
return buffer.data() + current_read_pos; }
264 current_read_pos = 0;
265 current_write_pos = 0;
266 if (is_clear_with_zero) {
267 memset(buffer.data(), 0, buffer.size());
274 size_t result = min(available_size, (
size_t)buffer.size());
275 current_read_pos = 0;
276 current_write_pos = result;
280 size_t size() {
return buffer.size(); }
282 void resize(
int size) {
283 if (buffer.size() != size) {
293 int current_read_pos = 0;
294 int current_write_pos = 0;
295 bool owns_buffer =
true;
296 bool is_clear_with_zero =
false;
299 void setWritePos(
int pos) { current_write_pos = pos; }
315 bool read(T &result)
override {
320 result = _aucBuffer[_iTail];
321 _iTail = nextIndex(_iTail);
328 bool peek(T &result)
override {
333 result = _aucBuffer[_iTail];
337 virtual int peekArray(T *data,
int n) {
338 if (isEmpty())
return -1;
340 int count = _numElems;
342 for (
int j = 0; j < n; j++) {
343 data[j] = _aucBuffer[tail];
344 tail = nextIndex(tail);
347 if (count == 0)
break;
355 bool isEmpty() {
return available() == 0; }
361 _aucBuffer[_iHead] = data;
362 _iHead = nextIndex(_iHead);
383 virtual T *
address() {
return _aucBuffer.data(); }
385 virtual void resize(
int len) {
386 if (max_size != len) {
387 LOGI(
"resize: %d", len);
388 _aucBuffer.resize(len);
394 virtual size_t size() {
return max_size; }
403 int nextIndex(
int index) {
return (uint32_t)(index + 1) % max_size; }
414template <
class File,
typename T>
423 if (p_file) p_file->close();
429 p_file = &bufferFile;
431 LOGE(
"file is not valid");
441 if (p_file ==
nullptr)
return 0;
442 int read_count = min(count,
available());
445 if (!
file_seek(offset.pos))
return false;
447 if (offset.len1 > 0) {
449 n +=
file_read(data + offset.len, offset.len1);
450 read_pos = offset.len1;
452 read_pos += read_count;
454 assert(n == read_count);
455 element_count -= read_count;
460 bool peek(T &result)
override {
461 if (p_file ==
nullptr || isEmpty()) {
472 if (p_file ==
nullptr)
return 0;
473 int read_count = min(count,
available());
476 if (!
file_seek(offset.pos))
return false;
478 if (offset.len1 > 0) {
480 n +=
file_read(data + offset.len, offset.len1);
482 assert(n == read_count);
491 if (p_file ==
nullptr)
return 0;
496 if (!
file_seek(offset.pos))
return false;
498 if (offset.len1 > 0) {
500 n +=
file_write(data + offset.len, offset.len1);
501 write_pos = offset.len1;
503 write_pos += write_count;
505 assert(n == write_count);
506 element_count += write_count;
513 bool isEmpty() {
return available() == 0; }
530 size_t size()
override {
return max_size; }
539 File *p_file =
nullptr;
542 int element_count = 0;
556 int overflow = (pos + len) - max_size;
563 result.len = len - overflow;
564 result.len1 = overflow;
571 int file_pos = pos *
sizeof(T);
572 if (p_file->position() != file_pos) {
573 LOGD(
"file_seek: %d", pos);
574 if (!p_file->seek(file_pos)) {
575 LOGE(
"seek %d", file_pos);
584 LOGD(
"file_write: %d", count);
585 if (p_file ==
nullptr)
return 0;
586 int to_write =
sizeof(T) * count;
587 int bytes_written = p_file->write((
const uint8_t *)data, to_write);
589 int elements_written = bytes_written /
sizeof(T);
590 if (bytes_written != to_write) {
591 LOGE(
"write: %d -> %d", to_write, bytes_written);
593 return elements_written;
598 LOGD(
"file_read: %d", count);
599 int read_bytes = count *
sizeof(T);
600 int result_bytes = p_file->readBytes((
char *)result, read_bytes);
601 int result_count = result_bytes /
sizeof(T);
602 if (result_count != count) {
603 LOGE(
"readBytes: %d -> %d", read_bytes, result_bytes);
619 NBuffer(
int size,
int count) { resize(size, count); }
621 virtual ~NBuffer() { freeMemory(); }
624 bool read(T &result)
override {
626 return actual_read_buffer->read(result);
630 bool peek(T &result)
override {
632 return actual_read_buffer->peek(result);
641 if (actual_write_buffer ==
nullptr) {
642 actual_write_buffer = getNextAvailableBuffer();
644 if (actual_write_buffer !=
nullptr) {
645 result = actual_write_buffer->write(data);
647 if (actual_write_buffer->isFull()) {
648 addFilledBuffer(actual_write_buffer);
649 actual_write_buffer = getNextAvailableBuffer();
655 if (start_time == 0l) {
658 if (result) sample_count++;
665 if (actual_read_buffer ==
nullptr) {
666 actual_read_buffer = getNextFilledBuffer();
668 if (actual_read_buffer ==
nullptr) {
671 int result = actual_read_buffer->available();
676 (actual_read_buffer ==
nullptr) ? 0 : actual_read_buffer->available();
683 if (actual_write_buffer ==
nullptr) {
684 actual_write_buffer = getNextAvailableBuffer();
687 if (actual_write_buffer ==
nullptr) {
691 if (actual_write_buffer->isFull()) {
694 addFilledBuffer(actual_write_buffer);
695 actual_write_buffer = getNextAvailableBuffer();
697 return actual_write_buffer->availableForWrite();
703 while (actual_read_buffer !=
nullptr) {
704 actual_read_buffer->reset();
705 addAvailableBuffer(actual_read_buffer);
707 actual_read_buffer = getNextFilledBuffer();
712 unsigned long sampleRate() {
713 unsigned long run_time = (
millis() - start_time);
714 return run_time == 0 ? 0 : sample_count * 1000 / run_time;
719 return actual_read_buffer ==
nullptr ? nullptr
720 : actual_read_buffer->address();
725 if (actual_write_buffer !=
nullptr) {
726 actual_write_buffer->setWritePos(buffer_size);
727 addFilledBuffer(actual_write_buffer);
729 actual_write_buffer = getNextAvailableBuffer();
730 return *actual_write_buffer;
735 BaseBuffer<T> &readEnd() {
738 return *actual_read_buffer;
741 virtual int bufferCountFilled() {
return filled_buffers.size(); }
743 virtual int bufferCountEmpty() {
return available_buffers.size(); }
745 virtual void resize(
int size,
int count) {
746 if (buffer_size == size && buffer_count == count)
return;
748 filled_buffers.resize(count);
749 available_buffers.resize(count);
753 buffer_count = count;
755 for (
int j = 0; j < count; j++) {
756 BaseBuffer<T> *buffer =
new SingleBuffer<T>(size);
757 LOGD(
"new buffer %p", buffer);
758 available_buffers.enqueue(buffer);
762 size_t size() {
return buffer_size * buffer_count; }
766 uint16_t buffer_count = 0;
767 BaseBuffer<T> *actual_read_buffer =
nullptr;
768 BaseBuffer<T> *actual_write_buffer =
nullptr;
769 QueueFromVector<BaseBuffer<T> *> available_buffers{0,
nullptr};
770 QueueFromVector<BaseBuffer<T> *> filled_buffers{0,
nullptr};
773 unsigned long start_time = 0;
774 unsigned long sample_count = 0;
780 if (actual_write_buffer) {
781 LOGD(
"deleting %p", actual_write_buffer);
782 delete actual_write_buffer;
783 actual_write_buffer =
nullptr;
785 if (actual_read_buffer) {
786 LOGD(
"deleting %p", actual_read_buffer);
787 delete actual_read_buffer;
788 actual_read_buffer =
nullptr;
791 BaseBuffer<T> *ptr = getNextAvailableBuffer();
792 while (ptr !=
nullptr) {
793 LOGD(
"deleting %p", ptr);
795 ptr = getNextAvailableBuffer();
798 ptr = getNextFilledBuffer();
799 while (ptr !=
nullptr) {
800 LOGD(
"deleting %p", ptr);
802 ptr = getNextFilledBuffer();
806 void resetCurrent() {
807 if (actual_read_buffer !=
nullptr) {
808 actual_read_buffer->reset();
809 addAvailableBuffer(actual_read_buffer);
812 actual_read_buffer = getNextFilledBuffer();
815 virtual BaseBuffer<T> *getNextAvailableBuffer() {
816 if (available_buffers.empty())
return nullptr;
817 BaseBuffer<T> *result =
nullptr;
818 available_buffers.dequeue(result);
822 virtual bool addAvailableBuffer(BaseBuffer<T> *buffer) {
823 return available_buffers.enqueue(buffer);
826 virtual BaseBuffer<T> *getNextFilledBuffer() {
827 if (filled_buffers.empty())
return nullptr;
828 BaseBuffer<T> *result =
nullptr;
829 filled_buffers.dequeue(result);
833 virtual bool addFilledBuffer(BaseBuffer<T> *buffer) {
834 return filled_buffers.enqueue(buffer);
847template <
class File,
typename T>
851 NBufferFile(
int fileSize) { number_of_objects_per_file = fileSize; }
857 next_file_name.
set(
"buffer-");
859 snprintf(number, 40,
"%d", file_count);
860 next_file_name.
add(number);
861 next_file_name.
add(
".tmp");
862 return next_file_name.
c_str();
868 if (!file)
return false;
869 empty_files.enqueue(file);
879 if (!filled_files.dequeue(read_file)) {
886 int result = read_file.readBytes((
char *)data, len *
sizeof(T)) /
sizeof(T);
891 empty_files.enqueue(read_file);
898 size_t pos = read_file.position();
899 bool result =
read(data);
907 if (!write_file || write_file.size() + len > number_of_objects_per_file) {
911 filled_files.enqueue(write_file);
914 if (!empty_files.dequeue(write_file))
return false;
916 int result = write_file.write((uint8_t *)data, len *
sizeof(T));
917 return result /
sizeof(T);
921 return filled_files.size() * number_of_objects_per_file +
922 (read_file.available() /
sizeof(T));
928 number_of_objects_per_file - (write_file.available() /
sizeof(T));
929 return empty_files.size() * number_of_objects_per_file +
930 write_file.available() + open_current;
933 size_t size()
override {
return number_of_objects_per_file * file_count; }
937 cleanupFile(read_file);
938 cleanupFile(write_file);
940 while (empty_files.dequeue(file)) cleanupFile(file);
941 while (filled_files.dequeue(file)) cleanupFile(file);
946 file_delete_callback = cb;
952 empty_files.enqueue(read_file);
957 empty_files.enqueue(write_file);
961 while (filled_files.dequeue(file)) {
963 empty_files.enqueue(file);
975 int number_of_objects_per_file = 0;
977 const uint16_t max_file_name = 256;
979 void (*file_delete_callback)(
const char *filename);
981 void cleanupFile(
File &file) {
984 int len = strlen(file.name());
985 char file_name[len + 1];
986 strncpy(file_name, file.name(), len);
988 file_delete_callback(file_name);
1001template <
typename T>
1005 LOGI(
"BufferedArray(%d)", len);
1010 int16_t *getValues(
size_t offset,
size_t length) {
1011 LOGD(
"getValues(%d,%d) - max %d", offset, length, array.size());
1015 actual_end = length;
1018 last_end = actual_end >= 0 ? actual_end : offset;
1020 actual_end = offset + length > actual_end ? offset + length : actual_end;
1022 int size = actual_end - last_end;
1024 LOGD(
"readBytes(%d,%d)", last_end, size);
1025 assert(last_end + size <= array.size());
1026 p_stream->readBytes((uint8_t *)(&array[last_end]), size * 2);
1028 assert(offset < actual_end);
1029 return &array[offset];
1033 int actual_end = -1;
1036 Stream *p_stream =
nullptr;